Domains Controller
Path: internal/api/v1/funnels/controllers/domains.controller.js
Service: domainsService
Module: Funnels
Overview
The Domains controller manages custom domain configuration for funnels. It handles domain routing, SSL settings, and domain-to-funnel mappings to enable funnels to be served on custom domains.
Key Capabilities
- Domain Routes: View all funnels using a specific domain
- Domain Updates: Configure domain settings and SSL
- Route Mapping: Manage which funnels are accessible via domain
- SSL Configuration: Enable/disable SSL for custom domains
Methods
getDomainRoutesById()
Retrieves all funnel routes configured for a specific domain.
Route: GET /v1/funnels/domains/:domain_id/routes
Auth: Required (account-scoped)
Request Parameters
{
domain_id: string; // Domain ID (MongoDB ObjectId)
}
Response
{
"success": true,
"message": "SUCCESS",
"data": {
"domain": {
"_id": "60d5ec49f1b2c72e8c8e4b1b",
"name": "example.com",
"ssl_enabled": true,
"ssl_status": "active",
"verified": true,
"account_id": "60d5ec49f1b2c72e8c8e4b19"
},
"routes": [
{
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"funnel_name": "Lead Generation Funnel",
"base_path": "/landing",
"full_url": "https://example.com/landing",
"status": "active",
"steps": [
{
"step_id": "60d5ec49f1b2c72e8c8e4b1d",
"step_name": "Home Page",
"path": "/",
"full_url": "https://example.com/landing/"
},
{
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"step_name": "Thank You",
"path": "/thank-you",
"full_url": "https://example.com/landing/thank-you"
}
]
},
{
"funnel_id": "60d5ec49f1b2c72e8c8e4b20",
"funnel_name": "Product Launch",
"base_path": "/launch",
"full_url": "https://example.com/launch",
"status": "active",
"steps": [
{
"step_id": "60d5ec49f1b2c72e8c8e4b21",
"step_name": "Launch Page",
"path": "/",
"full_url": "https://example.com/launch/"
}
]
}
],
"total_funnels": 2,
"total_routes": 3
}
}
MongoDB Collections
| Collection | Operation | Purpose |
|---|---|---|
funnel_domains | findOne | Retrieve domain details |
funnels | find | Find funnels using this domain |
funnel_steps | lookup | Join step details for each funnel |
Business Logic
- Filters funnels by
domain_idandaccount_id - Constructs full URLs from domain + base_path + step_path
- Includes SSL protocol (https) if
ssl_enabled: true - Excludes deleted or inactive funnels
updateDomain()
Updates domain configuration and settings.
Route: PUT /v1/funnels/domains/:domain_id
Auth: Required (account-scoped)
Request Parameters
{
domain_id: string; // Domain ID (MongoDB ObjectId)
}
Request Body
{
"domainInfo": {
"name": "example.com",
"ssl_enabled": true,
"ssl_certificate": {
"provider": "letsencrypt",
"issued_at": "2024-01-01T00:00:00Z",
"expires_at": "2024-04-01T00:00:00Z"
},
"dns_records": [
{
"type": "A",
"name": "@",
"value": "192.0.2.1",
"status": "active"
},
{
"type": "CNAME",
"name": "www",
"value": "example.com",
"status": "active"
}
],
"cloudflare_zone_id": "abc123def456",
"default_funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"redirect_www": true,
"force_https": true
}
}
Response
{
"success": true,
"message": "SUCCESS",
"data": {
"_id": "60d5ec49f1b2c72e8c8e4b1b",
"account_id": "60d5ec49f1b2c72e8c8e4b19",
"name": "example.com",
"ssl_enabled": true,
"ssl_status": "active",
"ssl_certificate": {
"provider": "letsencrypt",
"issued_at": "2024-01-01T00:00:00Z",
"expires_at": "2024-04-01T00:00:00Z"
},
"verified": true,
"verification_code": "dc-verify-abc123",
"dns_records": [
{
"type": "A",
"name": "@",
"value": "192.0.2.1",
"status": "active"
},
{
"type": "CNAME",
"name": "www",
"value": "example.com",
"status": "active"
}
],
"cloudflare_zone_id": "abc123def456",
"default_funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"redirect_www": true,
"force_https": true,
"updated_at": "2024-01-22T17:00:00Z"
}
}
MongoDB Collections
| Collection | Operation | Purpose |
|---|---|---|
funnel_domains | findOneAndUpdate | Update domain document |
cloudflare_zones | update (if applicable) | Sync Cloudflare settings |
Validations
- Domain name: Valid FQDN format
- SSL certificate: Valid date range
- DNS records: Valid record types (A, AAAA, CNAME, TXT)
- Cloudflare zone: Valid zone ID format
Data Models
Domain Document
{
_id: ObjectId;
account_id: ObjectId; // Owner account
name: string; // Domain name (e.g., "example.com")
// SSL Configuration
ssl_enabled: boolean;
ssl_status?: 'active' | 'pending' | 'failed' | 'expired';
ssl_certificate?: {
provider: 'letsencrypt' | 'custom' | 'cloudflare';
issued_at: Date;
expires_at: Date;
auto_renew?: boolean;
};
// Verification
verified: boolean;
verification_code?: string; // Code for domain ownership verification
verification_method?: 'dns' | 'file';
verified_at?: Date;
// DNS Configuration
dns_records?: Array<{
type: 'A' | 'AAAA' | 'CNAME' | 'TXT';
name: string; // Record name (@ for root, www, etc.)
value: string; // Record value (IP, domain, text)
status: 'active' | 'pending' | 'failed';
ttl?: number; // Time to live (seconds)
}>;
// Cloudflare Integration
cloudflare_zone_id?: string; // Cloudflare zone identifier
cloudflare_enabled?: boolean; // Use Cloudflare CDN
// Routing
default_funnel_id?: ObjectId; // Default funnel for root path
redirect_www: boolean; // Redirect www to non-www (or vice versa)
force_https: boolean; // Redirect HTTP to HTTPS
// Status
status: 'active' | 'inactive' | 'pending_verification';
created_at: Date;
updated_at: Date;
}
Business Logic & Workflows
Domain Setup Flow
sequenceDiagram
participant User
participant Domains
participant DNS
participant SSL
participant Cloudflare
User->>Domains: POST /domains (create domain)
Domains->>Domains: Generate verification code
Domains-->>User: Domain created (pending verification)
User->>DNS: Add DNS records
DNS-->>Domains: DNS propagation
User->>Domains: POST /domains/:id/verify
Domains->>DNS: Check DNS records
alt DNS Verified
DNS-->>Domains: Records found
Domains->>SSL: Request SSL certificate
SSL->>Cloudflare: Provision certificate
Cloudflare-->>SSL: Certificate issued
SSL-->>Domains: SSL active
Domains-->>User: Domain verified + SSL active
else DNS Not Found
DNS-->>Domains: Records missing
Domains-->>User: Verification failed
end
Funnel-Domain Mapping Flow
sequenceDiagram
participant User
participant Funnels
participant Domains
participant Cache
User->>Funnels: PUT /funnels/:id (set domain_id)
Funnels->>Domains: Check domain ownership
alt Domain Owned by Account
Domains-->>Funnels: Domain verified
Funnels->>Funnels: Update funnel.domain_id
Funnels->>Domains: Add route mapping
Funnels->>Cache: Purge domain cache
Funnels-->>User: Funnel updated
else Domain Not Owned
Domains-->>Funnels: Unauthorized
Funnels-->>User: 403 Forbidden
end
SSL Certificate Renewal Flow
sequenceDiagram
participant Cron
participant Domains
participant SSL
participant Cloudflare
participant Notification
Cron->>Domains: Check expiring certificates
Domains->>Domains: Find certs expiring in 30 days
loop For each expiring cert
Domains->>SSL: Request renewal
SSL->>Cloudflare: Renew certificate
alt Renewal Successful
Cloudflare-->>SSL: New certificate
SSL-->>Domains: Update certificate
Domains->>Notification: Success notification
else Renewal Failed
Cloudflare-->>SSL: Error
SSL-->>Domains: Mark as failed
Domains->>Notification: Alert admin
end
end
Integration Points
Cloudflare
- Purpose: CDN, SSL provisioning, DNS management
- Integration:
cloudflare_zone_idlinks to Cloudflare account - Features: Auto SSL, caching, DDoS protection
DNS Providers
- Purpose: Domain name resolution
- Supported: Cloudflare, AWS Route53, custom
- Verification: TXT record or file-based verification
SSL Certificate Providers
- Let's Encrypt: Free auto-renewing certificates
- Cloudflare SSL: Managed by Cloudflare
- Custom: User-uploaded certificates
Performance Considerations
Route Caching
- Domain routes cached for 5 minutes
- Cache invalidated on domain/funnel updates
- Cloudflare edge caching for maximum performance
DNS Propagation
- Verification checks use DNS resolver with 5-second timeout
- Retry logic for transient DNS failures
- TTL honored for cached DNS results
Query Optimization
- Indexed fields:
account_id,name,verified,status - Compound indexes:
(account_id, verified),(name, verified)
Security
Multi-Tenant Isolation
- All domain queries filtered by
account_id - Domain ownership verified before any updates
- Route listings only show account's funnels
Domain Verification
- DNS verification: TXT record with unique code
- File verification: Place file at
/.well-known/dashclicks-verify.txt - Prevents takeover: Must verify ownership before SSL/routing
SSL Security
- Force HTTPS: Redirects all HTTP to HTTPS
- Auto-renewal: Prevents certificate expiration
- Certificate validation: Verifies certificate chain
Error Handling
Common Errors
// Domain not found
{
"success": false,
"message": "Domain not found",
"statusCode": 404
}
// Domain not verified
{
"success": false,
"message": "Domain must be verified before use",
"statusCode": 403
}
// SSL provisioning failed
{
"success": false,
"message": "SSL certificate provisioning failed",
"data": {
"reason": "DNS records not configured correctly"
},
"statusCode": 500
}
// Domain already in use
{
"success": false,
"message": "Domain already connected to another account",
"statusCode": 409
}
// Invalid DNS record
{
"success": false,
"message": "Invalid DNS record format",
"data": {
"field": "dns_records[0].value",
"error": "Invalid IP address"
},
"statusCode": 400
}
Best Practices
When to Use This Controller
- ✅ Setting up custom domains for funnels
- ✅ Managing SSL certificates
- ✅ Configuring DNS records
- ✅ Viewing domain route mappings
Common Patterns
- Verify before use: Always verify domain ownership before allowing funnel connections
- Auto-renew SSL: Enable auto-renewal for all Let's Encrypt certificates
- Force HTTPS: Enable for all production domains
- Cache routes: Cache domain routes to reduce database queries
Edge Cases
- Subdomain conflicts: Multiple funnels cannot share exact same path on subdomain
- Wildcard domains: Not supported (each subdomain must be configured separately)
- Certificate limits: Let's Encrypt rate limits (50 certs per domain per week)
- DNS propagation delays: Verification may take up to 48 hours
Domain Verification Methods
DNS TXT Record Verification
Steps:
- Generate verification code:
dc-verify-{random} - User adds TXT record:
_dashclicks-verify.example.com→dc-verify-abc123 - System checks DNS for TXT record
- Domain verified if code matches
Advantages:
- Most secure method
- Industry standard
- Works for all domain types
File-Based Verification
Steps:
- Generate verification code:
dc-verify-{random} - User places file at:
https://example.com/.well-known/dashclicks-verify.txt - System fetches file via HTTP
- Domain verified if code matches
Advantages:
- No DNS access required
- Instant verification
- Works for existing websites
SSL Configuration
Auto SSL (Let's Encrypt)
{
"ssl_enabled": true,
"ssl_certificate": {
"provider": "letsencrypt",
"auto_renew": true
}
}
Features:
- Free certificates
- Auto-renewal 30 days before expiry
- Supports wildcard certificates (*.example.com)
Cloudflare SSL
{
"ssl_enabled": true,
"ssl_certificate": {
"provider": "cloudflare"
},
"cloudflare_enabled": true
}
Features:
- Managed by Cloudflare
- Universal SSL (automatic)
- No renewal management needed
Custom SSL
{
"ssl_enabled": true,
"ssl_certificate": {
"provider": "custom",
"certificate": "-----BEGIN CERTIFICATE-----...",
"private_key": "-----BEGIN PRIVATE KEY-----...",
"chain": "-----BEGIN CERTIFICATE-----..."
}
}
Features:
- User-provided certificates
- Manual renewal required
- Supports EV/OV certificates
DNS Record Configuration
Required A Records
{
"dns_records": [
{
"type": "A",
"name": "@",
"value": "192.0.2.1",
"ttl": 3600
}
]
}
Purpose: Point domain to DashClicks server
WWW Redirect
{
"dns_records": [
{
"type": "CNAME",
"name": "www",
"value": "example.com",
"ttl": 3600
}
],
"redirect_www": true
}
Purpose: Redirect www.example.com to example.com (or vice versa)
Cloudflare Proxied
{
"dns_records": [
{
"type": "A",
"name": "@",
"value": "192.0.2.1",
"ttl": 1,
"proxied": true
}
],
"cloudflare_enabled": true
}
Purpose: Route traffic through Cloudflare CDN
Related Documentation
- Funnels Controller: Connecting funnels to domains
- Cloudflare Integration: CDN and SSL management
- DNS Configuration: Domain setup guide
- SSL Certificates: Certificate provisioning and renewal
Last Updated: January 2025
API Version: v1
Maintained By: DashClicks Engineering