Tracking
Consent Mode v2
GDPR and CCPA consent management via client-side geo detection.
Consent Mode v2
GDPR/CCPA compliance via Google Consent Mode v2 with client-side geo detection.
Entry: app/layout.js, lib/consentModeBootstrap.js
Flow
Zone classification
| Zone | Condition |
|---|---|
| GDPR | EU-27 + EEA + UK + Crown Dependencies, or geo lookup failure |
| CCPA | US + California (CA) |
| Other | Everything else |
Consent defaults by zone
| Zone | ad_storage | analytics_storage |
|---|---|---|
| GDPR | denied (wait 500ms for CMP) | denied |
| CCPA | granted | granted |
| Other | granted | granted |
Key files
| File | Purpose |
|---|---|
lib/utils/consentZone.js | classifyConsentZone() + country lists |
lib/consentModeBootstrap.js | Client-side geo + consent bootstrap |
app/layout.js | #consent-mode-v2 inline script in <head> |
components/overlays/PixelConsentManager.js | CMP consent monitoring |
CCPA / US-state opt-out
Funding Choices can report the same choice via INITIAL_CCPA_DATA_READY, INITIAL_US_STATES_OPT_OUT_DATA_READY, and GPP sectionChange. Bootstrap maps those to Consent Mode denied/granted, but dedupes so Tag Assistant only sees one consent update per real state change. GPP listens to sectionChange only (not listenerRegistered / cmpStatus).
Gotchas
- Geo lookup is client-side only — no server/nginx config needed
- Geo API failure defaults to
"GDPR"(safest fallback) - Zone cached in
sessionStorage(ub_consent_zone) - Saved consent in localStorage is zone-scoped, and supports GDPR, CCPA, and Other zones
- First page load: ~100–300ms delay for geo; cached visits are instant
LocalStorage schema
{
"ad_storage": "granted",
"ad_user_data": "granted",
"ad_personalization": "granted",
"analytics_storage": "granted"
}Key: ub_gtag_consent