🔌 Duda Integration
🎯 Overview
The Duda integration provides comprehensive website builder capabilities through Duda's REST API. This integration enables DashClicks users to create, manage, and publish professional websites using Duda's platform.
Provider: Duda (https://www.duda.co)
API Version: Multiscreen API
Integration Type: REST API with Basic Authentication
Use Case: Website building and management for agencies and clients
📁 Directory Structure
Documentation Structure:
duda/
├── 📄 index.md - Integration overview (this file)
├── 📄 sites.md - Site CRUD, publishing, analytics
├── 📄 accounts.md - Account management and SSO
├── 📄 content.md - Content operations and uploads
└── 📄 webhooks.md - Webhook event handling
Source Code Location:
- Base Path:
external/Integrations/Duda/ - Services:
services/ - Controllers:
controllers/ - Utils:
utils/
🗄️ MongoDB Collections
📚 Detailed Schema: See Database Collections Documentation
config
- Purpose: Store Duda API credentials (username/password)
- Model:
external/models/config.js - Primary Use: Authentication for Duda API calls
agency-website
- Purpose: Store DashClicks agency website data
- Model:
external/models/agency-website.js - Primary Use: Track published Duda sites, sync status
instasite
- Purpose: Store Instasite (instant website) data
- Model:
external/models/instasite.js - Primary Use: Quick-start website templates
user-config
- Purpose: User notification preferences
- Model:
external/models/user-config.js - Primary Use: Webhook notification settings
🔐 Authentication & Configuration
Authentication Method: Basic Authentication (username:password Base64-encoded)
Required Environment Variables:
| Variable | Description | Required |
|---|---|---|
DUDA_SITES_DOMAIN | Duda API base URL | ✅ |
DUDA_TOKEN | Default Duda config ID | ✅ |
GOOGLE_CLOUD_PROJECT_ID | For thumbnail generation | ✅ |
Credential Storage:
- API credentials stored in
configcollection - Retrieved by config ID (
dudaHeaderparameter) - Encoded to Base64 before each API call
Authentication Flow:
// 1. Fetch credentials from database
const query = await Config.findById(dudaHeader);
// 2. Encode to Base64
const access_token = utils.base64(query); // Encodes username:password
// 3. Add to request header
headers: {
authorization: `Basic ${access_token}`;
}
🏗️ Architecture Overview
Key Responsibilities:
- Create and manage Duda websites for client accounts
- Publish/unpublish sites with thumbnail generation
- Manage site content and uploaded resources
- Handle SSO (Single Sign-On) for Duda editor access
- Process Duda webhooks for publish/unpublish events
- Sync site status with DashClicks database
API Communication Pattern:
- RESTful HTTP/HTTPS API
- Synchronous request/response
- Webhook-based event notifications
Rate Limiting:
- Duda enforces rate limits (varies by plan)
- No explicit rate limiting in integration code
🔗 Features & Capabilities
Core Features
- 📘 Sites Management - Site CRUD, publishing, analytics, form data
- 📗 Account Management - Duda account creation, SSO links, site access
- 📙 Content Operations - Site content, resource uploads, publishing
- 📕 Webhook Handling - Publish/unpublish event processing
🔄 Integration Data Flow
Typical Site Creation Flow
sequenceDiagram
participant DC as DashClicks
participant DudaService as Duda Service
participant ConfigDB as Config DB
participant DudaAPI as Duda API
DC->>DudaService: Create site request
DudaService->>ConfigDB: Fetch API credentials
ConfigDB-->>DudaService: Return username/password
DudaService->>DudaService: Encode to Base64
DudaService->>DudaAPI: POST /sites/multiscreen/create
Note over DudaService,DudaAPI: Authorization: Basic {token}
DudaAPI-->>DudaService: Site created
DudaService-->>DC: Return site details
Webhook Event Processing
sequenceDiagram
participant Duda as Duda Platform
participant WebhookService as Webhook Service
participant DB as Database
participant PubSub as Google PubSub
participant FCM as Notifications
Duda->>WebhookService: Webhook: site.published
WebhookService->>DB: Find site by builder_id
WebhookService->>Duda: Fetch updated site details
Duda-->>WebhookService: Site + content data
WebhookService->>DB: Update site status
WebhookService->>DB: Delete old thumbnails
WebhookService->>PubSub: Trigger thumbnail generation
PubSub-->>WebhookService: Job queued
WebhookService-->>Duda: 200 OK
Note over Duda,FCM: For unpublish events
WebhookService->>FCM: Send notification to user
🚨 Error Handling
Common Error Scenarios:
- 404 Not Found: API credentials not in Config collection
- 400 Bad Request: Invalid request body or missing required fields
- 401 Unauthorized: Invalid Duda credentials (wrong username/password)
- 404 Duda Site Not Found: Site doesn't exist in Duda system
- 500 Server Error: Duda API downtime or internal errors
Error Handling Pattern:
try {
const response = await axios(options);
return response.data;
} catch (error) {
// Axios automatically throws for 4xx/5xx
if (error.response?.data) {
throw badRequest(error.response.data.message);
}
throw error;
}
📊 Monitoring & Logging
Webhook Processing:
- Logs webhook events with logger utility
- Tracks thumbnail generation failures
- Monitors notification delivery failures
Error Logging:
logger.error({
initiator: 'external/Integrations/Duda',
error: err,
message: 'Failed to send site unpublished notification.',
});
🔗 Submodules
Service Files
📘 Sites Service
File: services/sites.service.js
Functions: 11 functions for site management
Core capabilities:
getSites()- List sites by accountgetSite()- Get single site detailscreateSite()- Create new websitedeleteSites()- Delete siteupdateSites()- Update site configpublishSites()- Publish site liveunpublishSites()- Take site offlinegetTemplate()- Get template infogetAnalytics()- Retrieve site analyticsgetFormData()- Get form submissionssetSitesPlan()- Update site plan
📗 Accounts Service
File: services/accounts.service.js
Functions: 3 functions for account management
Core capabilities:
createAccount()- Create Duda sub-accountgrantSiteAccess()- Grant site permissions to accountgetSSOLink()- Generate SSO link for editor access
📙 Content Service
File: services/content.service.js
Functions: 4 functions for content operations
Core capabilities:
getContent()- Retrieve site contentupdateContent()- Update site contentpublishContent()- Publish content changesuploadedResources()- Upload images/files
📕 Webhook Service
File: services/webhook.service.js
Functions: 2 functions for webhook processing
Core capabilities:
publish()- Handle site.published eventunpublish()- Handle site.unpublished event
🔐 Security Considerations
- Credential Storage: Duda credentials stored encrypted in Config collection
- Basic Auth: Always use HTTPS to protect Base64-encoded credentials
- Webhook Verification: Consider adding webhook signature verification
- External UID: DashClicks account_id tracked in Duda's external_uid field
- SSO Links: SSO links are time-limited (check Duda documentation)
🚀 Quick Start
Creating a Website
const sitesService = require('./services/sites.service');
// 1. Create site
const site = await sitesService.createSite(
dudaConfigId,
{
template_id: 'template_123',
default_domain_prefix: 'mybusiness',
site_data: {
site_business_info: {
business_name: 'My Business',
phone: '555-0100',
},
},
},
accountId,
);
// 2. Update content
await contentService.updateContent(
dudaConfigId,
{
location_data: {
phones: [{ phoneNumber: '555-0100' }],
emails: ['contact@mybusiness.com'],
},
},
site.site_name,
);
// 3. Publish site
await sitesService.publishSites(dudaConfigId, site.site_name);
Setting Up SSO
const accountsService = require('./services/accounts.service');
// 1. Create Duda account
await accountsService.createAccount(dudaConfigId, 'client-account-name');
// 2. Grant site access
await accountsService.grantSiteAccess(dudaConfigId, {
siteName: 'site_123',
accountName: 'client-account-name',
permissions: ['EDIT', 'PUBLISH'],
});
// 3. Generate SSO link
const ssoData = await accountsService.getSSOLink(dudaConfigId, 'client-account-name', {
target: 'EDITOR',
site_name: 'site_123',
});
// Redirect user to ssoData.url
⚠️ Important Notes
- External UID Tracking: Always set
external_uidinsite_datato track ownership - Base64 Encoding: Credentials must be Base64-encoded username:password for each request
- Webhook Processing: Publish webhooks trigger thumbnail generation via Google PubSub
- Site Status Sync: Webhooks keep DashClicks database in sync with Duda site status
- Thumbnail Management: Old thumbnails deleted from Wasabi when site republished
- Notification Preferences: Unpublish events respect user notification settings
- Site Types: Integration handles both agency-websites and instasites
- Content Publishing: Content changes require explicit publish call
- Analytics Date Range: Analytics API requires
fromandtodate parameters - Plan Management: Site plans affect available features and functionality
🔗 Related Documentation
- Duda Official API: https://developer.duda.co
- Sites Service: Detailed sites.md documentation
- Accounts Service: Detailed accounts.md documentation
- Content Service: Detailed content.md documentation
- Webhooks Service: Detailed webhooks.md documentation
- Config Model:
external/models/config.js - Agency Website Model:
external/models/agency-website.js