@c15t/react 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -3
- package/README.md +1 -1
- package/dist/components/iab-consent-dialog/atoms/purpose-item.cjs +1 -1
- package/dist/components/iab-consent-dialog/atoms/purpose-item.js +1 -1
- package/dist/components/iab-consent-dialog/hooks/use-gvl-data.cjs +1 -1
- package/dist/components/iab-consent-dialog/hooks/use-gvl-data.js +1 -1
- package/dist/components/iab-consent-dialog/iab-consent-dialog.cjs +1 -1
- package/dist/components/iab-consent-dialog/iab-consent-dialog.js +1 -1
- package/dist/iab/styles.tw3.css +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist-types/components/consent-banner/components.d.ts +3 -3
- package/dist-types/components/consent-banner/consent-banner.d.ts +1 -1
- package/dist-types/components/consent-banner/index.d.ts +9 -9
- package/dist-types/components/consent-banner/policy-actions.d.ts +2 -2
- package/dist-types/components/consent-dialog/atoms/card.d.ts +5 -5
- package/dist-types/components/consent-dialog/atoms/overlay.d.ts +1 -1
- package/dist-types/components/consent-dialog/consent-dialog.d.ts +2 -2
- package/dist-types/components/consent-dialog/index.d.ts +7 -7
- package/dist-types/components/consent-dialog-link/index.d.ts +1 -1
- package/dist-types/components/consent-dialog-trigger/atoms/button.d.ts +1 -1
- package/dist-types/components/consent-dialog-trigger/atoms/icon.d.ts +1 -1
- package/dist-types/components/consent-dialog-trigger/atoms/root.d.ts +2 -2
- package/dist-types/components/consent-dialog-trigger/atoms/toolbar.d.ts +2 -2
- package/dist-types/components/consent-dialog-trigger/consent-dialog-trigger-toolbar.d.ts +1 -1
- package/dist-types/components/consent-dialog-trigger/consent-dialog-trigger.d.ts +5 -5
- package/dist-types/components/consent-dialog-trigger/index.d.ts +4 -4
- package/dist-types/components/consent-dialog-trigger/types.d.ts +1 -1
- package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
- package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
- package/dist-types/components/consent-widget/atoms/accordion.d.ts +3 -3
- package/dist-types/components/consent-widget/atoms/button.d.ts +1 -1
- package/dist-types/components/consent-widget/atoms/footer.d.ts +1 -1
- package/dist-types/components/consent-widget/atoms/root.d.ts +1 -1
- package/dist-types/components/consent-widget/consent-widget.d.ts +1 -1
- package/dist-types/components/consent-widget/index.d.ts +11 -11
- package/dist-types/components/consent-widget/policy-actions.d.ts +2 -2
- package/dist-types/components/consent-widget/types.d.ts +1 -1
- package/dist-types/components/frame/atoms.d.ts +2 -2
- package/dist-types/components/frame/frame.d.ts +1 -1
- package/dist-types/components/frame/index.d.ts +3 -3
- package/dist-types/components/frame/types.d.ts +1 -1
- package/dist-types/components/iab-consent-banner/iab-consent-banner.d.ts +2 -2
- package/dist-types/components/iab-consent-banner/index.d.ts +19 -19
- package/dist-types/components/iab-consent-dialog/atoms/purpose-item.d.ts +21 -2
- package/dist-types/components/iab-consent-dialog/atoms/stack-item.d.ts +1 -1
- package/dist-types/components/iab-consent-dialog/atoms/vendor-list.d.ts +1 -1
- package/dist-types/components/iab-consent-dialog/hooks/use-gvl-data.d.ts +7 -1
- package/dist-types/components/iab-consent-dialog/iab-consent-dialog.d.ts +5 -4
- package/dist-types/components/iab-consent-dialog/index.d.ts +25 -25
- package/dist-types/components/iab-consent-dialog/use-iab-translations.d.ts +4 -0
- package/dist-types/components/integrations/index.d.ts +2 -2
- package/dist-types/components/integrations/shared.d.ts +1 -1
- package/dist-types/components/integrations/youtube-embed.d.ts +1 -1
- package/dist-types/components/shared/policy-actions.d.ts +2 -2
- package/dist-types/components/shared/primitives/box.d.ts +1 -1
- package/dist-types/components/shared/primitives/button.d.ts +4 -4
- package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
- package/dist-types/components/shared/primitives/legal-links/index.d.ts +1 -1
- package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
- package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
- package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
- package/dist-types/components/shared/ui/branding.d.ts +1 -1
- package/dist-types/components/shared/ui/button/button.d.ts +1 -1
- package/dist-types/components/shared/ui/button/index.d.ts +2 -2
- package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
- package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
- package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
- package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
- package/dist-types/components/shared/ui/switch/switch.d.ts +1 -1
- package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
- package/dist-types/context/theme-context.d.ts +1 -1
- package/dist-types/headless.d.ts +9 -9
- package/dist-types/hooks/index.d.ts +12 -12
- package/dist-types/hooks/use-headless-consent-ui.d.ts +1 -1
- package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
- package/dist-types/hooks/use-styles.d.ts +1 -1
- package/dist-types/hooks/use-theme.d.ts +1 -1
- package/dist-types/iab.d.ts +4 -4
- package/dist-types/index.d.ts +20 -20
- package/dist-types/primitives/accordion.d.ts +1 -1
- package/dist-types/primitives/button.d.ts +1 -1
- package/dist-types/primitives/collapsible.d.ts +1 -1
- package/dist-types/primitives/dialog.d.ts +1 -1
- package/dist-types/primitives/preference-item.d.ts +1 -1
- package/dist-types/primitives/switch.d.ts +1 -1
- package/dist-types/primitives/tabs.d.ts +1 -1
- package/dist-types/primitives.d.ts +7 -7
- package/dist-types/providers/consent-manager-provider.d.ts +1 -1
- package/dist-types/server/fetch-ssr-data.d.ts +1 -1
- package/dist-types/server/index.d.ts +5 -5
- package/dist-types/types/theme/index.d.ts +2 -2
- package/dist-types/types/theme/style-types.d.ts +1 -1
- package/dist-types/utils/merge-styles.d.ts +1 -1
- package/dist-types/utils/test-helpers.d.ts +1 -1
- package/dist-types/utils/theme-utils.d.ts +1 -1
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +6 -3
- package/docs/frameworks/react/concepts/client-modes.md +5 -3
- package/docs/frameworks/react/concepts/consent-models.md +2 -2
- package/docs/frameworks/react/concepts/cookie-management.md +4 -0
- package/docs/frameworks/react/concepts/glossary.md +1 -1
- package/docs/frameworks/react/concepts/initialization-flow.md +3 -3
- package/docs/frameworks/react/concepts/policy-packs.md +4 -2
- package/docs/frameworks/react/hooks/use-consent-manager/overview.md +1 -1
- package/docs/frameworks/react/iab/consent-banner.md +2 -2
- package/docs/frameworks/react/iab/consent-dialog.md +12 -3
- package/docs/frameworks/react/iab/overview.md +18 -6
- package/docs/frameworks/react/iframe-blocking.md +2 -0
- package/docs/frameworks/react/policy-packs.md +1 -1
- package/docs/integrations/front-chat.md +178 -0
- package/docs/integrations/one-dollar-stats.md +118 -0
- package/docs/integrations/overview.md +3 -0
- package/docs/integrations/pinterest-tag.md +236 -0
- package/docs/shared/concepts/client-modes.md +5 -3
- package/docs/shared/concepts/consent-models.md +2 -2
- package/docs/shared/concepts/cookie-management.md +4 -0
- package/docs/shared/concepts/glossary.md +1 -1
- package/docs/shared/concepts/initialization-flow.md +3 -3
- package/docs/shared/concepts/policy-packs.md +4 -2
- package/docs/shared/react/guides/iframe-blocking.md +2 -0
- package/docs/shared/react/guides/policy-packs.md +1 -1
- package/docs/shared/react/hooks/use-consent-manager/overview.md +1 -1
- package/docs/shared/react/iab/consent-banner.md +1 -1
- package/docs/shared/react/iab/consent-dialog.md +11 -2
- package/docs/shared/react/iab/overview.md +16 -4
- package/package.json +6 -6
- package/readme.json +1 -1
|
@@ -9,7 +9,7 @@ c15t supports four consent models that control how consent defaults, banner visi
|
|
|
9
9
|
|--|--|--|--|
|
|
10
10
|
|`opt-in`|Explicit consent required|Blocking banner|`false` (except `necessary`)|
|
|
11
11
|
|`opt-out`|Processing allowed by default|Non-blocking notice|`true` (all granted)|
|
|
12
|
-
|`iab`|IAB TCF 2.
|
|
12
|
+
|`iab`|IAB TCF 2.4 for programmatic ads|TCF banner|Managed by TCF framework|
|
|
13
13
|
|`null`|No regulation detected|No banner|`true` (all auto-granted)|
|
|
14
14
|
|
|
15
15
|
There are two ways c15t determines which model applies:
|
|
@@ -56,7 +56,7 @@ When the policy has `consent.gpc: true`, the browser's Global Privacy Control si
|
|
|
56
56
|
|
|
57
57
|
### IAB
|
|
58
58
|
|
|
59
|
-
IAB Transparency and Consent Framework (TCF) 2.
|
|
59
|
+
IAB Transparency and Consent Framework (TCF) 2.4 mode for programmatic advertising compliance. Only activates when two conditions are met: the jurisdiction is `GDPR` or `UK_GDPR`, and `iab.enabled` is `true` in your configuration.
|
|
60
60
|
|
|
61
61
|
When active, IAB mode generates TC strings, registers the `__tcfapi` CMP API, and works with the Global Vendor List (GVL) for machine-readable consent signals. If `iab.enabled` is not set, GDPR jurisdictions fall back to standard opt-in.
|
|
62
62
|
|
|
@@ -14,6 +14,10 @@ There are four sources of cookies on a typical website:
|
|
|
14
14
|
**1. c15t itself**
|
|
15
15
|
c15t stores the user's consent state in a `c15t` cookie (and mirrors it to localStorage). This cookie records which categories the user consented to, when they consented, and their subject ID. This is a strictly necessary cookie - it exists so the site remembers the user's consent choice.
|
|
16
16
|
|
|
17
|
+
If reading `window.localStorage` or calling a storage method throws, c15t logs a warning and skips unavailable pending-submission queues. Runtime construction still completes, and cookie-backed choices can still be read and saved. In v2, a failed localStorage access check skips policy initialization and hides the banner. Optional categories without a saved choice remain denied.
|
|
18
|
+
|
|
19
|
+
If the browser also blocks cookies, it cannot retain your choice across page loads. Do not use `enabled: false` to handle storage restrictions: that option grants every category.
|
|
20
|
+
|
|
17
21
|
**2. Third-party scripts**
|
|
18
22
|
When you load a tracking script (Google Analytics, Meta Pixel, etc.), that script sets its own cookies. Google Analytics creates `_ga` and `_gid` cookies. Meta creates `_fbp` and `_fbc`. These cookies are set by the script's code running in the browser - c15t prevents them by not loading the script until the user consents.
|
|
19
23
|
|
|
@@ -20,5 +20,5 @@ group: frameworks
|
|
|
20
20
|
|--|--|
|
|
21
21
|
|`jurisdiction`|A privacy regulation code (e.g., `GDPR`, `CCPA`, `PIPEDA`, `QC_LAW25`) detected from the user's geolocation. Maps to a consent model. See [Consent Models](/docs/frameworks/react/concepts/consent-models) for the full mapping table.|
|
|
22
22
|
|GPC|Global Privacy Control — a browser signal (`Sec-GPC: 1`) indicating the user opts out of data sale/sharing. Honored when a policy sets `consent.gpc: true` (enabled by default in California presets).|
|
|
23
|
-
|TCF|IAB Transparency and Consent Framework (v2.
|
|
23
|
+
|TCF|IAB Transparency and Consent Framework (v2.4) — a standard for programmatic advertising consent in GDPR jurisdictions. See [IAB TCF](/docs/frameworks/react/iab/overview).|
|
|
24
24
|
|GVL|Global Vendor List — an IAB-maintained registry of ad-tech vendors and their declared purposes, used by the TCF consent flow.|
|
|
@@ -69,9 +69,9 @@ sequenceDiagram
|
|
|
69
69
|
|
|
70
70
|
**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.
|
|
71
71
|
|
|
72
|
-
**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,
|
|
72
|
+
**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, categories are auto-granted only when there is no saved choice — 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.
|
|
73
73
|
|
|
74
|
-
**Re-prompting** — If the resolved policy's material fingerprint differs from the fingerprint stored with the user's last consent, the banner
|
|
74
|
+
**Re-prompting** — If the resolved policy's material fingerprint differs from the fingerprint stored with the user's last consent, previous grants become invalid, while the saved choice and its denials remain. The consent UI opens again when the resolved policy has one; under a no-banner policy, invalidated grants stay denied until the user makes a new choice. 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.
|
|
75
75
|
|
|
76
76
|
**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.
|
|
77
77
|
|
|
@@ -85,7 +85,7 @@ The banner appears when any of these conditions are true:
|
|
|
85
85
|
2. **Policy changed** — the material policy fingerprint differs from the fingerprint stored with the user's last consent (re-prompting)
|
|
86
86
|
3. **Storage is accessible** — the browser allows localStorage (not blocked in private mode)
|
|
87
87
|
|
|
88
|
-
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.
|
|
88
|
+
If the resolved model is `none` or `opt-out` (and `ui.mode` is `none`) and no saved choice exists, consents are auto-granted and the banner never appears. An existing saved choice keeps its denials, but grants invalidated by a policy change stay denied until the user makes a new choice. See [Consent Models](/docs/frameworks/react/concepts/consent-models) and [Policy Packs](/docs/frameworks/react/concepts/policy-packs) for details.
|
|
89
89
|
|
|
90
90
|
## Debugging the Lifecycle
|
|
91
91
|
|
|
@@ -32,7 +32,7 @@ const policies = [
|
|
|
32
32
|
|Preset|Model|UI|Matches|
|
|
33
33
|
|--|--|--|--|
|
|
34
34
|
|`europeOptIn()`|`opt-in`|banner|EEA + UK countries + geo fallback|
|
|
35
|
-
|`europeIab()`|`iab`|banner|EEA + UK countries + geo fallback (TCF 2.
|
|
35
|
+
|`europeIab()`|`iab`|banner|EEA + UK countries + geo fallback (TCF 2.4)|
|
|
36
36
|
|`californiaOptOut()`|`opt-out`|none|US-CA region|
|
|
37
37
|
|`quebecOptIn()`|`opt-in`|banner|CA-QC region|
|
|
38
38
|
|`worldNoBanner()`|`none`|none|default fallback|
|
|
@@ -65,7 +65,7 @@ Each policy combination produces a different consent experience:
|
|
|
65
65
|
|`model: 'opt-out'`, `ui.mode: 'none'`|No banner, everything loads immediately — user opts out via a "Do Not Sell" link|
|
|
66
66
|
|`model: 'none'`, `ui.mode: 'none'`|No banner, all categories auto-granted silently|
|
|
67
67
|
|`model: 'opt-in'`, `ui.mode: 'dialog'`|Full-screen dialog, nothing loads until the user consents|
|
|
68
|
-
|`model: 'iab'`, `ui.mode: 'banner'`|IAB TCF 2.
|
|
68
|
+
|`model: 'iab'`, `ui.mode: 'banner'`|IAB TCF 2.4 banner with vendor-level controls|
|
|
69
69
|
|
|
70
70
|
## How Policy Resolution Works
|
|
71
71
|
|
|
@@ -203,6 +203,8 @@ back to the `eu` profile's `fallbackLanguage`.
|
|
|
203
203
|
|
|
204
204
|
When you change a policy in a way that affects consent semantics — like adding a category, changing the consent model, or modifying allowed actions — c15t automatically re-prompts returning users.
|
|
205
205
|
|
|
206
|
+
A material policy change invalidates previous grants but keeps the user's choice record and denials. Optional categories stay denied until the user makes a new choice. The resolved policy controls whether a banner or dialog appears; a no-banner policy does not silently grant previously rejected categories. A temporary hosted initialization failure does not count as an authoritative policy change.
|
|
207
|
+
|
|
206
208
|
This works through the **material policy fingerprint**: a hash of only the consent-affecting fields (model, categories, scope, allowed actions, grouped action layout, direction, proof settings). Presentation-only changes like copy, button styling, or scroll lock do not trigger re-prompts.
|
|
207
209
|
|
|
208
210
|
|Change|Re-prompts?|
|
|
@@ -168,5 +168,5 @@ type Model = 'opt-in' | 'opt-out' | 'iab' | null;
|
|
|
168
168
|
|
|
169
169
|
* `'opt-in'` — Explicit consent required before tracking (GDPR)
|
|
170
170
|
* `'opt-out'` — Tracking allowed by default, user can opt out (CCPA)
|
|
171
|
-
* `'iab'` — IAB TCF 2.
|
|
171
|
+
* `'iab'` — IAB TCF 2.4 compliance mode
|
|
172
172
|
* `null` — No jurisdiction detected yet
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: IABConsentBanner
|
|
3
|
-
description: An IAB TCF 2.
|
|
3
|
+
description: An IAB TCF 2.4 compliant consent banner that displays partner
|
|
4
4
|
count, purpose summaries, and legitimate interest notices.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
7
|
> ℹ️ **Info:**
|
|
8
8
|
> c15t's IAB TCF support can be used in production. Use Inth for a hosted, IAB TCF-certified CMP setup with a managed CMP ID, or register your own CMP with IAB Europe and configure your own CMP ID.
|
|
9
9
|
|
|
10
|
-
`IABConsentBanner` is a pre-built consent banner that follows the [IAB Transparency & Consent Framework (TCF) 2.
|
|
10
|
+
`IABConsentBanner` is a pre-built consent banner that follows the [IAB Transparency & Consent Framework (TCF) 2.4](https://iabeurope.eu/tcf-2-0/) specification. It renders when the consent model is set to `'iab'` and includes required disclosures like partner count, purpose summaries, and legitimate interest notices.
|
|
11
11
|
|
|
12
12
|
Use this component instead of `ConsentBanner` when you need IAB TCF compliance for programmatic advertising in EU jurisdictions.
|
|
13
13
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: IABConsentDialog
|
|
3
|
-
description: An IAB TCF 2.
|
|
3
|
+
description: An IAB TCF 2.4 compliant preference center with tabbed purpose and
|
|
4
4
|
vendor management.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
7
|
> ℹ️ **Info:**
|
|
8
8
|
> c15t's IAB TCF support can be used in production. Use Inth for a hosted, IAB TCF-certified CMP setup with a managed CMP ID, or register your own CMP with IAB Europe and configure your own CMP ID.
|
|
9
9
|
|
|
10
|
-
`IABConsentDialog` is an IAB TCF 2.
|
|
10
|
+
`IABConsentDialog` is an IAB TCF 2.4 compliant consent dialog that provides a tabbed interface for managing purpose consent and vendor preferences. It includes purpose grouping via stacks, individual purpose/vendor toggles, special purpose and feature disclosures, and legitimate interest handling.
|
|
11
11
|
|
|
12
12
|
## Basic Usage
|
|
13
13
|
|
|
@@ -52,7 +52,8 @@ Displays all IAB purposes grouped into:
|
|
|
52
52
|
* **Standalone purposes** — Purpose 1 (Store and/or access information on a device) is always shown standalone per IAB TCF spec
|
|
53
53
|
* **Stacks** — Groups of related purposes determined by the GVL. Each stack is expandable to show individual purpose toggles
|
|
54
54
|
* **Special features** — Opt-in features like precise geolocation
|
|
55
|
-
* **Essential functions** — Special purposes
|
|
55
|
+
* **Essential functions** — Special purposes, which are locked (no user toggle) because vendors need them for basic operation
|
|
56
|
+
* **Features** — An informational section, shown when at least one vendor declares a feature
|
|
56
57
|
|
|
57
58
|
Each purpose shows:
|
|
58
59
|
|
|
@@ -62,6 +63,14 @@ Each purpose shows:
|
|
|
62
63
|
* Legitimate interest toggle where applicable
|
|
63
64
|
* Expandable vendor list
|
|
64
65
|
|
|
66
|
+
### Features section
|
|
67
|
+
|
|
68
|
+
TCF Policies v5.0.b treat features as information, not choices. The Features section follows those rules:
|
|
69
|
+
|
|
70
|
+
* Under the heading, the dialog shows the IAB standard text from the vendor list (`standardTexts.features`). If the vendor list does not include it, the dialog shows the `iab.preferenceCenter.features.description` translation.
|
|
71
|
+
* Each feature shows its name, description, IAB illustrations under **Examples**, and the names of the vendors that use it.
|
|
72
|
+
* The section has no switches, lock icons or per-vendor toggles. Features only serve the purposes the user chooses elsewhere in the dialog.
|
|
73
|
+
|
|
65
74
|
### Vendors Tab
|
|
66
75
|
|
|
67
76
|
Displays all vendors from the GVL plus any custom vendors:
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: IAB TCF 2.
|
|
3
|
-
description: Implement IAB Transparency & Consent Framework 2.
|
|
2
|
+
title: IAB TCF 2.4
|
|
3
|
+
description: Implement IAB Transparency & Consent Framework 2.4 compliance for
|
|
4
4
|
programmatic advertising in EU/EEA jurisdictions.
|
|
5
5
|
group: frameworks
|
|
6
6
|
---
|
|
7
7
|
## What is IAB TCF?
|
|
8
8
|
|
|
9
|
-
The [IAB Transparency & Consent Framework (TCF)](https://iabeurope.eu/tcf-2-0/) is a standardized protocol for communicating user consent choices to ad tech vendors in the programmatic advertising ecosystem. TCF 2.
|
|
9
|
+
The [IAB Transparency & Consent Framework (TCF)](https://iabeurope.eu/tcf-2-0/) is a standardized protocol for communicating user consent choices to ad tech vendors in the programmatic advertising ecosystem. TCF 2.4 is the current version and is widely adopted across the EU/EEA.
|
|
10
10
|
|
|
11
11
|
When your site participates in the IAB ecosystem (ad exchanges, SSPs, DSPs, DMPs), you need to:
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@ If you self-host the c15t backend or want to operate as your own CMP, register y
|
|
|
26
26
|
|
|
27
27
|
## How c15t Implements TCF
|
|
28
28
|
|
|
29
|
-
c15t provides a complete IAB TCF 2.
|
|
29
|
+
c15t provides a complete IAB TCF 2.4 CMP (Consent Management Platform) implementation:
|
|
30
30
|
|
|
31
31
|
1. **Global Vendor List (GVL)** — Automatically fetched from the c15t backend. Contains the official IAB vendor registry with purposes, features, and stacks.
|
|
32
32
|
2. **IABConsentBanner** — A pre-built banner showing partner count, purpose summaries, and legitimate interest notices.
|
|
@@ -95,7 +95,11 @@ Purposes are grouped into **stacks** by the GVL for a simplified UI presentation
|
|
|
95
95
|
|
|
96
96
|
### Special Features
|
|
97
97
|
|
|
98
|
-
Features like precise geolocation or
|
|
98
|
+
Features like precise geolocation, or identifying devices based on information actively requested, that require explicit opt-in beyond standard consent.
|
|
99
|
+
|
|
100
|
+
### Features
|
|
101
|
+
|
|
102
|
+
Features, such as linking different devices, are means of processing that vendors use only for the purposes the user chooses. They have no consent toggle. The preference center lists them in an informational section with the IAB standard text.
|
|
99
103
|
|
|
100
104
|
### Legitimate Interest
|
|
101
105
|
|
|
@@ -105,11 +109,19 @@ Some purposes can be processed under legitimate interest rather than consent. Us
|
|
|
105
109
|
|
|
106
110
|
Each vendor in the GVL declares which purposes it uses, whether via consent or legitimate interest. The preference center lets users toggle consent per-vendor.
|
|
107
111
|
|
|
112
|
+
## Consent Scope
|
|
113
|
+
|
|
114
|
+
c15t stores TCF choices per site and browser, so every TC string it creates is service-specific. c15t does not sync TCF choices across devices.
|
|
115
|
+
|
|
116
|
+
Do not use `/consent/check` or your own account data to skip the TCF UI on another device. Reusing choices across devices is a multi-device scope, and the TCF requires you to disclose that scope in the first layer of the UI, which the prebuilt IAB components do not do.
|
|
117
|
+
|
|
118
|
+
The `isServiceSpecific` option is deprecated. TCF requires IsServiceSpecific=1 in every TC string, so c15t always encodes `true` and logs a warning if you pass `false`.
|
|
119
|
+
|
|
108
120
|
## Standard vs IAB Components
|
|
109
121
|
|
|
110
122
|
|Feature|ConsentBanner / ConsentDialog|IABConsentBanner / IABConsentDialog|
|
|
111
123
|
|--|--|--|
|
|
112
|
-
|Consent model|opt-in / opt-out|IAB TCF 2.
|
|
124
|
+
|Consent model|opt-in / opt-out|IAB TCF 2.4|
|
|
113
125
|
|Granularity|Category-level (measurement, marketing, etc.)|Purpose-level + vendor-level|
|
|
114
126
|
|Vendor management|No|Yes (full GVL integration)|
|
|
115
127
|
|TC String|No|Yes|
|
|
@@ -73,6 +73,8 @@ For iframes outside of React (e.g., CMS content, server-rendered HTML), add `dat
|
|
|
73
73
|
|
|
74
74
|
When consent for the specified category is granted, c15t automatically swaps `data-src` to `src`, loading the iframe. When consent is revoked, `src` is moved back to `data-src`.
|
|
75
75
|
|
|
76
|
+
The `data-category` value must be one of `necessary`, `functionality`, `measurement`, `experience`, or `marketing`. An iframe with any other value, including an empty one, stays blocked, and c15t logs a warning to the console.
|
|
77
|
+
|
|
76
78
|
### Dynamic Iframes
|
|
77
79
|
|
|
78
80
|
c15t uses a `MutationObserver` to watch for dynamically added iframes. Any iframe with `data-category` added to the DOM after initialization is automatically processed.
|
|
@@ -73,7 +73,7 @@ Available presets:
|
|
|
73
73
|
|Preset|Model|Matches|
|
|
74
74
|
|--|--|--|
|
|
75
75
|
|`europeOptIn()`|`opt-in`|EEA + UK countries + geo fallback|
|
|
76
|
-
|`europeIab()`|`iab`|EEA + UK countries + geo fallback (TCF 2.
|
|
76
|
+
|`europeIab()`|`iab`|EEA + UK countries + geo fallback (TCF 2.4)|
|
|
77
77
|
|`californiaOptOut()`|`opt-out`|US-CA region|
|
|
78
78
|
|`quebecOptIn()`|`opt-in`|CA-QC region|
|
|
79
79
|
|`worldNoBanner()`|`none`|default fallback|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Front Chat
|
|
3
|
+
description: Load Front Chat after functionality consent and initialize the
|
|
4
|
+
widget when its SDK is ready.
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
Front Chat adds a live chat widget connected to your Front inbox. c15t waits for
|
|
8
|
+
functionality consent before loading the widget's SDK and calling `FrontChat('init')`.
|
|
9
|
+
|
|
10
|
+
## Official Front documentation
|
|
11
|
+
|
|
12
|
+
* [Set up a Front Chat inbox and install the widget](https://help.front.com/en/articles/2049)
|
|
13
|
+
* [Chat Widget SDK reference](https://dev.frontapp.com/docs/chat-sdk-reference)
|
|
14
|
+
|
|
15
|
+
## Integrate with c15t
|
|
16
|
+
|
|
17
|
+
Copy the `chatId` from the widget code snippet in your Front Chat channel's
|
|
18
|
+
**Installation** tab. Pass that value to `frontChat()` instead of adding Front's
|
|
19
|
+
script snippet separately.
|
|
20
|
+
|
|
21
|
+
**React**
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { type ReactNode } from 'react';
|
|
25
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
26
|
+
import { frontChat } from '@c15t/scripts/front-chat';
|
|
27
|
+
|
|
28
|
+
const scripts = [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })];
|
|
29
|
+
|
|
30
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
31
|
+
return (
|
|
32
|
+
<ConsentManagerProvider
|
|
33
|
+
options={{
|
|
34
|
+
mode: 'hosted',
|
|
35
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
36
|
+
scripts,
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</ConsentManagerProvider>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Next.js**
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
'use client';
|
|
49
|
+
|
|
50
|
+
import { type ReactNode } from 'react';
|
|
51
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
52
|
+
import { frontChat } from '@c15t/scripts/front-chat';
|
|
53
|
+
|
|
54
|
+
const scripts = [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })];
|
|
55
|
+
|
|
56
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
57
|
+
return (
|
|
58
|
+
<ConsentManagerProvider
|
|
59
|
+
options={{
|
|
60
|
+
mode: 'hosted',
|
|
61
|
+
backendURL: '/api/c15t',
|
|
62
|
+
scripts,
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</ConsentManagerProvider>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**JavaScript**
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
75
|
+
import { frontChat } from '@c15t/scripts/front-chat';
|
|
76
|
+
|
|
77
|
+
getOrCreateConsentRuntime({
|
|
78
|
+
mode: 'hosted',
|
|
79
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
80
|
+
scripts: [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })],
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## How c15t loads it
|
|
85
|
+
|
|
86
|
+
* **Category:** `functionality` (Functional)
|
|
87
|
+
* **Loads when:** functionality consent is granted
|
|
88
|
+
* **Script:** `https://chat-assets.frontapp.com/v1/chat.bundle.js`
|
|
89
|
+
* **After load:** c15t calls `window.FrontChat('init', ...)` with your chat ID and launcher options
|
|
90
|
+
* **On revocation:** c15t reloads the page by default and leaves Front Chat unloaded while functionality consent is denied
|
|
91
|
+
|
|
92
|
+
Keep the default `reloadOnConsentRevoked: true` behavior. Removing a script tag
|
|
93
|
+
does not stop a widget that has already initialized, and this integration does
|
|
94
|
+
not provide automatic widget shutdown when you disable the reload.
|
|
95
|
+
|
|
96
|
+
## Configure the integration
|
|
97
|
+
|
|
98
|
+
`chatId` must be a non-empty string. The default launcher is enabled unless you
|
|
99
|
+
set `useDefaultLauncher` to `false`:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
frontChat({
|
|
103
|
+
chatId: 'YOUR_FRONT_CHAT_ID',
|
|
104
|
+
useDefaultLauncher: false,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
With the default launcher hidden, use Front's SDK to open the widget from your
|
|
109
|
+
own launcher after consent is granted and the widget has initialized. See the
|
|
110
|
+
[SDK reference](https://dev.frontapp.com/docs/chat-sdk-reference) for commands
|
|
111
|
+
and initialization requirements.
|
|
112
|
+
|
|
113
|
+
### Content Security Policy
|
|
114
|
+
|
|
115
|
+
If your Content Security Policy (CSP) uses nonces, pass the server-generated nonce
|
|
116
|
+
for the current response. c15t applies it to the loader script and forwards it
|
|
117
|
+
to Front's initialization call:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
function createChatScripts(nonce: string) {
|
|
121
|
+
return [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID', nonce })];
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Front creates additional resources for the widget. Follow Front's
|
|
126
|
+
[CSP setup instructions](https://help.front.com/en/articles/2049) for the
|
|
127
|
+
remaining policy requirements. You can override the loader URL with `scriptSrc`
|
|
128
|
+
if you serve the SDK through your own proxy; this does not proxy the widget's
|
|
129
|
+
other requests.
|
|
130
|
+
|
|
131
|
+
### Optional session cleanup
|
|
132
|
+
|
|
133
|
+
`frontChat()` does not automatically delete an existing Front session. You can
|
|
134
|
+
also request session cleanup before c15t's revocation reload using
|
|
135
|
+
`shutdownFrontChat()`:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
139
|
+
import { frontChat, shutdownFrontChat } from '@c15t/scripts/front-chat';
|
|
140
|
+
|
|
141
|
+
getOrCreateConsentRuntime({
|
|
142
|
+
mode: 'hosted',
|
|
143
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
144
|
+
scripts: [frontChat({ chatId: 'YOUR_FRONT_CHAT_ID' })],
|
|
145
|
+
callbacks: {
|
|
146
|
+
onBeforeConsentRevocationReload: ({ preferences }) => {
|
|
147
|
+
if (!preferences.functionality) {
|
|
148
|
+
shutdownFrontChat();
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The function calls Front's `shutdown` command with `clearSession: true` when
|
|
156
|
+
the SDK is available. This is a best-effort request: the reload does not wait
|
|
157
|
+
for Front to finish clearing its session. Keep reload on revocation enabled;
|
|
158
|
+
the cleanup call does not replace it.
|
|
159
|
+
|
|
160
|
+
## Types
|
|
161
|
+
|
|
162
|
+
### FrontChatOptions
|
|
163
|
+
|
|
164
|
+
|Property|Value|
|
|
165
|
+
|:--|:--|
|
|
166
|
+
|Type Name|\`FrontChatOptions\`|
|
|
167
|
+
|Source Path|\`./packages/scripts/src/vendors/functional/front-chat.ts\`|
|
|
168
|
+
|
|
169
|
+
\*ExtractedTypeTable: Could not extract "FrontChatOptions" from "./packages/scripts/src/vendors/functional/front-chat.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
170
|
+
|
|
171
|
+
### Script
|
|
172
|
+
|
|
173
|
+
|Property|Value|
|
|
174
|
+
|:--|:--|
|
|
175
|
+
|Type Name|\`Script\`|
|
|
176
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
177
|
+
|
|
178
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: OneDollarStats
|
|
3
|
+
description: Load OneDollarStats after measurement consent with optional tracker
|
|
4
|
+
data attributes.
|
|
5
|
+
group: integrations
|
|
6
|
+
---
|
|
7
|
+
[OneDollarStats](https://onedollarstats.com/) matches events to the domain registered in your dashboard, so no API key is needed. This helper loads its classic deferred script after measurement consent and forwards settings as `data-*` attributes.
|
|
8
|
+
|
|
9
|
+
## Integrate with c15t
|
|
10
|
+
|
|
11
|
+
**React**
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
import { type ReactNode } from 'react';
|
|
15
|
+
import { ConsentManagerProvider } from '@c15t/react';
|
|
16
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
17
|
+
|
|
18
|
+
const scripts = [oneDollarStats()];
|
|
19
|
+
|
|
20
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
21
|
+
return (
|
|
22
|
+
<ConsentManagerProvider
|
|
23
|
+
options={{
|
|
24
|
+
mode: 'hosted',
|
|
25
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
26
|
+
scripts,
|
|
27
|
+
}}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</ConsentManagerProvider>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Next.js**
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
'use client';
|
|
39
|
+
|
|
40
|
+
import { type ReactNode } from 'react';
|
|
41
|
+
import { ConsentManagerProvider } from '@c15t/nextjs';
|
|
42
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
43
|
+
|
|
44
|
+
const scripts = [oneDollarStats()];
|
|
45
|
+
|
|
46
|
+
export function ConsentProvider({ children }: { children: ReactNode }) {
|
|
47
|
+
return (
|
|
48
|
+
<ConsentManagerProvider
|
|
49
|
+
options={{
|
|
50
|
+
mode: 'hosted',
|
|
51
|
+
backendURL: '/api/c15t',
|
|
52
|
+
scripts,
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{children}
|
|
56
|
+
</ConsentManagerProvider>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**JavaScript**
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { getOrCreateConsentRuntime } from 'c15t';
|
|
65
|
+
import { oneDollarStats } from '@c15t/scripts/one-dollar-stats';
|
|
66
|
+
|
|
67
|
+
getOrCreateConsentRuntime({
|
|
68
|
+
mode: 'hosted',
|
|
69
|
+
backendURL: 'https://your-instance.c15t.dev',
|
|
70
|
+
scripts: [oneDollarStats()],
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Tracker settings
|
|
75
|
+
|
|
76
|
+
All settings use strings and omit the `data-` prefix. Unknown settings are forwarded for compatibility with future tracker options.
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
oneDollarStats({
|
|
80
|
+
hostname: 'docs.example.com',
|
|
81
|
+
devmode: 'true',
|
|
82
|
+
autocollect: 'false',
|
|
83
|
+
'hash-routing': 'true',
|
|
84
|
+
url: 'https://analytics.example.com/events',
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
* `hostname` must be a bare hostname, optionally including a port. It overrides the event hostname on every host, including production.
|
|
89
|
+
* Local testing needs both `hostname` and `devmode: 'true'`.
|
|
90
|
+
* `autocollect: 'false'` disables automatic pageview and click collection.
|
|
91
|
+
* `'hash-routing': 'false'` omits the attribute entirely: the CDN tracker enables hash routing whenever the attribute is present, regardless of its value.
|
|
92
|
+
* `url` overrides the collection endpoint. Leave it unset to use the vendor default.
|
|
93
|
+
|
|
94
|
+
The tracker handles browser history navigation itself; no extra router hook is required. See the [vendor installation reference](https://docs.onedollarstats.com/installation) for its settings.
|
|
95
|
+
|
|
96
|
+
## Consent behaviour
|
|
97
|
+
|
|
98
|
+
The script uses the `measurement` category and loads only when that consent is granted. On revocation, c15t removes its script element. Removing a script does not undo code that already executed, including the tracker's history hooks and event listeners. Use c15t's reload-on-revocation behaviour to clear the running tracker, and check measurement consent before making manual tracking calls.
|
|
99
|
+
|
|
100
|
+
## Types
|
|
101
|
+
|
|
102
|
+
### OneDollarStatsOptions
|
|
103
|
+
|
|
104
|
+
|Property|Value|
|
|
105
|
+
|:--|:--|
|
|
106
|
+
|Type Name|\`OneDollarStatsOptions\`|
|
|
107
|
+
|Source Path|\`./packages/scripts/src/vendors/analytics/one-dollar-stats.ts\`|
|
|
108
|
+
|
|
109
|
+
\*ExtractedTypeTable: Could not extract "OneDollarStatsOptions" from "./packages/scripts/src/vendors/analytics/one-dollar-stats.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
110
|
+
|
|
111
|
+
### Script
|
|
112
|
+
|
|
113
|
+
|Property|Value|
|
|
114
|
+
|:--|:--|
|
|
115
|
+
|Type Name|\`Script\`|
|
|
116
|
+
|Source Path|\`./packages/core/src/libs/script-loader/types.ts\`|
|
|
117
|
+
|
|
118
|
+
\*ExtractedTypeTable: Could not extract "Script" from "./packages/core/src/libs/script-loader/types.ts" using base path "/home/runner/work/c15t/c15t". Verify the path/name and that the file is included by your tsconfig.\*
|
|
@@ -94,6 +94,7 @@ Analytics integrations usually require `measurement` consent. Some vendors can r
|
|
|
94
94
|
* [LogRocket](/docs/integrations/logrocket)
|
|
95
95
|
* [Matomo Analytics](/docs/integrations/matomo-analytics)
|
|
96
96
|
* [PostHog](/docs/integrations/posthog)
|
|
97
|
+
* [OneDollarStats](/docs/integrations/one-dollar-stats)
|
|
97
98
|
* [Promptwatch](/docs/integrations/promptwatch)
|
|
98
99
|
* [Pirsch](/docs/integrations/pirsch)
|
|
99
100
|
* [RudderStack](/docs/integrations/rudderstack)
|
|
@@ -107,6 +108,7 @@ Analytics integrations usually require `measurement` consent. Some vendors can r
|
|
|
107
108
|
Functional integrations usually require `functionality` consent. They add optional user-facing capabilities, such as chat widgets, that should only run after the user allows them.
|
|
108
109
|
|
|
109
110
|
* [Crisp](/docs/integrations/crisp)
|
|
111
|
+
* [Front Chat](/docs/integrations/front-chat)
|
|
110
112
|
* [Intercom](/docs/integrations/intercom)
|
|
111
113
|
|
|
112
114
|
## Ads & Pixels
|
|
@@ -120,6 +122,7 @@ Advertising pixels usually require `marketing` consent. Many of them need startu
|
|
|
120
122
|
* [LinkedIn Insight Tag](/docs/integrations/linkedin-insights)
|
|
121
123
|
* [Microsoft UET](/docs/integrations/microsoft-uet)
|
|
122
124
|
* [X (Twitter) Pixel](/docs/integrations/x-pixel)
|
|
125
|
+
* [Pinterest Tag](/docs/integrations/pinterest-tag)
|
|
123
126
|
|
|
124
127
|
## Tag Managers
|
|
125
128
|
|