Skip to content

Consent Integration

Edition 3.1.1


Sections 02–06 describe the technical ceiling: full UID persistence, all click IDs, attribution across sessions. Consent determines how far below that ceiling you operate.

The core tension: consent-first operation in consent-required jurisdictions means a substantial share of sessions never obtain the permissions that persistent identity and paid-media attribution depend on. Sessions without those permissions run in degraded modes. That is the cost of collecting lawfully, not a defect in the implementation. (This page deliberately publishes no percentage split: the split depends on your traffic mix and consent UX, and no dated evidence supports a universal figure.)

This section defines what “degraded” means in each consent state and where the gray areas are.


Consent handling separates three layers, and behavior is driven by the third, never by a tier number. A CMP (consent management platform) is the tool that shows the consent banner and records the visitor’s choice.

  1. Observed signals: the four purpose signals as received from the consent source, each exactly granted | denied | unknown | not_applicable: analytics_storage, ad_storage, ad_user_data, ad_personalization.
  2. Lifecycle status: internally exactly pending | resolved | not_applicable. pending means no answer yet (or a mechanism failure); it sends nothing. resolved means a real choice exists. not_applicable means the site runs under an explicit no-consent-mechanism policy. On the wire, status is only resolved | not_applicable: pending sends no payload, and no reason or provenance field ever appears in a data-plane consent object.
  3. Effective permissions: four binary decisions, each exactly allowed | denied, derived from observed signals after fail-closed defaults, site policy, and the GPC overlay: analytics_storage, ad_storage, ad_user_data, ad_personalization. Anything unknown fails closed to denied.

Every payload records the consent state it was produced under: the observed choices, the effective permissions derived from them, the selected source (the tool that recorded the choice), and when that source record last changed.

Every capability reads exactly one effective permission, or a documented conjunction. Storage/capture authority and disclosure authority are different questions:

CapabilityRequires
UID persistence (any device storage for identity)lifecycle resolved (or not_applicable under the established T0 policy) AND effective analytics_storage: allowed AND the deployment’s documented first-party analytics/persistent-identity purpose — the permission alone is insufficient
Click-ID capture/holding (memory or permitted storage)effective ad_storage: allowed — and holding begins only after lifecycle resolved
Click-ID / identifier disclosure to Googleeffective ad_user_data: allowed plus the applicable purpose gate
Disclosure to any other destinationthat destination’s own documented policy gate — no signal alone confers disclosure authority
Audience / remarketing actionseffective ad_personalization: allowed
Automatic session emissioncanonical state changed AND effective analytics_storage: allowed AND the deployment’s documented first-party analytics purpose. ad_storage alone never authorizes a generic session

conversion and identify are explicit application calls under their own purpose/destination gates, never emitted automatically.

The truth table covers the 16 combinations of the four binary effective permissions. (a=analytics_storage, s=ad_storage, u=ad_user_data, p=ad_personalization; ✓=allowed, ✕=denied). pending/not_applicable and GPC are derivation overlays, not extra rows.

#asupDerived tierOutcome
11Full capability
22Identity + click IDs; Google disclosure allowed; no audience actions
32Identity + click IDs; no Google user-data disclosure; audience actions allowed
42Identity + click IDs held; no disclosure gates open
52Identity; no click-ID capture; Google user-data + audience gates open
62Identity; no click-ID capture; Google user-data gate open
72Identity; no click-ID capture; audience gate open
82Identity + analytics only
93No identity/persistence; purpose-limited in-memory click-ID handling; explicitly consented ad actions via their own gates
103As #9 without audience actions
113As #9 without Google user-data disclosure
123In-memory ad handling only; no disclosure gates open
133No storage or capture; only explicit-call gates open
143As #13, Google gate only
153As #13, audience gate only
164Nothing permitted — a resolved all-denied state is dormant (registry derived_tier_table.rows.dddd = 4)

Rows 9–12 are the ads-only family: analytics denial removes identity and persistence (derived tier 3), while ad_storage: allowed still permits purpose-limited, in-memory click-ID handling and an explicitly consented ad action. That action is an example of the explicit conversion/identify calls under their own gates. It is not a promise that those events are generally available in tier-3 states, and never a generic session.

  • pending fails closed: all effective permissions denied, tier-3 in-memory behavior, zero data-plane traffic. The internal reason (awaiting_user vs. failure tokens) never reaches the wire.
  • not_applicable applies only when no consent mechanism is configured and the implementer has explicitly configured the T0 policy. Effective permissions then come from that site policy, source is site_policy, and all four observed signals are not_applicable. There is no other T0 encoding.
  • GPC (Global Privacy Control, a browser-level opt-out signal) is an independent observed policy signal, never a fifth enum and never a source. The payload records detected and the implementer’s applicable determination. When detected and applicable, the overlay forces ad_storage, ad_user_data, ad_personalization to denied; it does not by itself alter analytics_storage.

Scope of the silence claims (UIAF-shaped traffic only). Every “zero data-plane traffic”, “wholly silent”, and “dormant” claim on this page governs UIAF-shaped data-plane events and client-side persistence only.

UIAF-07-CONSENT-008 (derived tier)tier MUST be derived from effective permissions, for reporting and prose only, exactly per the registry derived_tier_table (uiaf-enums.json): 0 = not_applicable under explicit site policy (status_override); 1 = all four allowed; 2 = analytics_storage allowed with any ad permission denied (rows 2–8); 3 = analytics_storage denied with at least one ad permission allowed (rows 9–15) — plus the internal lifecycle-pending overlay, which fails closed to tier-3 in-memory behavior and never serializes; 4 = a resolved all-four-denied state (row 16, registry dddd) — dormant. The tier number MUST NOT drive collection, purge, or routing — every behavior reads effective-permission fields.


UIAF-07-CONSENT-001 — The server MUST evaluate Sec-GPC: 1 on the incoming request before any capture or injection, as an independent observation; GPC observation is not a step in a source-precedence chain. Client-side navigator.globalPrivacyControl is the in-page complement. Observed signals and their provenance are recorded separately from effective permissions — a GPC-forced denial is never misrepresented as a CMP choice.

Consent-source precedence (observed-signal layer only): a CMP current-state adapter is preferred over GCM-derived signals. The CMP record reflects the user’s direct choice, while GCM signals are set by integration code and can be stale, mis-mapped, or delayed. When CMP and GCM disagree, trust the CMP. The selected authority becomes source (cmp_cookiebot, cmp_onetrust, cmp_didomi, cmp_custom for any other adapter, or gcm).

UIAF-07-CONSENT-018 (TCF→four-signal mapping — no over-disclosure) — Deployments sourcing consent from a TCF-capable CMP (cmp_cookiebot, cmp_onetrust, and cmp_didomi are TCF-capable) MUST maintain a reviewed, dated TCF→four-signal mapping as configuration [CONTROLLER][COUNSEL], and MUST NOT over-disclose relative to the recorded consent: each effective permission MAY be allowed only where the corresponding TCF purposes/consents are affirmatively present in the consent record, and any ambiguity — unmapped purposes, legitimate-interest-only bases where consent is required, or conflicting purpose/vendor state — MUST fail closed to denied. The mapping MUST account for the granularity mismatch of the IAB Europe TCF model (TCF Policies v2.2: Purposes 1–10, Special Features, and Stacks do not map 1:1 onto the four signals); collapsing a TCF record into four binary signals without a reviewed mapping is a purpose-limitation and consent-fidelity risk (GDPR Art 5(1)(b), Art 6(1)(a)).

No consent-state getter exists in Google’s consent mode. Google documents that “consent mode doesn’t save consent choices” and instructs implementers to persist the choice themselves and re-set state on every page load. That persist-and-reset pattern is exactly UIAF’s CMP-record-first reading. Replaying the dataLayer command history is an unofficial technique and is not part of this specification. (Google consent-mode guide, 2026-05-06.)

UIAF-07-CONSENT-017 (GCM-source consent receipt) — Because Google Consent Mode does not persist consent choices, no CMP record exists on the gcm path. In consent-required jurisdictions, a deployment whose consent source is gcm MUST persist its own Art 7(1)-adequate consent receipt — the recorded signal values, the timestamp of the user’s choice, the UIAF/CMP-integration version, and request provenance sufficient to demonstrate how consent was obtained — retained server-side under the deployment’s retention schedule, and MUST surface it via the payload’s opaque consent_record_id. A gcm-source deployment without such a receipt is non-conforming in consent-required jurisdictions. The CMP-as-system-of-record deferral elsewhere in this specification applies to cmp_* sources only and MUST NOT be read as covering the GCM-only path [CONTROLLER][COUNSEL].

Resolution outcomes: a CMP expected but not yet answered → lifecycle pending, reason awaiting_user; adapter/CMP failure → pending with timeout/parse_failure/cmp_error/unavailable; both are silent on the data plane. No mechanism configured at all → only under the explicit T0 policy, not_applicable.

UIAF-07-CONSENT-015 (state_updated_at adapter contract) — A consent-source adapter MUST supply a trustworthy last-material-change timestamp for the selected source record, and state_updated_at MUST be that time — stable across unchanged rereads, never read, event, receipt, or serialization time. Where the source cannot supply one, the adapter MUST freeze the first-observation time of the current source record as state_updated_at: the freeze is persisted per source record, keyed to the record identity the adapter reads; it is stable across rereads of an unchanged record; it is replaced only when the source record itself materially changes (the replacement freezing the changed record’s own first-observation time); and it MUST NOT be derived from read, hydration, or serialization time. An adapter that can neither supply a trustworthy material-change time nor persist a first-observation freeze MUST leave the integration in lifecycle pending (reason unavailable) — it MUST NOT invent a fresh timestamp per read. Source-supplied time, first-observation freeze, and the pending outcome are the only permitted strategies, and a deployment MUST NOT switch strategies silently between reads — so two conforming implementations of the same source cannot diverge on a value that rides the dirty projection.

UIAF-07-CONSENT-016 (server/client consent-record divergence — explicit degraded mode) — The deployment MUST be configured so that server middleware and the client observe the same consent record and version — a CMP record readable in both contexts, or a server-side mirror the client treats as authoritative. Where that is impossible (the consent record is resolvable in the browser but unreadable to middleware), the divergence rule is: the server MUST fail closed — consent treated as unresolved for that request, deny-before-use, no persistent-identity issuance or refresh against the unobservable record — and the client-side resolution path MUST NOT loop create/recovery attempts against the deny-before-use server: after a bounded, deployment-configured set of attempts, the client MUST treat the deployment as operating in the client-only degraded profile (no server persistent-identity capability for the affected scope) rather than retrying indefinitely. A permanent create/recovery churn loop against a fail-closed server is non-conforming. The degraded profile and its attempt bound are declared per consent-adapter profile as deployment configuration [CONTROLLER].


Google Consent Mode (GCM) provides a standardized signal that UIAF reads but does not control. The four signals and their purposes:

SignalControls
analytics_storageanalytics-purpose storage
ad_storageadvertising-purpose storage
ad_user_datasending user data related to advertising to Google
ad_personalizationremarketing/personalization

Advanced vs. Basic mode is a controller choice, not a spec default [CONTROLLER]. Two Google-tag settings materially change what Google’s own tags transmit when storage is denied. They modify Google’s behavior, not UIAF’s:

  • ads_data_redaction (gtag('set', 'ads_data_redaction', true)): when ad_storage is denied, ad click identifiers in Google Ads/Floodlight requests are redacted and requests use a cookieless domain.
  • url_passthrough (gtag('set', 'url_passthrough', true)): deliberately passes gclid/dclid/gclsrc/_gl/wbraid through URLs when storage is denied.

The five tier names remain as derived shorthand for the states above.

Section titled “Tier 0 — Explicit site-policy baseline (no consent mechanism)”

Only lawful where the implementer has established that the full technical baseline is lawful for the request and has explicitly configured the T0 policy. The encoding is status: not_applicable, all four observed signals not_applicable, source: site_policy, and state_updated_at set to the active policy-record activation time.

UIAF-07-CONSENT-005 (T0 jurisdiction duty) — The GDPR follows the visitor (Art 3(2)), and applicable-jurisdiction opt-out signals still bind. A T0 deployment MUST evaluate its current, dated jurisdiction/site-policy configuration and GPC for each request. Geolocation is one possible deployment signal feeding that evaluation — never a UIAF mandate and never a guarantee — and UIAF hard-codes no country list. Where T0 eligibility cannot be established for a request, that request MUST fail closed to lifecycle pending with pending reason unavailable, all four effective permissions denied, and zero data-plane traffic. Which jurisdictions make the baseline lawful is a controller/counsel determination [COUNSEL].

All four effective permissions allowed. Full capability with consent evidence attached: every payload carries the complete consent object described above.

Tier 2 — Analytics identity with ad restrictions

Section titled “Tier 2 — Analytics identity with ad restrictions”

Effective analytics_storage: allowed with one or more ad permissions denied (truth-table rows 2–8). Identity and analytics run; each ad capability follows its own field. When ad_storage is denied, click IDs are excluded from capture, but never stripped from the page URL itself (see Attribution Capture). Removing gclid/fbclid from the URL breaks platform detection and deduplication. Campaign-level UTM handling follows the contextual rules in Attribution Capture. UTM values are not treated as automatically safe or automatically personal; the classification is contextual [COUNSEL].

Effective analytics_storage: denied with at least one ad permission allowed (rows 9–15), or lifecycle unresolved (every pending state, as the internal fail-closed overlay). A resolved all-four-denied state is row 16: tier 4/dormant, not tier 3. Only lifecycle pending and the dormant state are wholly silent.

Any “minimal anonymous measurement” under a tier-3 state is a separately named, default-off, deployment-specific profile requiring its own documented legal basis, minimization, aggregation, and retention policy. Designing and justifying such a profile is controller/counsel work and is not part of the conforming core [CONTROLLER][COUNSEL].

Explicit rejection or enforced maximum restriction: a resolved row-16 state. The dormant state’s purge and silence obligations are UIAF-07-CONSENT-009’s.

UIAF-07-CONSENT-009 (dormant purge, dormant silence, and the T4 revocation control request) — Entering the dormant state MUST apply the transition-matrix purge (UIAF-07-CONSENT-012, “Explicit full revocation” row). Once dormant, UIAF MUST emit zero data-plane traffic — including no terminal ping of any kind. Consent revocation additionally uses the dedicated one-shot revocation control request — a same-origin, CSRF-hardened, minimal tombstone-only control-plane call defined in Data Handling (UIAF-08-REVOKE-001). The previous UID MUST be used solely to honor withdrawal; the request MUST fire before local purge; local purge MUST proceed regardless of timeout or failure; the call is one-shot — it MUST NOT be retried or queued; the previous UID MUST NOT be reused after purge; and a persistent UIAF opt-out marker or indefinite tombstone MUST NOT exist or be created — server-side suppression retention (a distinct, bounded record) remains controller/jurisdiction-configured. It is not an event and MUST NOT enter the analytics schema or retry queue.


UIAF-07-CONSENT-006 (pre-consent storage boundary) — Before consent resolution the conforming core uses only server-injected current-request context and current-document memory. It MUST NOT write UIAF attribution or click IDs — encrypted or otherwise — to cookies, localStorage, or sessionStorage: encryption does not make a pre-consent terminal-storage write exempt, and confinement to memory is minimization that reduces exposure under ePrivacy Art 5(3), not an exemption from it.

Scope of the server-processing position (mainstream reading, not a guarantee): a server receiving its own HTTP request is not obviously the same act as storing or reading data on the visitor’s device, but that reading is not a safe harbor.

UIAF-07-CONSENT-002 — During lifecycle pending, retained context MUST be exactly the registry contract pending_context_allowlist (uiaf-enums.json, edition 3.1.1): JSON null or a closed object {utm_source, utm_medium, utm_campaign} — all three keys required, no additional properties, each member a string or null. Members are only these three; utm_term, utm_content, referrer values, landing URL/path, click IDs, custom or unallowlisted query values, identifiers, tokens, timestamps, and any user-specific decoration MUST be excluded while pending. Values MUST pass the registry’s normalization and byte bounds (1–128 UTF-8 bytes per member; ≤1,024-byte canonical object; fail-closed, never truncated) and MUST exact-match a finite controller-configured per-key campaign vocabulary — no wildcard, regex-only, default, inferred-value, or raw-query passthrough. The vocabulary configuration is the registry’s closed contract: a closed required three-key config (utm_source, utm_medium, utm_campaign), each key a finite array of closed entry records exactly {value, review}; values are normalization fixed points, unique within their key, 1–128 UTF-8 bytes; each review record is exactly record_id (^[A-Za-z0-9._:-]{1,128}$), reviewed_at (integer Unix seconds, 0..253402300799), classification: shared_campaign_metadata, plus the five required-false booleans (per_recipient_or_dynamic, identifier_or_token, free_text, sensitive_or_special_category, audience_membership_inference) — controller assertions whose truth remains a controller obligation; validator success cannot convert prohibited data into campaign metadata. Config failure is two-tier: T1 — config absent, unparseable, non-object, or carrying an unsupported top-level key → all three vocabularies empty; T2 — within an otherwise object-shaped config, a missing key, non-array value, malformed or extra-property entry, non-fixed-point value, duplicate-after-normalization, or unreviewed/invalid-review entry → only that key’s vocabulary empty, valid siblings surviving. An empty array is valid (an empty vocabulary, not a failure); no fallback exists at either tier. Duplicate JSON keys MUST be rejected pre-materialization by a raw-JSON duplicate-rejecting parser or lossless pre-scan using decoded-name equality (escaped and literal spellings collide); never first-wins or last-wins; a top-level duplicate (recognized or extra) → T1; an entry-object or nested-review duplicate → T2 for the affected key; outcomes are byte-identical in both member orders; failure diagnostics carry only the layer, the affected allowlist key where applicable, and the duplicate-name error class — never decoded names, raw spellings, configured or request values, or review metadata. Request-side member failures are independent per member with valid-sibling survival, distinct from config failure; an all-members-null result or a canonical object exceeding 1,024 bytes yields top-level null. Review metadata is excluded from the context object and from every sink. Click-ID memory handling MUST begin only after lifecycle resolved with effective ad_storage: allowed. After resolution, the pending context MUST map only into an independently authorized touchpoint’s source/medium/campaign; nothing else is reconstructed from it.

Pre-resolution exception boundary (master-locked): any pre-resolution exception to the above exists only in the separately named, default-off restricted_measurement profile. That profile carries its own legal basis, minimization, schema, retention, and conformance contract, and it can never weaken the conforming core described here.

UIAF-07-CONSENT-010 (leakage controls — engineering controls, not a legal exemption) — Responses carrying injected request context MUST use Cache-Control: private, no-store. Channel rules are split by value class: prohibited values (identifiers, click IDs, user-specific or unallowlisted URL values) MUST NOT appear in any channel — cache, page source, script access, reports, referrer, or logs. Allowed minimized campaign context may exist in the carrying page and its scoped module state, but MUST NOT be cached or durably serialized (shared/CDN/service-worker/hydration), copied into history entries, error/CSP/analytics reports, referrers, or logs, or exposed through third-party-readable globals. URL minimization and a Referrer-Policy of strict-origin-when-cross-origin or stricter MUST be applied; allowlisted click-ID and user-specific query values MUST be redacted from logs at the earliest controllable boundary — the initial request may already have reached infrastructure before that boundary. Page-source and script-access verification is scoped to minimization and access control, not to impossible universal absence of the injected context from the page that carries it. In-memory pre-consent context MUST be cleared on pagehide/navigation, and a pageshow with persisted: true (back/forward-cache restore) is a negative path — pre-consent context MUST NOT be recovered from a restored page; no-store alone does not evict a live JS heap.

Expected loss: if the user navigates before consent resolves, the in-memory context is deliberately lost. Consent granted on page 2 starts attribution from page 2’s context. This is the designed behavior of a consent-first architecture, not a defect.

Banner blocked / CMP failure: lifecycle stays pending with the applicable failure reason; the core remains silent; memory dies with the page.


UIAF-07-CONSENT-011 (lifecycle state machine) — Normative text equivalent of the diagram: initialization MUST be pending when a CMP is expected, or not_applicable under the explicit T0 policy. pending → resolved occurs when the adapter delivers signals. Within resolved, changes MUST be processed as field-level effective-permission transitions. Explicit rejection or enforced restriction enters the dormant state; re-consent leaves it via ordinary resolution. Deploying a CMP on a former T0 site (or removing one, under explicit policy) MUST initialize at the new state — a T0 ↔ Tn transition, treated as fresh initialization.

UIAF-07-CONSENT-012 (transition and purge matrix) — On each effective-permission change, the storage/queue and routing actions in the following table MUST be applied; tier numbers MUST NOT appear in any transition, purge, or routing condition.

Effective-permission changeStorage/queue action (registry uiaf-storage-keys.json)Routing action
analytics_storage allowed→deniedDelete uiaf_uid + uiaf_recovery (atomic pair), uiaf_session_state, the persisted uiaf_attribution record, uiaf_dirty_baseline — per the mechanism-aware contract (Data Handling UIAF-08-PURGE-002): the client synchronously clears permitted script-clearable mechanisms only and never writes/deletes the persistent uiaf_uid cookie; middleware treats an inbound prior UID as denied/absent before any use and sends the original-scope deletion cookie (Max-Age=0, Path=/, Secure, SameSite=Lax, identical configured Domain when set). Current-document, purpose-limited ads state survives when effective ad_storage remains allowed (the ads-only family, truth-table rows 9–12)Automatic session emission stops
ad_storage allowed→deniedStrip click-ID members from uiaf_attribution in the same synchronous blockClick-ID capture/holding stops
ad_user_data allowed→deniedNo live identity/attribution-state change; apply the UIAF-07-CONSENT-004 queue predicate belowGoogle-destination disclosure stops
ad_personalization allowed→deniedNo live identity/attribution-state change; apply the UIAF-07-CONSENT-004 queue predicate belowAudience/remarketing actions stop
Explicit full revocation (→ dormant)Full purge of all registry keys incl. the retry queue and legacy purge-only keys, per the UIAF-08-PURGE-002 mechanism-aware split (client clears script-clearable mechanisms; uiaf_uid is expired by middleware with the original-scope deletion cookie, prior UID denied/absent before any use); the revocation control request follows its full one-shot contract (previous UID solely for withdrawal; fired before purge; purge regardless of timeout/failure; no retry/queue; UID never reused; no marker/tombstone)Zero data-plane traffic thereafter
Erasure (data-subject request)Client-side: full registry purge incl. legacy keys per the UIAF-08-PURGE-002 mechanism-aware split (script-clearable mechanisms only; uiaf_uid middleware-expired with the original-scope deletion cookie); server side per Data Handling control workflows
Any upgrade (denied→allowed)Initialize newly permitted capabilities from the current page context (plus any surviving pending context per its mapping rule)A session fires only under the automatic-emission gate

UIAF-07-CONSENT-004 (queue predicate on every downgrade) — On every effective-permission downgrade (analytics_storage, ad_storage, ad_user_data, or ad_personalization), entries in uiaf_retry_queue whose immutable required_permissions/purpose/destinations are no longer satisfied MUST be dropped before send; a dropped entry is never redacted and resent, its event_id is never changed or reused, and unrelated still-permitted entries are retained. This rule applies over the whole transition table above.

UIAF-07-CONSENT-003 (reconcile-on-init) — On every initialization, before any capability logic runs, persisted UIAF state that current effective permissions no longer allow MUST be purged per the mechanism-aware contract in Data Handling UIAF-08-PURGE-002 (reconcile-on-init is a UIAF-08-PURGE-001 predicate): the client synchronously clears permitted script-clearable mechanisms only and MUST NOT write or delete the persistent uiaf_uid cookie; middleware MUST treat an inbound prior UID as denied/absent before any use and MUST send the original-issuance-scope deletion cookie (Max-Age=0, Path=/, Secure, SameSite=Lax, identical configured Domain when set); local purge completes on timeout, and next-request middleware expiry prevents prior-UID reuse. The purge set includes the complete legacy purge-on-sight set, for which the registry’s legacy_purge_only section (uiaf-storage-keys.json) is the sole source of truth (this page defers to it and does not enumerate it), plus the pre-3.0 uiaf_attribution cookie, recorded as legacy mechanism-purge metadata on the live uiaf_attribution registry entry. Cross-tab/session convergence is re-read-based, not instantaneous: at every guarded operational boundary from UIAF-07-CONSENT-007 — immediately before capture, every persistence write, retry queueing, retry drain, and every network send — the implementation MUST re-read the authoritative CMP/GPC/server consent state and MUST complete any applicable mechanism-aware UIAF-08-PURGE-002 purge before using stored UIAF state; stale state MUST NOT be used at that boundary.

UIAF-07-CONSENT-007 (consent wake-up IPC and cross-tab convergence) — Consent wake-up broadcasting MUST use the exact channel uiaf-consent-wakeup — the registered binding runtime_ipc.consent_wakeup_broadcast_channel = uiaf-consent-wakeup in uiaf-enums.json, with no alias, distinct from the session-claim channel runtime_ipc.broadcast_channel = uiaf-session-claim. The channel is wake-only runtime IPC, not storage: a message carries no UID, consent vector, reason, provenance, or policy state, says only “consent may have changed,” and is never trusted as consent proof — receipt triggers only a re-read of the authoritative CMP/GPC/server-side consent state (mirroring UIAF-02-CONSENT-001). Authoritative consent MUST be re-read on initialization; immediately before capture, every persistence write, retry queueing, retry drain, and every network send; on focus/visibility return; and on pageshow/BFCache restore. Where BroadcastChannel is unavailable, those mandatory re-read points remain the fallback — no state or epoch is invented or stored, and no persistent convergence marker exists.

UIAF-07-CONSENT-013 (dirty projection) — The session dirty projection’s consent component MUST include exactly signals, status, effective, gpc, source, and state_updated_at, and MUST exclude both the derived tier and consent_record_id (tier is redundant derived shorthand and never independently drives emission). A source or state_updated_at change alters projection bytes and thereby satisfies only the canonical-change limb of the emission gate — an automatic session still MUST satisfy effective analytics_storage: allowed and the documented analytics purpose. Receipt rotation alone is projection-byte-identical and MUST NOT trigger anything.


GPC (Sec-GPC: 1 header; navigator.globalPrivacyControl) expresses an opt-out of sale/sharing/targeted advertising. UIAF treats it as an independent observed policy overlay (see the Capability Model). When detected and applicable, the three ad-purpose permissions are forced to denied. First-party analytics permission is not silently revoked by the signal itself. That non-strict default is a documented controller choice, not a protocol-level legal determination. The gpc_strict option below exists for jurisdictions where counsel reads the opt-out as also covering analytics feeding ad targeting. Firefox 135 removed the Do Not Track checkbox and pointed users to its GPC setting (Firefox 135 release notes, 2025-02-04; B10).

UIAF-07-CONSENT-014 (GPC binding-jurisdiction configuration and the gpc_strict option) — The set of jurisdictions where an observed GPC signal is treated as binding MUST be maintained as dated site-policy configuration — never as prose, and never as a code constant — shaped as a gpc_binding_jurisdictions record carrying the jurisdiction list and a last_reviewed date, with a quarterly review cadence [CONTROLLER][COUNSEL]; gpc.applicable MUST be derived from that current, dated configuration. The default (non-strict) overlay MUST force exactly the three ad-purpose permissions (ad_storage, ad_user_data, ad_personalization) to denied and MUST NOT by itself alter analytics_storage. Where counsel reads a binding jurisdiction’s opt-out as also covering first-party analytics that feeds ad targeting, the deployment MAY set the dated gpc_strict configuration option [CONTROLLER][COUNSEL], which then MUST extend the overlay to force analytics_storage: denied for applicable requests as well. Both keys are site-policy configuration only: they MUST NOT add any wire field, and MUST NOT alter the data-plane consent-object shape.

  • The payload records gpc.detected and gpc.applicable, the implementer’s jurisdiction determination, maintained as the dated gpc_binding_jurisdictions configuration (with last_reviewed, quarterly review) defined by UIAF-07-CONSENT-014 [CONTROLLER][COUNSEL]. This specification does not enumerate binding jurisdictions in prose: the set changes, and the current list belongs in that reviewed configuration, not static text.
  • GPC enforcement is real: the California Attorney General’s Sephora settlement (announced 2022-08-24) rested in part on failure to honor GPC signals. That is a dated enforcement citation, not a compliance recipe.
  • Where an applicable framework provides a lawful path for a subsequent, specific, informed opt-in to prevail for a known user, implementing that path is controller/counsel work [COUNSEL]. A generic “accept all” click does not qualify under the mainstream reading.

Key metrics, keyed to the consent object (never to tier alone):

  • Sessions by effective-permission state: the distribution across truth-table rows; derived tier may label the report.
  • Pending vs. explicit denial: awaiting_user cohorts (banner unanswered) are a UX problem; explicit-denial cohorts are a consent-choice fact. The lifecycle/provenance split makes these distinguishable; conflating them misdirects remediation.
  • Attribution coverage: share of sessions with source/medium present.
  • Identity persistence: share of sessions with a returning UID (zero wherever analytics_storage is denied).
  • Click-ID coverage: share of paid-traffic sessions where effective ad_storage: allowed permitted capture.

Text equivalent: evaluate Sec-GPC first as an independent observation. With no mechanism and an explicit T0 policy, encode not_applicable/site_policy. With a mechanism unresolved, stay pending (internal reason; all-denied; silent). Once resolved, take observed signals from the selected authority (CMP over GCM). Then apply fail-closed defaults, site policy, and the GPC overlay to produce the four binary effective permissions. Derive the display tier last. Ads-only observed states resolve to no-identity effective states that retain in-memory ad capability (truth-table rows 9–12).


Digital Omnibus (proposed Regulation COM(2025) 837). The proposal does not repeal ePrivacy Art 5(3): ePD Art 4 is repealed, terminal-equipment cases involving personal data move to a new GDPR Art 88a, and Art 5(3) survives for non-personal data. Procedural status: Council general approach adopted December 2025; European Parliament negotiating mandate granted March 2026; interinstitutional trilogue underway since April 2026 (joint ITRE/LIBE draft-report consideration 2026-07-13). The proposal is not yet adopted (European Parliament, ITRE committee highlights, europarl.europa.eu/committees/en/itre/home/highlights, accessed 2026-08-07). Trilogue text is fluid: the final scope of any Art 88a(3)(c) analytics exemption is to be re-verified at adoption. Do not implement ahead of adoption; any future consent-free mode contemplated by the proposal is tied to aggregate outputs. (Status verified 2026-08-07.)

ePrivacy Regulation. The proposed ePrivacy Regulation’s withdrawal was announced in the Commission’s 2025 Work Programme (2025-02-11), formalized 2025-07-16, and published in the Official Journal (OJ C/2025/5423, 2025-10-06). The ePrivacy Directive remains in force. (Verified 2026-07-19.)


CMP fails to load. Lifecycle stays pending with the applicable failure reason; the core stays silent; in-memory context dies with the page.

Consent on page 2. Each page load initializes fresh; pre-consent context from page 1 was deliberately lost on navigation. On grant, capabilities initialize from the current page’s context. Expected loss, by design.

Consent then refresh. The CMP record persists; on refresh the adapter resolves directly to the recorded state. No transition logic needed.

Back/forward-cache restore. pageshow with persisted: true is a negative path: pre-consent in-memory context was cleared on pagehide and is not recovered.

Consent varies by subdomain. Consent is read independently per page load; identity sharing across subdomains follows Identity Management, while capabilities follow the local consent state.