# Consent Mode v2 Implementation Examples ## Basic gtag.js Implementation ### Complete Setup (EU GDPR Compliant) ```html ``` ## Regional Consent Settings ### EU vs US Default Consent ```javascript window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} // EU/EEA: Default denied gtag('consent', 'default', { 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied' }, { 'region': ['AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB', 'IS', 'LI', 'NO'] }); // US (except California): Default granted gtag('consent', 'default', { 'ad_storage': 'granted', 'ad_user_data': 'granted', 'ad_personalization': 'granted', 'analytics_storage': 'granted' }); // California (CCPA): Analytics granted, ads denied gtag('consent', 'default', { 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'granted' }, { 'region': ['US-CA'] }); ``` ## Google Tag Manager Implementation ### Method 1: Custom HTML Tags **Tag 1: Consent Initialization (Fires First)** ```html ``` **Tag 2: Consent Update - Accept All** ```html ``` **Tag 3: Consent Update - Analytics Only** ```html ``` ### Method 2: Using CMP Template (Cookiebot Example) 1. **Install Cookiebot Template:** - GTM Templates → Template Gallery - Search "Cookiebot" - Add to workspace 2. **Configure Cookiebot Tag:** - Tag Type: Cookiebot CMP (Community Template) - Cookiebot ID: Your Cookiebot ID - Default consent: All denied - Trigger: Consent Initialization - All Pages - Priority: 999 3. **Cookiebot auto-handles:** - Default consent setting - Consent updates on user choice - Consent persistence - Regional settings ## JavaScript Event Listeners ### Listening to Consent Changes ```javascript // Monitor consent state changes window.addEventListener('consent-update', function(event) { console.log('Consent updated:', event.detail); // Send custom event to analytics gtag('event', 'consent_update', { 'consent_status': event.detail.analytics_storage, 'timestamp': new Date().toISOString() }); }); // Trigger on user action function updateConsent(status) { gtag('consent', 'update', status); // Dispatch event for other scripts window.dispatchEvent(new CustomEvent('consent-update', { detail: status })); } ``` ## CCPA / Global Privacy Control (GPC) ### Detecting and Honoring GPC ```javascript window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} // Check for Global Privacy Control signal if (navigator.globalPrivacyControl === true) { // User has GPC enabled - deny advertising gtag('consent', 'default', { 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'granted' // Analytics OK }); } else { // No GPC signal - use standard defaults gtag('consent', 'default', { 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied' }); } ``` ### GTM Variable for GPC **Variable Configuration:** - Variable Type: Custom JavaScript - Name: "GPC - Global Privacy Control" ```javascript function() { return navigator.globalPrivacyControl === true ? 'enabled' : 'disabled'; } ``` Use in consent logic to conditionally set consent. ## Consent with Server-Side Tracking ### Measurement Protocol with Consent ```python import requests import json MEASUREMENT_ID = "G-XXXXXXXXXX" API_SECRET = "your_api_secret" ENDPOINT = f"https://www.google-analytics.com/mp/collect?measurement_id={MEASUREMENT_ID}&api_secret={API_SECRET}" def send_with_consent(client_id, event_name, consent_status): payload = { "client_id": client_id, "consent": { "ad_storage": consent_status.get('ad_storage', 'denied'), "analytics_storage": consent_status.get('analytics_storage', 'denied'), "ad_user_data": consent_status.get('ad_user_data', 'denied'), "ad_personalization": consent_status.get('ad_personalization', 'denied') }, "events": [{ "name": event_name, "params": {} }] } response = requests.post(ENDPOINT, json=payload) return response.status_code == 204 # Example: User has granted analytics only send_with_consent( client_id="client_123", event_name="purchase", consent_status={ "ad_storage": "denied", "analytics_storage": "granted", "ad_user_data": "denied", "ad_personalization": "denied" } ) ``` ## SPA (Single Page Application) Consent ### React Example ```javascript import { useEffect, useState } from 'react'; function ConsentManager() { const [showBanner, setShowBanner] = useState(false); useEffect(() => { // Initialize consent on app load window.dataLayer = window.dataLayer || []; function gtag(){window.dataLayer.push(arguments);} // Set default gtag('consent', 'default', { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }); // Check for stored consent const storedConsent = localStorage.getItem('userConsent'); if (storedConsent) { const consent = JSON.parse(storedConsent); gtag('consent', 'update', consent); } else { setShowBanner(true); } }, []); const acceptAll = () => { const consent = { 'ad_storage': 'granted', 'analytics_storage': 'granted', 'ad_user_data': 'granted', 'ad_personalization': 'granted' }; window.gtag('consent', 'update', consent); localStorage.setItem('userConsent', JSON.stringify(consent)); setShowBanner(false); }; const rejectAll = () => { const consent = { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }; window.gtag('consent', 'update', consent); localStorage.setItem('userConsent', JSON.stringify(consent)); setShowBanner(false); }; if (!showBanner) return null; return (

We use cookies to improve your experience.

); } export default ConsentManager; ``` ## Testing Consent Mode ### DebugView Verification ```javascript // Enable debug mode for testing gtag('config', 'G-XXXXXXXXXX', { 'debug_mode': true }); // Set consent gtag('consent', 'update', { 'analytics_storage': 'granted' }); // Send test event gtag('event', 'test_consent', { 'test_parameter': 'test_value' }); // Check in DebugView: // 1. Event appears // 2. Event details show consent status // 3. Look for "gcs" parameter (Google Consent State) ``` ### Console Verification ```javascript // Check consent state in console dataLayer.filter(item => item[0] === 'consent') // Expected output: // [ // ['consent', 'default', {...}], // ['consent', 'update', {...}] // ] ``` ### Cookie Inspection **Before Consent (analytics_storage = denied):** - Open DevTools → Application → Cookies - Should NOT see `_ga`, `_ga_*` cookies **After Consent (analytics_storage = granted):** - `_ga` cookie present - `_ga_` cookie present ## Advanced: Granular Consent Options ### Custom Consent Categories ```javascript // Your custom consent preferences const userPreferences = { necessary: true, // Always on analytics: true, // User accepted marketing: false, // User denied personalization: true // User accepted }; // Map to Google consent parameters const consentMapping = { ad_storage: userPreferences.marketing ? 'granted' : 'denied', ad_user_data: userPreferences.marketing ? 'granted' : 'denied', ad_personalization: userPreferences.personalization ? 'granted' : 'denied', analytics_storage: userPreferences.analytics ? 'granted' : 'denied' }; // Update consent gtag('consent', 'update', consentMapping); ``` ## Consent Revocation ### Allowing Users to Change Consent ```javascript function showConsentSettings() { // Show modal/settings page document.getElementById('consent-settings-modal').style.display = 'block'; } function updateConsentPreferences(newPreferences) { gtag('consent', 'update', newPreferences); localStorage.setItem('userConsent', JSON.stringify(newPreferences)); // Optional: Reload page to apply changes // window.location.reload(); } // Example: User clicks "Withdraw Consent" function withdrawConsent() { const deniedConsent = { 'ad_storage': 'denied', 'analytics_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied' }; updateConsentPreferences(deniedConsent); // Delete existing GA cookies document.cookie.split(";").forEach(function(c) { if (c.trim().startsWith('_ga')) { document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=" + new Date().toUTCString() + ";path=/"); } }); } ``` ## Compliance Checklist - [ ] Default consent set to "denied" before tags load - [ ] Consent banner shown before tracking - [ ] User can accept/reject consent - [ ] Consent choices persist across sessions - [ ] Consent can be withdrawn/changed later - [ ] All 4 v2 parameters included (ad_storage, analytics_storage, ad_user_data, ad_personalization) - [ ] Regional settings configured if needed - [ ] GPC honored for CCPA compliance - [ ] Consent status tested in DebugView - [ ] Cookie behavior verified (no cookies before consent) - [ ] Privacy policy updated with consent information