UNPKG

c15t

Version:

Headless JavaScript consent management platform for cookie banners, privacy preferences, consent storage, and script gating.

106 lines (81 loc) 8.38 kB
--- title: Initialization Flow description: Reference page for initialization flow. group: reference --- 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 **Simplified** 1. **Provider mounts** — creates (or retrieves from cache) a consent runtime and store 2. **Check stored consent** — reads existing consent from cookies / localStorage; if found and the policy fingerprint hasn't changed, the banner stays hidden 3. **Fetch init data** — calls the backend `GET /init` (or uses SSR/offline data) for the resolved policy, location, and translations 4. **Apply resolved policy** — the backend resolves the policy from your [policy pack](/docs/frameworks/react/concepts/policy-packs) 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. 5. **Decide banner visibility** — shows the banner only if no prior consent exists, the resolved policy requires it (`ui.mode` is `banner` or `dialog`), or the policy fingerprint changed since last consent 6. **Gating enforced** — scripts, iframes, and network requests tagged with a consent category are blocked until that category is granted 7. **User interacts** — choices are persisted to storage, synced to the backend (with `policySnapshotToken` if configured), and blocked scripts/iframes load immediately after consent is granted **Sequence Diagram** ```mermaid sequenceDiagram participant Provider as ConsentManagerProvider participant Store as Consent Store participant Storage as localStorage / Cookie participant API as c15t Backend participant UI as Banner / Dialog participant Scripts as Script Loader Provider->>Store: getOrCreateConsentRuntime() Store->>Storage: getStoredConsent() alt Stored consent exists Storage-->>Store: consentInfo + consents Store->>Store: activeUI = 'none' else No stored consent Store->>Store: isLoadingConsentInfo = true end Store->>Store: initConsentManager() Store->>Storage: Check pending consent sync opt Pending sync from revocation reload Store->>API: Deferred setConsent() (non-blocking) end alt SSR data provided Store->>Store: tryUseSSRData() else No SSR data Store->>API: GET /init API-->>Store: policy, policyDecision, location, translations end Store->>Store: Apply resolved policy (model, categories, ui.mode) Store->>Store: Check fingerprint change → re-prompt if needed Store->>Store: Set activeUI, auto-grant if opt-out/none alt User has no prior consent or policy changed UI->>UI: Banner / Dialog appears (per policy ui.mode) UI->>Store: saveConsents({ type }) Store->>Storage: Persist consent + subjectId + fingerprint Store->>Scripts: updateScripts(), updateIframes(), updateNetwork() Store->>API: POST /subjects + policySnapshotToken (non-blocking) end ``` ## 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](/docs/frameworks/react/concepts/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](/docs/frameworks/react/server-side) for SSR setup. **Policy resolution** — When [policy packs](/docs/frameworks/react/concepts/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](/docs/frameworks/react/concepts/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](/docs/frameworks/react/concepts/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](/docs/frameworks/react/script-loader), [Iframe Blocking](/docs/frameworks/react/iframe-blocking), and [Network Blocker](/docs/frameworks/react/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](/docs/frameworks/react/concepts/cookie-management) for revocation and persistence details. ## When Does the Banner Show? The banner appears when any of these conditions are true: 1. **No existing consent** — the user has never consented (or their consent was cleared), **and** the resolved policy requires a UI (`ui.mode` is `banner` or `dialog`, or the model is `opt-in` or `iab`) 2. **Policy changed** — the material policy fingerprint differs from the fingerprint stored with the user's last consent (re-prompting) 3. **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](/docs/frameworks/react/concepts/consent-models) and [Policy Packs](/docs/frameworks/react/concepts/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|