Skip to main content

Cross-Subdomain Consent

Configure consent sharing across multiple subdomains to provide seamless user experience and avoid repeated consent collection.

Cross-subdomain consent sharing is essential for organizations with multiple subdomains that need to share consent preferences without repeatedly asking users for the same permissions.

Common Use Cases

Multi-Service Architecture:

  • Main website: example.com
  • Blog: blog.example.com
  • Documentation: docs.example.com
  • Support: support.example.com
  • User dashboard: app.example.com

E-commerce Platforms:

  • Store: shop.example.com
  • Checkout: checkout.example.com
  • Account management: account.example.com
  • Customer service: help.example.com

International Sites:

  • Global: example.com
  • Regional: us.example.com, eu.example.com
  • Country-specific: de.example.com, fr.example.com

Development Environments:

  • Production: example.com
  • Staging: staging.example.com
  • Testing: test.example.com
  • Preview: preview.example.com

Improved User Experience:

  • Users consent once across all subdomains
  • Seamless navigation between services
  • Reduced consent fatigue
  • Consistent privacy experience

Business Benefits:

  • Higher consent rates due to reduced friction
  • Better analytics across entire ecosystem
  • Unified marketing attribution
  • Simplified compliance management

Technical Advantages:

  • Centralized consent management
  • Consistent tracking implementation
  • Reduced development complexity
  • Single source of truth for consent state

Technical Implementation

Storage Mechanisms

biskoui offers multiple storage mechanisms for cross-subdomain consent sharing, each with specific advantages and limitations.

The most reliable method using first-party cookies set on the parent domain.

How It Works:

// Set consent cookie on parent domain (.example.com)
document.cookie = "biskoui_consent=" + consentData + "; domain=.example.com; path=/; secure; samesite=lax";

// All subdomains can read this cookie:
// - blog.example.com
// - app.example.com
// - docs.example.com

Configuration:

{
"cross_subdomain": {
"method": "shared_cookie",
"parent_domain": ".example.com",
"cookie_name": "biskoui_consent",
"cookie_options": {
"secure": true,
"samesite": "lax",
"max_age": 31536000
}
}
}

Advantages:

  • ✅ Works reliably across all browsers
  • ✅ No additional network requests required
  • ✅ Immediate consent state availability
  • ✅ Compatible with CDNs and edge caching

Limitations:

  • ❌ Requires proper domain configuration
  • ❌ Subject to browser cookie policies
  • ❌ Limited storage size (4KB)

2. PostMessage Communication

Real-time communication between subdomains using cross-origin messaging.

Implementation:

// Parent domain (example.com) - consent manager
function shareConsent(consent) {
const subdomains = [
'https://blog.example.com',
'https://app.example.com',
'https://docs.example.com'
];

subdomains.forEach(origin => {
window.postMessage({
type: 'biskoui_consent_update',
consent: consent,
timestamp: Date.now()
}, origin);
});
}

// Subdomain (blog.example.com) - consent receiver
window.addEventListener('message', function(event) {
if (event.origin !== 'https://example.com') return;

if (event.data.type === 'biskoui_consent_update') {
window.biskoui.setConsent(event.data.consent);
}
});

Configuration:

{
"cross_subdomain": {
"method": "postmessage",
"hub_domain": "example.com",
"allowed_origins": [
"https://blog.example.com",
"https://app.example.com",
"https://docs.example.com"
]
}
}

Advantages:

  • ✅ Real-time consent synchronization
  • ✅ Works with strict cookie policies
  • ✅ Can handle complex consent objects
  • ✅ Secure origin validation

Limitations:

  • ❌ Requires all domains to be loaded simultaneously
  • ❌ More complex implementation
  • ❌ Potential performance impact

3. Centralized API Storage

Server-side consent storage with API-based retrieval.

Implementation:

// Store consent on server
async function storeConsent(userId, consent) {
await fetch('https://api.example.com/consent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
user_id: userId,
consent: consent,
domain: window.location.hostname
})
});
}

// Retrieve consent from server
async function getConsent(userId) {
const response = await fetch(`https://api.example.com/consent/${userId}`);
return await response.json();
}

Configuration:

{
"cross_subdomain": {
"method": "api_storage",
"api_endpoint": "https://api.example.com/consent",
"user_identification": "session_id",
"cache_duration": 3600
}
}

Advantages:

  • ✅ Works across completely different domains
  • ✅ Centralized audit trail
  • ✅ No browser storage limitations
  • ✅ Supports complex user identification

Limitations:

  • ❌ Requires server infrastructure
  • ❌ Network latency for consent retrieval
  • ❌ Additional privacy considerations
  • ❌ Dependency on API availability

Setup Configuration

Dashboard Configuration

  1. Enable Cross-Subdomain Consent:

    • Go to SettingsCross-Domain
    • Enable Cross-subdomain consent sharing
    • Select storage method
  2. Configure Parent Domain:

    • Enter parent domain (e.g., .example.com)
    • Verify domain ownership
    • Set cookie options
  3. Add Subdomains:

    • List all subdomains that should share consent
    • Configure individual subdomain settings
    • Test domain connectivity
  4. Sync Configuration:

    • Choose sync timing (immediate, delayed, manual)
    • Set conflict resolution rules
    • Configure fallback behavior

JavaScript Configuration

// Initialize biskoui with cross-subdomain settings
window.biskouiConfig = {
siteId: 'your-site-id',
crossSubdomain: {
enabled: true,
method: 'shared_cookie',
parentDomain: '.example.com',
subdomains: [
'blog.example.com',
'app.example.com',
'docs.example.com'
],
syncOnLoad: true,
syncOnChange: true
}
};

Domain Management

Domain Verification

Before enabling cross-subdomain consent, verify ownership of all domains:

DNS Verification

; Add TXT record to verify domain ownership
_biskoui-verification.example.com. IN TXT "verification-token-12345"

File-Based Verification

<!-- Place verification file at domain root -->
<!-- https://example.com/.well-known/biskoui-verification.txt -->
verification-token-12345

Meta Tag Verification

<!-- Add to <head> of main page -->
<meta name="biskoui-domain-verification" content="verification-token-12345">

Subdomain Hierarchy

Define clear subdomain relationships and consent inheritance:

{
"domain_hierarchy": {
"example.com": {
"role": "parent",
"consent_authority": true,
"children": [
{
"domain": "blog.example.com",
"inherit_consent": true,
"override_allowed": false
},
{
"domain": "app.example.com",
"inherit_consent": true,
"override_allowed": true,
"custom_categories": ["advanced_analytics"]
}
]
}
}
}

Domain-Specific Settings

Configure different settings for individual subdomains:

{
"subdomain_config": {
"blog.example.com": {
"banner_style": "minimal",
"required_categories": ["analytics"],
"auto_consent": {
"functional": true,
"analytics": false
}
},
"app.example.com": {
"banner_style": "detailed",
"required_categories": ["analytics", "functional"],
"progressive_consent": true
},
"docs.example.com": {
"banner_style": "bottom_bar",
"required_categories": ["functional"],
"minimal_consent": true
}
}
}

Synchronization Strategies

Immediate Synchronization

Real-time consent updates across all subdomains:

// Sync consent immediately when changed
document.addEventListener('biskoui:consent:given', function(event) {
syncConsentAcrossSubdomains(event.detail.consent);
});

function syncConsentAcrossSubdomains(consent) {
// Update shared cookie
document.cookie = `biskoui_consent=${JSON.stringify(consent)}; domain=.example.com; path=/`;

// Notify other subdomains via postMessage
broadcast('consent_updated', consent);

// Update centralized storage
updateConsentAPI(consent);
}

Batched Synchronization

Group multiple consent changes and sync periodically:

let pendingConsentUpdates = [];
let syncTimer;

function queueConsentUpdate(consent) {
pendingConsentUpdates.push({
consent: consent,
timestamp: Date.now()
});

// Debounce sync to avoid excessive updates
clearTimeout(syncTimer);
syncTimer = setTimeout(syncBatchedConsent, 1000);
}

function syncBatchedConsent() {
if (pendingConsentUpdates.length === 0) return;

// Get most recent consent state
const latestConsent = pendingConsentUpdates[pendingConsentUpdates.length - 1];

// Sync across subdomains
syncConsentAcrossSubdomains(latestConsent.consent);

// Clear pending updates
pendingConsentUpdates = [];
}

Conflict Resolution

Handle conflicting consent states across subdomains:

function resolveConsentConflict(localConsent, remoteConsent) {
// Strategy 1: Most recent wins
if (remoteConsent.timestamp > localConsent.timestamp) {
return remoteConsent;
}

// Strategy 2: Most permissive wins
const resolvedConsent = {
essential: localConsent.essential || remoteConsent.essential,
analytics: localConsent.analytics || remoteConsent.analytics,
marketing: localConsent.marketing || remoteConsent.marketing,
timestamp: Math.max(localConsent.timestamp, remoteConsent.timestamp)
};

return resolvedConsent;
}

Security Considerations

Domain Validation

Ensure consent is only shared with legitimate subdomains:

function validateDomain(domain) {
const allowedSubdomains = [
'blog.example.com',
'app.example.com',
'docs.example.com'
];

// Check exact match
if (allowedSubdomains.includes(domain)) {
return true;
}

// Check wildcard patterns
const wildcardPatterns = [
/^[a-z0-9-]+\.example\.com$/,
/^staging-[a-z0-9-]+\.example\.com$/
];

return wildcardPatterns.some(pattern => pattern.test(domain));
}

Message Origin Verification

Validate postMessage origins to prevent XSS attacks:

window.addEventListener('message', function(event) {
// Verify origin matches expected domains
const allowedOrigins = [
'https://example.com',
'https://blog.example.com',
'https://app.example.com'
];

if (!allowedOrigins.includes(event.origin)) {
console.warn('Rejected consent message from unauthorized origin:', event.origin);
return;
}

// Verify message structure
if (!event.data || event.data.type !== 'biskoui_consent_update') {
return;
}

// Process consent update
processConsentUpdate(event.data.consent);
});

Implement secure cookie handling for cross-subdomain storage:

function setSecureConsentCookie(consent) {
const cookieValue = JSON.stringify(consent);
const options = [
`domain=.example.com`,
`path=/`,
`max-age=31536000`, // 1 year
`secure`, // HTTPS only
`samesite=lax`, // CSRF protection
`httponly=false` // JavaScript access needed
];

document.cookie = `biskoui_consent=${cookieValue}; ${options.join('; ')}`;
}

Testing Cross-Subdomain Setup

Local Development Testing

Set up local testing environment with multiple subdomains:

# /etc/hosts configuration for local testing
127.0.0.1 example.local
127.0.0.1 blog.example.local
127.0.0.1 app.example.local
127.0.0.1 docs.example.local
// Development configuration
const isDevelopment = window.location.hostname.includes('.local');

window.biskouiConfig = {
siteId: isDevelopment ? 'dev-site-id' : 'prod-site-id',
crossSubdomain: {
enabled: true,
parentDomain: isDevelopment ? '.example.local' : '.example.com',
// ... other settings
}
};

Testing Checklist

Functional Testing:

  • Consent set on parent domain appears on subdomains
  • Consent changes on subdomain sync to other subdomains
  • Fallback behavior works when sync fails
  • New subdomains automatically inherit consent

Security Testing:

  • Unauthorized domains cannot access consent data
  • PostMessage origin validation works correctly
  • Cookie domain restrictions are enforced
  • No consent leakage to external domains

Performance Testing:

  • Sync operations don't significantly impact page load
  • Large consent objects don't cause issues
  • Multiple rapid changes are handled gracefully
  • Timeout and retry logic works as expected

Automated Testing

// Automated cross-subdomain consent testing
describe('Cross-Subdomain Consent', () => {
test('should sync consent across subdomains', async () => {
// Set consent on parent domain
await setConsent('example.com', {
analytics: true,
marketing: false
});

// Wait for sync
await new Promise(resolve => setTimeout(resolve, 100));

// Check consent on subdomain
const subdomainConsent = await getConsent('blog.example.com');
expect(subdomainConsent.analytics).toBe(true);
expect(subdomainConsent.marketing).toBe(false);
});

test('should handle conflict resolution', async () => {
// Create conflicting consent states
await setConsent('example.com', { analytics: true });
await setConsent('app.example.com', { analytics: false });

// Trigger sync and conflict resolution
await syncConsent();

// Verify resolution (most recent should win)
const resolvedConsent = await getConsent('example.com');
expect(resolvedConsent.analytics).toBe(false);
});
});

Troubleshooting

Common Issues

Consent Not Syncing:

  1. Verify domain configuration in dashboard
  2. Check cookie domain settings
  3. Confirm subdomain accessibility
  4. Review browser console for errors

Cookie Issues:

  1. Ensure HTTPS for secure cookies
  2. Check SameSite policy compatibility
  3. Verify domain starts with dot (.example.com)
  4. Test cookie size limits

PostMessage Failures:

  1. Verify origin allowlists are correct
  2. Check for content security policy blocks
  3. Ensure event listeners are properly registered
  4. Test cross-origin communication manually

Debug Tools

Enable debug mode for detailed logging:

window.biskouiConfig = {
debug: true,
crossSubdomain: {
debug: true,
logLevel: 'verbose'
}
};

// Monitor consent sync events
document.addEventListener('biskoui:cross_subdomain:sync', function(event) {
console.log('Consent synced:', event.detail);
});

document.addEventListener('biskoui:cross_subdomain:error', function(event) {
console.error('Sync error:', event.detail);
});

Best Practices

Implementation Guidelines

  1. Start Simple: Begin with shared cookie method before trying complex approaches
  2. Test Thoroughly: Verify behavior across all target subdomains and browsers
  3. Plan for Failures: Implement fallback behavior when sync fails
  4. Monitor Performance: Track impact on page load and user experience
  5. Security First: Always validate origins and implement proper access controls

Maintenance Recommendations

  1. Regular Testing: Periodically test sync behavior across all subdomains
  2. Monitor Logs: Watch for sync errors and user consent patterns
  3. Update Documentation: Keep subdomain lists current as infrastructure changes
  4. Performance Monitoring: Track consent sync impact on site performance
  5. Security Audits: Regularly review domain access and origin validation

Next Steps

After configuring cross-subdomain consent:

  1. Set up consent registry and logging
  2. Configure consent mode for analytics
  3. Test implementation thoroughly
  4. Monitor performance impact