Cross-Subdomain Consent
Configure consent sharing across multiple subdomains to provide seamless user experience and avoid repeated consent collection.
When Cross-Subdomain Consent is Needed
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
Benefits of Cross-Subdomain Consent
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.
1. Shared Cookie Storage (Recommended)
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
-
Enable Cross-Subdomain Consent:
- Go to Settings → Cross-Domain
- Enable Cross-subdomain consent sharing
- Select storage method
-
Configure Parent Domain:
- Enter parent domain (e.g.,
.example.com) - Verify domain ownership
- Set cookie options
- Enter parent domain (e.g.,
-
Add Subdomains:
- List all subdomains that should share consent
- Configure individual subdomain settings
- Test domain connectivity
-
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);
});
Cookie Security
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:
- Verify domain configuration in dashboard
- Check cookie domain settings
- Confirm subdomain accessibility
- Review browser console for errors
Cookie Issues:
- Ensure HTTPS for secure cookies
- Check SameSite policy compatibility
- Verify domain starts with dot (
.example.com) - Test cookie size limits
PostMessage Failures:
- Verify origin allowlists are correct
- Check for content security policy blocks
- Ensure event listeners are properly registered
- 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
- Start Simple: Begin with shared cookie method before trying complex approaches
- Test Thoroughly: Verify behavior across all target subdomains and browsers
- Plan for Failures: Implement fallback behavior when sync fails
- Monitor Performance: Track impact on page load and user experience
- Security First: Always validate origins and implement proper access controls
Maintenance Recommendations
- Regular Testing: Periodically test sync behavior across all subdomains
- Monitor Logs: Watch for sync errors and user consent patterns
- Update Documentation: Keep subdomain lists current as infrastructure changes
- Performance Monitoring: Track consent sync impact on site performance
- Security Audits: Regularly review domain access and origin validation
Next Steps
After configuring cross-subdomain consent: