Initialization Flow
When the consent provider mounts, it creates a cached consent runtime, reads any stored consent from the browser, fetches the resolved policy from the backend (or uses SSR/offline data), and decides whether to show the banner. This entire sequence completes before the first meaningful consent-aware render.
Lifecycle Sequence
- Provider mounts — creates (or retrieves from cache) a consent runtime and store
- Check stored consent — reads existing consent from cookies / localStorage; if found and the policy fingerprint hasn't changed, the banner stays hidden
- Fetch init data — calls the backend
GET /init(or uses SSR/offline data) for the resolved policy, location, and translations - Apply resolved policy — the backend resolves the policy from your policy pack based on visitor geo (region → country → fallback → default). The response includes the consent model, categories, UI mode, and a material fingerprint. If no policy pack is configured, the legacy jurisdiction-to-model mapping is used instead.
- Decide banner visibility — shows the banner only if no prior consent exists, the resolved policy requires it (
ui.modeisbannerordialog), or the policy fingerprint changed since last consent - Gating enforced — scripts, iframes, and network requests tagged with a consent category are blocked until that category is granted
- User interacts — choices are persisted to storage, synced to the backend (with
policySnapshotTokenif configured), and blocked scripts/iframes load immediately after consent is granted
How It Works
Mount — When the provider renders, it creates (or retrieves from cache) a consent runtime and store. Any existing consent is read from localStorage/cookies immediately. If consent already exists and the policy fingerprint matches, the banner stays hidden and gating rules apply right away. See Client Modes for how the mode affects runtime creation.
Init — The store fetches the resolved policy, location, and translation data. In hosted mode this calls GET /init on your backend; in offline mode it resolves from offlinePolicy.policyPacks locally. If SSR data was passed to the provider, the network fetch is skipped entirely. See Server-Side Utilities for SSR setup.
Policy resolution — When policy packs are configured, the backend resolves the right policy for the visitor based on their geo-location (region → country → fallback → default). The resolved policy determines the consent model (opt-in, opt-out, iab, or none), which categories are in scope, and what UI to show. For opt-out and none models, all categories are auto-granted — unless the resolved policy has consent.gpc: true and the browser sends a Global Privacy Control signal, in which case marketing and measurement are denied. If no policy pack is configured, the legacy jurisdiction-to-model mapping is used instead. See Consent Models for details.
Re-prompting — If the resolved policy's material fingerprint differs from the fingerprint stored with the user's last consent, the banner is shown again. This happens automatically when you change consent-affecting fields (model, categories, scope mode, allowed actions). Presentation-only changes do not trigger re-prompts. See Policy Packs — Re-Prompting for details.
Save — When the user interacts with the banner or dialog, their choices are persisted to localStorage/cookies and synced to the backend (along with the policySnapshotToken if snapshot signing is configured). Script, iframe, and network gating rules update immediately based on the new consent state. See the Script Loader, Iframe Blocking, and Network Blocker guides for gating details.
Revocation — If a user revokes a previously granted category, the page reloads by default to ensure a clean execution environment. The API sync is deferred to the fresh page load. See Cookie Management for revocation and persistence details.
When Does the Banner Show?
The banner appears when any of these conditions are true:
- No existing consent — the user has never consented (or their consent was cleared), and the resolved policy requires a UI (
ui.modeisbannerordialog, or the model isopt-inoriab) - Policy changed — the material policy fingerprint differs from the fingerprint stored with the user's last consent (re-prompting)
- Storage is accessible — the browser allows localStorage (not blocked in private mode)
If the resolved model is none or opt-out (and ui.mode is none), consents are auto-granted and the banner never appears. See Consent Models and Policy Packs for details.
Debugging the Lifecycle
Use the DevTools panel and callbacks to inspect each step of the initialization flow. onConsentSet is the broad lifecycle signal; onConsentChanged and subscribeToConsentChanges() are the change-only signals for explicit post-init saves.
| Step | DevTools Panel | Callback | What to check |
|---|---|---|---|
| Init / SSR hydration | Location | onBannerFetched | jurisdiction, countryCode, regionCode populated? |
| Policy resolution | Policy | onBannerFetched | policyId, matchedBy, fingerprint in policyDecision |
| Model resolution | Location | onBannerFetched | model value matches the resolved policy |
| Banner visibility | Consents | — | activeUI in store state; does policy ui.mode require it? |
| Re-prompting | Policy | — | Fingerprint mismatch between stored and resolved policy? |
| Consent save | Consents + Events | onConsentSet | preferences object in callback payload |
| Change-only integrations | Events | onConsentChanged or subscribeToConsentChanges() | allowedCategories, deniedCategories, and previous values only when a real save changed preferences |
| Script loading | Scripts | onConsentSet | Script IDs and their load/blocked status |
| Reload on revocation | Events | onBeforeConsentRevocationReload | Fires before reload; check localStorage for c15t:pending-consent-sync |
| Deferred sync | Events | onError (if sync fails) | After reload, check Events panel for successful API call |
Configure callbacks in the provider to log lifecycle events, and add DevTools for a visual inspector: