Per-Platform Consent Integration Specification
Technical specification for cookie consent banner developers to integrate per-platform consent with Conversion Bridge.
Overview
Conversion Bridge supports two consent models:
- Category-Based Consent - Traditional model where consent is granted for broad categories like "analytics" or "marketing"
- Per-Platform Consent - Granular model where consent is granted for individual platforms (e.g., Google Analytics, Meta Pixel, Microsoft Clarity)
This document covers per-platform consent integration for consent management platforms (CMPs) that allow users to grant or deny consent for specific tracking services rather than broad categories.
Platform Identifiers
Conversion Bridge uses the following platform identifiers:
| Platform | Identifier | Category Fallback |
|---|---|---|
| Google Analytics 4 | ga4 | analytics |
| Google Ads | googleads | marketing |
| Meta Pixel (Facebook) | meta | marketing |
| Microsoft Clarity | clarity | analytics |
| Microsoft Ads | microsoft | marketing |
| Conversion Bridge Journeys | conversion_bridge | analytics |
| TikTok Pixel | tiktok | marketing |
| PostHog | posthog | analytics |
| Matomo | matomo | analytics |
| Pinterest Tag | pinterest | marketing |
| LinkedIn Insight | linkedin | marketing |
| Twitter/X Pixel | twitter | marketing |
| Snapchat Pixel | snapchat | marketing |
| Reddit Pixel | reddit | marketing |
Consent State Architecture
Conversion Bridge maintains consent state in a JavaScript object:
var consent = {
categories: [], // e.g., ['analytics', 'marketing']
platforms: [] // e.g., ['ga4', 'conversion_bridge', 'googleads']
};
// Presence in array = consent grantedConsent Mode Determination
The system automatically determines which consent mode is active:
- Platform Mode: If
consent.platforms.length > 0, the system uses platform-specific consent - Category Mode: Otherwise, it falls back to category-based consent
For Conversion Bridge internal tracking (journeys/sessions):
function can_cb_track() {
if (consent.platforms.length > 0) {
return consent.platforms.includes('conversion_bridge');
}
return consent.categories.includes('analytics');
}JavaScript API
Setting Per-Platform Consent
Use ConversionBridge.platform_consent() to set consent for individual platforms:
/**
* Set consent for a specific platform
*
* @param {string} platform - Platform identifier (e.g., 'ga4', 'meta')
* @param {boolean} allowed - Whether consent is granted (default: false)
*/
ConversionBridge.platform_consent( platform, allowed );Examples:
// Grant consent for Google Analytics
ConversionBridge.platform_consent( 'ga4', true );
// Deny consent for Meta Pixel
ConversionBridge.platform_consent( 'meta', false );
// Grant consent for multiple platforms
ConversionBridge.platform_consent( 'ga4', true );
ConversionBridge.platform_consent( 'clarity', true );
ConversionBridge.platform_consent( 'meta', true );
ConversionBridge.platform_consent( 'conversion_bridge', true ); // For CB journeysSetting Category-Based Consent
Use ConversionBridge.category_consent() for category-based consent:
/**
* Set category-based consent
*
* @param {string} category - 'analytics' or 'marketing'
* @param {boolean} allowed - Whether consent is granted
*/
ConversionBridge.category_consent( category, allowed );Examples:
// Grant analytics consent
ConversionBridge.category_consent( 'analytics', true );
// Deny marketing consent
ConversionBridge.category_consent( 'marketing', false );Checking Consent State
/**
* Check if consent is granted for a category
*
* @param {string} category - 'analytics' or 'marketing'
* @returns {boolean}
*/
ConversionBridge.has_consent( category );
/**
* Get full consent state object (for debugging)
*
* @returns {object} { categories: [...], platforms: [...] }
*/
ConversionBridge.get_consent();Examples:
// Check if marketing consent is granted
if ( ConversionBridge.has_consent( 'marketing' ) ) {
// Marketing tracking is allowed
}
// Get full consent state
console.log( ConversionBridge.get_consent() );
// { categories: ['analytics'], platforms: ['ga4', 'conversion_bridge'] }Events
Events Dispatched by Conversion Bridge
Conversion Bridge dispatches these custom events on the window object when consent changes:
cb_consent_category
Fired when category-based consent changes. The event detail is the array of granted categories.
window.addEventListener( 'cb_consent_category', function( e ) {
console.log( e.detail );
// ['analytics', 'marketing'] - array of granted categories
// Check specific category
if ( e.detail.includes( 'marketing' ) ) {
// Marketing consent was granted
}
});cb_consent_platform
Fired when per-platform consent changes. The event detail is the array of granted platforms.
window.addEventListener( 'cb_consent_platform', function( e ) {
console.log( e.detail );
// ['ga4', 'googleads', 'conversion_bridge'] - array of granted platforms
// Check specific platform
if ( e.detail.includes( 'meta' ) ) {
// Meta consent was granted
}
});Platform Consent Listener Pattern
Each platform in Conversion Bridge listens for both events to handle consent updates:
// Category consent listener
window.addEventListener( 'cb_consent_category', function( e ) {
updatePlatformConsent( e.detail.includes( 'marketing' ) );
});
// Platform consent listener
window.addEventListener( 'cb_consent_platform', function( e ) {
updatePlatformConsent( e.detail.includes( 'googleads' ) );
});Integration Patterns
Pattern 1: Direct API Integration
Call Conversion Bridge methods directly from your consent banner's callback:
// Your consent banner's callback when user makes choices
function onConsentUpdated( userChoices ) {
// Map your platform identifiers to Conversion Bridge identifiers
const platformMapping = {
'google-analytics': 'ga4',
'google-ads': 'googleads',
'facebook-pixel': 'meta',
'microsoft-clarity': 'clarity',
'microsoft-ads': 'microsoft',
'tiktok-pixel': 'tiktok',
'conversion-bridge': 'conversion_bridge'
};
// Iterate through user's choices
Object.keys( userChoices ).forEach( function( yourPlatformId ) {
const cbPlatform = platformMapping[ yourPlatformId ];
if ( cbPlatform ) {
ConversionBridge.platform_consent( cbPlatform, userChoices[ yourPlatformId ] );
}
});
// Trigger pageview after consent is set (if analytics allowed)
if ( ConversionBridge.has_consent( 'analytics' ) ) {
ConversionBridge.pageview();
}
}Pattern 2: Event-Based Integration
If your CMP dispatches custom events:
// Listen for your CMP's consent event
document.addEventListener( 'your_cmp_consent_updated', function( e ) {
const consent = e.detail.consent;
// Example: Your CMP provides consent per service
if ( consent.services ) {
consent.services.forEach( function( service ) {
// Map service names to CB platform identifiers
const platform = mapServiceToPlatform( service.name );
if ( platform ) {
ConversionBridge.platform_consent( platform, service.allowed );
}
});
}
});Pattern 3: Initial State on Page Load
Set consent state on page load based on stored preferences:
document.addEventListener( 'DOMContentLoaded', function() {
// Wait for both your CMP and Conversion Bridge to be ready
if ( typeof ConversionBridge === 'undefined' ) {
return;
}
// Get stored consent from your CMP
const storedConsent = YourCMP.getStoredConsent();
if ( storedConsent && storedConsent.platforms ) {
Object.keys( storedConsent.platforms ).forEach( function( platform ) {
ConversionBridge.platform_consent( platform, storedConsent.platforms[ platform ] );
});
}
});Complete Integration Example
Here's a complete example for a hypothetical CMP called "ConsentManager":
(function() {
'use strict';
// Platform identifier mapping
const PLATFORM_MAP = {
// Your CMP's service IDs : Conversion Bridge platform IDs
'google_analytics_4': 'ga4',
'google_ads': 'googleads',
'facebook_pixel': 'meta',
'microsoft_clarity': 'clarity',
'microsoft_ads': 'microsoft',
'tiktok_pixel': 'tiktok',
'pinterest_tag': 'pinterest',
'linkedin_insight': 'linkedin',
'twitter_pixel': 'twitter',
'snapchat_pixel': 'snapchat',
'reddit_pixel': 'reddit',
'conversion_journeys': 'conversion_bridge'
};
/**
* Sync consent state from your CMP to Conversion Bridge
*/
function syncConsentToConversionBridge( consentData ) {
if ( typeof ConversionBridge === 'undefined' ) {
console.warn( 'ConversionBridge not loaded' );
return;
}
// Handle per-platform consent
if ( consentData.services && Array.isArray( consentData.services ) ) {
consentData.services.forEach( function( service ) {
const cbPlatform = PLATFORM_MAP[ service.id ];
if ( cbPlatform ) {
ConversionBridge.platform_consent( cbPlatform, service.consented === true );
}
});
}
// Fallback: Handle category-based consent if no per-platform data
if ( ! consentData.services && consentData.categories ) {
if ( consentData.categories.analytics !== undefined ) {
ConversionBridge.category_consent( 'analytics', consentData.categories.analytics );
}
if ( consentData.categories.marketing !== undefined ) {
ConversionBridge.category_consent( 'marketing', consentData.categories.marketing );
}
}
// Trigger pageview after consent sync
ConversionBridge.pageview();
}
/**
* Initialize integration
*/
function init() {
// 1. Sync initial consent state on page load
if ( window.ConsentManager && window.ConsentManager.getConsent ) {
const initialConsent = window.ConsentManager.getConsent();
if ( initialConsent ) {
syncConsentToConversionBridge( initialConsent );
}
}
// 2. Listen for consent changes
document.addEventListener( 'ConsentManager:updated', function( e ) {
syncConsentToConversionBridge( e.detail );
});
// 3. Handle consent banner acceptance
document.addEventListener( 'ConsentManager:accepted', function( e ) {
syncConsentToConversionBridge( e.detail );
});
// 4. Handle consent withdrawal
document.addEventListener( 'ConsentManager:withdrawn', function( e ) {
// Set all platforms to false
Object.values( PLATFORM_MAP ).forEach( function( platform ) {
ConversionBridge.platform_consent( platform, false );
});
});
}
// Wait for DOM and ConversionBridge
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', init );
} else {
init();
}
})();Server-Side Consent Handling
When Conversion Bridge sends events to the server, consent state is included in the payload:
{
"event_type": "form_submit",
"event_name": "Contact Form",
"consent": {
"categories": ["analytics", "marketing"],
"platforms": {
"ga4": true,
"meta": false,
"clarity": true,
"conversion_bridge": true
}
}
}The server uses this to determine which platforms should receive the event data via server-side APIs (e.g., Meta Conversions API).
Consent Priority
Conversion Bridge uses this priority order when determining consent:
- Per-Platform Consent (highest priority) - If any platform consent is set, platform mode is active
- Category Consent - Falls back to category if no platform consent is set
- Default - If no consent plugin configured, all consent is granted
// Example: Platform consent takes priority
ConversionBridge.category_consent( 'analytics', true ); // Category: analytics = true
ConversionBridge.platform_consent( 'ga4', false ); // Platform: ga4 = false
// Result: GA4 will NOT receive data (platform consent overrides category)
// But other analytics platforms without explicit platform consent will use categoryEvent Queue Behavior
When analytics consent is not granted:
- Events are queued in
localStorage(key:cb_event_queue) - Maximum queue size: 100 events
- Events expire after 48 hours
- When consent is granted: queued events are sent
- When consent is denied: queue is cleared
This ensures no data is lost if users grant consent later in their session.
Debugging
Console Logging
Enable debug mode in Conversion Bridge settings to see consent operations in the browser console.
When consent is denied, platform events will show detailed status messages:
[Conversion Bridge] Google Ads event: conversion {...}
[Conversion Bridge] ↳ Google Ads Consent Mode: ad_storage=denied - conversion will be modeled, not tracked with cookiesA small piece of data stored in a user’s browser that helps websites remember user activity, preferences, or sessions across visits.
[Conversion Bridge] Meta event: Lead (fbq not loaded - script blocked, event NOT sent) {...}
[Conversion Bridge] Microsoft Ads event: form_submit {...}
[Conversion Bridge] ↳ Microsoft Ads: UET SDK not loaded (script blocked) - event queued but will NOT be sent to Microsoft
[Conversion Bridge] TikTok event: SubmitForm (ttq not loaded - script blocked, event NOT sent) {...}Checking Consent State
// Check current consent state
console.log( ConversionBridge.get_consent() );
// { categories: ['analytics'], platforms: ['ga4', 'conversion_bridge'] }
// Check specific category consent
console.log( ConversionBridge.has_consent( 'marketing' ) );
// false
// Listen for consent changes
window.addEventListener( 'cb_consent_category', function( e ) {
console.log( 'Category consent changed:', e.detail );
});
window.addEventListener( 'cb_consent_platform', function( e ) {
console.log( 'Platform consent changed:', e.detail );
});Understanding Console Output
When you see platform events in the console with consent denied:
| Platform | What Happens |
|---|---|
| Google Ads/GA4 (Consent Mode) | Events are sent but Google "models" conversions instead of tracking with cookies |
| Meta (script blocked) | fbq function not available, event NOT sent to Meta |
| Microsoft (script blocked) | UET SDK not loaded, events queued in array but NOT processed |
| TikTok (script blocked) | ttq object not functional, event NOT sent to TikTok |
WordPress Consent API Compatibility
If your CMP implements the WordPress Consent API, Conversion Bridge automatically integrates with it. The plugin:
- Listens to
wp_listen_for_consent_changeevents - Maps WP categories:
statistics→analytics,marketing→marketing - Uses
wp_has_consent()for initial state
If you implement the WP Consent API, category-based consent works automatically. For per-platform consent, you'll still need to call ConversionBridge.platform_consent() directly.
Best Practices
- Always set consent before triggering pageview - Ensure all platform consent is set before calling
ConversionBridge.pageview() - Handle both initial state and changes - Sync consent on page load AND listen for updates
- Use the correct platform identifiers - Refer to the platform table above
- Test consent withdrawal - Verify that denying consent properly stops tracking
- Consider the event queue - Be aware that events may be queued and sent later
- Map your services accurately - Create a clear mapping between your service IDs and Conversion Bridge platform identifiers
- Include
conversion_bridgefor journeys - If you want CB's internal journey tracking, grant consent for theconversion_bridgeplatform
Support
For integration support or to request additional platform identifiers, contact the Conversion Bridge development team.
Still need help?
If you have not yet found your answer in the documentation articles, please contact support
Contact support