@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.2
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 +3 -1
- package/dist/aggregate-components.js +1 -1
- package/dist/component-hooks/use-manager.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -0
- package/dist/components/consent-gate/consent-gate.js +2 -0
- package/dist/components/consent-gate/index.js +2 -0
- package/dist/components/preferences/atoms/accordion.js +1 -1
- package/dist/components/preferences/atoms/vendor-list.js +1 -0
- package/dist/components/preferences/index.js +1 -1
- package/dist/consent-gate.js +2 -0
- package/dist/draft.js +1 -1
- package/dist/external-iab-context.js +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/styles.tw3.css +6 -3
- package/dist/utils/deferred-module.js +2 -0
- package/dist/version.js +1 -1
- package/dist-types/aggregate-components.d.ts +2 -2
- package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +1 -1
- package/dist-types/component-hooks/use-manager.d.ts +6 -1
- package/dist-types/components/consent-gate/atoms.d.ts +11 -0
- package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
- package/dist-types/components/consent-gate/index.d.ts +41 -0
- package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
- 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/iab-panel/atoms/purpose-item.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/stack-item.d.ts +1 -1
- package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
- package/dist-types/components/iab-panel/iab-panel.d.ts +1 -1
- package/dist-types/components/iab-panel/index.d.ts +24 -24
- package/dist-types/components/iab-prompt/index.d.ts +17 -17
- package/dist-types/components/panel/atoms/card.d.ts +4 -4
- package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
- package/dist-types/components/panel/index.d.ts +7 -7
- package/dist-types/components/panel/panel.d.ts +2 -2
- package/dist-types/components/panel-link/index.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
- package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
- package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
- package/dist-types/components/panel-trigger/index.d.ts +4 -4
- package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
- package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -9
- package/dist-types/components/panel-trigger/types.d.ts +1 -1
- package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
- package/dist-types/components/preferences/atoms/button.d.ts +1 -1
- package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
- package/dist-types/components/preferences/atoms/root.d.ts +1 -1
- package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
- package/dist-types/components/preferences/index.d.ts +13 -11
- package/dist-types/components/preferences/policy-actions.d.ts +2 -2
- package/dist-types/components/preferences/preferences.d.ts +1 -1
- package/dist-types/components/preferences/types.d.ts +1 -1
- package/dist-types/components/prompt/components.d.ts +3 -3
- package/dist-types/components/prompt/index.d.ts +11 -11
- package/dist-types/components/prompt/policy-actions.d.ts +2 -2
- package/dist-types/components/prompt/prompt.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 +2 -2
- package/dist-types/components/shared/primitives/button.types.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/consent-gate.d.ts +1 -0
- package/dist-types/context/index.d.ts +3 -3
- package/dist-types/context/theme-context.d.ts +1 -1
- package/dist-types/draft.d.ts +53 -1
- package/dist-types/headless.d.ts +7 -7
- package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
- package/dist-types/hooks/use-iab-manager.d.ts +1 -1
- package/dist-types/hooks/use-theme.d.ts +1 -1
- package/dist-types/hooks.d.ts +28 -1
- package/dist-types/iab.d.ts +5 -5
- package/dist-types/index.d.ts +25 -25
- package/dist-types/module-hooks.d.ts +4 -4
- package/dist-types/panel-link.d.ts +1 -1
- package/dist-types/panel-trigger.d.ts +1 -1
- package/dist-types/panel.d.ts +1 -1
- package/dist-types/preferences.d.ts +1 -1
- 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/prompt.d.ts +1 -1
- package/dist-types/provider.d.ts +22 -5
- package/dist-types/server/fetch-ssr-data.d.ts +1 -1
- package/dist-types/server/index.d.ts +5 -5
- package/dist-types/theme-provider.d.ts +2 -2
- package/dist-types/types/index.d.ts +3 -3
- package/dist-types/types/manager.d.ts +1 -1
- package/dist-types/types/theme/index.d.ts +1 -1
- package/dist-types/ui-config-context.d.ts +1 -1
- package/dist-types/utils/deferred-module.d.ts +11 -0
- package/dist-types/utils/index.d.ts +4 -4
- package/dist-types/utils/merge-slot-props.d.ts +2 -2
- package/dist-types/utils/merge-styles.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 +3 -1
- package/docs/frameworks/react/components/consent-dialog.md +1 -1
- package/docs/frameworks/react/components/{frame.md → consent-gate.md} +27 -27
- package/docs/frameworks/react/components/consent-manager-provider.md +5 -1
- package/docs/frameworks/react/components/consent-widget.md +39 -6
- package/docs/frameworks/react/concepts/consent-categories.md +31 -2
- package/docs/guides/deployment-modes.md +12 -0
- package/docs/integrations/building-integrations.md +5 -0
- package/docs/integrations/cloudflare-zaraz.md +399 -0
- package/docs/integrations/google-maps.md +20 -20
- package/docs/integrations/granular-consent.md +208 -0
- package/docs/integrations/overview.md +5 -4
- package/docs/integrations/youtube.md +26 -21
- package/docs/upgrade-v3.md +47 -0
- package/package.json +26 -16
- package/dist/components/frame/atoms.js +0 -1
- package/dist/components/frame/frame.js +0 -2
- package/dist/components/frame/index.js +0 -2
- package/dist/frame.js +0 -2
- package/dist-types/components/frame/atoms.d.ts +0 -11
- package/dist-types/components/frame/frame.d.ts +0 -2
- package/dist-types/components/frame/index.d.ts +0 -24
- package/dist-types/frame.d.ts +0 -1
- package/readme.json +0 -48
- package/src/iab/styles.css +0 -11
- package/src/styles.css +0 -10
- /package/dist/components/{frame → consent-gate}/types.js +0 -0
package/docs/README.md
CHANGED
|
@@ -25,10 +25,10 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
|
|
|
25
25
|
- [ConsentDialog](./frameworks/react/components/consent-dialog.md): Open the c15t preference center as a modal ConsentDialog in a React app, wire its triggers and control blocking, focus and policy gating.
|
|
26
26
|
- [ConsentDialogLink](./frameworks/react/components/consent-dialog-link.md): Add a ConsentDialogLink to a React footer so visitors reopen the c15t preference center from your own text link, with asChild and rights data.
|
|
27
27
|
- [ConsentDialogTrigger](./frameworks/react/components/consent-dialog-trigger.md): Floating button and toolbar that reopen the preference center after the first prompt.
|
|
28
|
+
- [ConsentGate](./frameworks/react/components/consent-gate.md): Gate a YouTube or map iframe behind consent with ConsentGate in React, showing a placeholder that opens the preference center until the category is allowed.
|
|
28
29
|
- [ConsentProvider](./frameworks/react/components/consent-manager-provider.md): Configure the v3 consent runtime and share its state with child components.
|
|
29
30
|
- [ConsentWidget](./frameworks/react/components/consent-widget.md): Embed the c15t preference center inline with ConsentWidget on a React privacy page, with draft toggles that record a choice only on Save.
|
|
30
31
|
- [DevTools](./frameworks/react/components/dev-tools.md): A development tool for inspecting consent state, geolocation, loaded scripts, and consent events in real time.
|
|
31
|
-
- [Frame](./frameworks/react/components/frame.md): Gate a YouTube or map iframe behind consent with Frame in React, showing a placeholder that opens the preference center until the category is allowed.
|
|
32
32
|
- [Consent categories](./frameworks/react/concepts/consent-categories.md): Assign optional features to categories and understand how policy scope affects permission.
|
|
33
33
|
- [Policy presets](./frameworks/react/concepts/policy-presets.md): Understand how policy rules affect React prompts, permissions and persistent privacy controls.
|
|
34
34
|
- [Headless](./frameworks/react/headless.md): Build a custom consent banner in React with the c15t/react/headless hooks inside your ConsentProvider.
|
|
@@ -64,12 +64,14 @@ These docs describe v3. Start with Inth hosted setup, identify the framework, ro
|
|
|
64
64
|
- [Clear on revocation](./integrations/clear-on-revocation.md): Remove configured first-party cookies and Web Storage keys when their consent category is denied.
|
|
65
65
|
- [Clearbit](./integrations/clearbit.md): Configure Clearbit with c15t v3, understand marketing permission and verify loading and revocation.
|
|
66
66
|
- [Cloudflare Web Analytics](./integrations/cloudflare-web-analytics.md): Configure Cloudflare Web Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
67
|
+
- [Cloudflare Zaraz](./integrations/cloudflare-zaraz.md): Synchronize c15t permissions with Zaraz purposes while Cloudflare manages your tools.
|
|
67
68
|
- [Crisp](./integrations/crisp.md): Configure Crisp with c15t v3, understand functionality permission and verify loading and revocation.
|
|
68
69
|
- [Databuddy](./integrations/databuddy.md): Configure Databuddy's initial and updated consent state with c15t v3.
|
|
69
70
|
- [Fathom Analytics](./integrations/fathom-analytics.md): Configure Fathom Analytics with c15t v3, understand measurement permission and verify loading and revocation.
|
|
70
71
|
- [Google Maps](./integrations/google-maps.md): Prevent a map iframe from mounting before the required permission.
|
|
71
72
|
- [Google Tag](./integrations/google-tag.md): Configure gtag with c15t Consent Mode signals and understand its loading behavior.
|
|
72
73
|
- [Google Tag Manager](./integrations/google-tag-manager.md): Load GTM with c15t consent signals and verify the tags inside your container.
|
|
74
|
+
- [Granular consent](./integrations/granular-consent.md): Let visitors grant a category and still turn one vendor off, without adopting IAB TCF.
|
|
73
75
|
- [Heap](./integrations/heap.md): Configure Heap with c15t v3, understand measurement permission and verify loading and revocation.
|
|
74
76
|
- [Hightouch](./integrations/hightouch.md): Configure Hightouch with c15t v3, understand measurement permission and verify loading and revocation.
|
|
75
77
|
- [Hotjar](./integrations/hotjar.md): Configure Hotjar with c15t v3, understand measurement permission and verify loading and revocation.
|
|
@@ -93,7 +93,7 @@ it is `dialog`. These set that surface:
|
|
|
93
93
|
* The Customize button on a `ConsentBanner`, and the "Manage preferences"
|
|
94
94
|
or "Do not sell or share my data" button a notice renders.
|
|
95
95
|
* `ConsentDialogLink` and `ConsentDialogTrigger`.
|
|
96
|
-
* The button in a `
|
|
96
|
+
* The button in a `ConsentGate` placeholder.
|
|
97
97
|
* `useSetActiveUI()('dialog')` in your own component, or `openDialog()`
|
|
98
98
|
from `useHeadlessConsentUI()` on the headless subpath.
|
|
99
99
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description: Gate a YouTube or map iframe behind consent with
|
|
4
|
-
showing a placeholder that opens the preference center until the
|
|
5
|
-
allowed.
|
|
2
|
+
title: ConsentGate
|
|
3
|
+
description: Gate a YouTube or map iframe behind consent with ConsentGate in
|
|
4
|
+
React, showing a placeholder that opens the preference center until the
|
|
5
|
+
category is allowed.
|
|
6
6
|
group: frameworks
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Gate an embed behind consent
|
|
10
10
|
|
|
11
|
-
`
|
|
11
|
+
`ConsentGate` mounts its children only while the effective permission for one
|
|
12
12
|
consent category is granted, and shows a placeholder otherwise. Wrap any
|
|
13
13
|
iframe or third-party widget that would set cookies or contact a vendor on
|
|
14
14
|
load. Render it anywhere inside the `ConsentProvider` from your
|
|
@@ -16,11 +16,11 @@ load. Render it anywhere inside the `ConsentProvider` from your
|
|
|
16
16
|
placeholder button opens.
|
|
17
17
|
|
|
18
18
|
```tsx title="src/product-video.tsx"
|
|
19
|
-
import {
|
|
19
|
+
import { ConsentGate } from 'c15t/react';
|
|
20
20
|
|
|
21
21
|
export function ProductVideo() {
|
|
22
22
|
return (
|
|
23
|
-
<
|
|
23
|
+
<ConsentGate category="marketing" className="video-frame">
|
|
24
24
|
<iframe
|
|
25
25
|
src="https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ"
|
|
26
26
|
title="Product tour"
|
|
@@ -28,18 +28,18 @@ export function ProductVideo() {
|
|
|
28
28
|
allowFullScreen
|
|
29
29
|
style={{ width: '100%', aspectRatio: '16 / 9', border: 0 }}
|
|
30
30
|
/>
|
|
31
|
-
</
|
|
31
|
+
</ConsentGate>
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
`marketing` must be in your policy scope. If you set a non-empty
|
|
37
37
|
`options.consentCategories` list on `ConsentProvider`, include `marketing`
|
|
38
|
-
there too so the preference center can display and save it. `
|
|
38
|
+
there too so the preference center can display and save it. `ConsentGate` does
|
|
39
39
|
not add categories to that list.
|
|
40
40
|
|
|
41
41
|
The placeholder names the category using its title from your translations. Set `className` or `style`
|
|
42
|
-
on `
|
|
42
|
+
on `ConsentGate` to reserve the embed's space, so the page does not shift when the
|
|
43
43
|
placeholder is replaced.
|
|
44
44
|
|
|
45
45
|
## Props
|
|
@@ -51,22 +51,22 @@ placeholder is replaced.
|
|
|
51
51
|
| `placeholder` | `ReactNode` | built-in placeholder | Replaces the built-in title and button while the category is not allowed. Falsy values such as `null`, `false`, `0` and an empty string use the built-in placeholder. Pass an empty fragment, `<></>`, to render no placeholder content. |
|
|
52
52
|
|
|
53
53
|
Other `div` attributes such as `className`, `style` and `ref` apply to the
|
|
54
|
-
wrapper element that stays in the page in both states. `
|
|
54
|
+
wrapper element that stays in the page in both states. `ConsentGateProps` also
|
|
55
55
|
declares `noStyle` and `theme`, but the component does not apply them yet;
|
|
56
56
|
style the wrapper with `className` and theme the placeholder through the
|
|
57
57
|
provider `theme` option.
|
|
58
58
|
|
|
59
59
|
## Behavior
|
|
60
60
|
|
|
61
|
-
`
|
|
61
|
+
`ConsentGate` renders a `div` wrapper. Inside it, when the effective permission for
|
|
62
62
|
`category` is granted, it renders the children; otherwise it renders the
|
|
63
63
|
placeholder. Permission is the same value `useConsent(category)` returns,
|
|
64
64
|
so it can be granted under an opt-out rule before the visitor records a
|
|
65
65
|
choice, and a recorded grant can be overridden by a privacy signal.
|
|
66
66
|
|
|
67
67
|
While effective permission is denied, the children are absent from the DOM,
|
|
68
|
-
so an iframe or a third-party widget inside `
|
|
69
|
-
children unmount and the embed disappears. `
|
|
68
|
+
so an iframe or a third-party widget inside `ConsentGate` sends no requests. When the visitor later revokes it, the
|
|
69
|
+
children unmount and the embed disappears. `ConsentGate` does not depend on the
|
|
70
70
|
network blocker or the iframe blocker modules; use those for markup you
|
|
71
71
|
cannot wrap in a component.
|
|
72
72
|
|
|
@@ -89,13 +89,13 @@ A grant in the request cookie allows the embed only when policy and privacy
|
|
|
89
89
|
signals permit it. Browser privacy signals detected during hydration can
|
|
90
90
|
withdraw that permission. In a browser-only setup the
|
|
91
91
|
provider has no permission until it resolves policy on the client, so
|
|
92
|
-
`
|
|
92
|
+
`ConsentGate` shows the placeholder first and swaps in the embed after resolution
|
|
93
93
|
when the category is already granted.
|
|
94
94
|
|
|
95
|
-
`
|
|
95
|
+
`ConsentGate` is one component on this page; the per-vendor embed guides for
|
|
96
96
|
[YouTube](../../../integrations/youtube.md) and
|
|
97
97
|
[Google Maps](../../../integrations/google-maps.md) show a complete embed
|
|
98
|
-
configuration with sizing, titles and the same `
|
|
98
|
+
configuration with sizing, titles and the same `ConsentGate` usage across
|
|
99
99
|
frameworks.
|
|
100
100
|
|
|
101
101
|
To read the same permission in your own components, use `useConsent` from
|
|
@@ -104,24 +104,24 @@ also import from there.
|
|
|
104
104
|
|
|
105
105
|
## Composition
|
|
106
106
|
|
|
107
|
-
The placeholder parts are available as `
|
|
108
|
-
`
|
|
109
|
-
behavior. `
|
|
107
|
+
The placeholder parts are available as `ConsentGate.Root`, `ConsentGate.Title` and
|
|
108
|
+
`ConsentGate.Button` for a custom placeholder that keeps the built-in copy and
|
|
109
|
+
behavior. `ConsentGate.Title` and `ConsentGate.Button` accept `category` and fill in the
|
|
110
110
|
translated text; pass children to either to replace it.
|
|
111
111
|
|
|
112
112
|
```tsx
|
|
113
|
-
<
|
|
113
|
+
<ConsentGate
|
|
114
114
|
category="marketing"
|
|
115
115
|
placeholder={
|
|
116
|
-
<
|
|
117
|
-
<
|
|
116
|
+
<ConsentGate.Root>
|
|
117
|
+
<ConsentGate.Title category="marketing" />
|
|
118
118
|
<p>The video is also available on our channel.</p>
|
|
119
|
-
<
|
|
120
|
-
</
|
|
119
|
+
<ConsentGate.Button category="marketing">Choose cookies</ConsentGate.Button>
|
|
120
|
+
</ConsentGate.Root>
|
|
121
121
|
}
|
|
122
122
|
>
|
|
123
123
|
<iframe src="https://www.youtube-nocookie.com/embed/..." title="Product tour" />
|
|
124
|
-
</
|
|
124
|
+
</ConsentGate>
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
The built-in placeholder carries `data-testid="frame-placeholder"` and its
|
|
@@ -131,7 +131,7 @@ button `data-testid="frame-open-dialog"`.
|
|
|
131
131
|
|
|
132
132
|
The placeholder is plain text and a `button`, so it is readable and
|
|
133
133
|
operable without the embed. Give the iframe a descriptive `title`, and keep a
|
|
134
|
-
transcript, address or link outside the `
|
|
134
|
+
transcript, address or link outside the `ConsentGate` for visitors who decline
|
|
135
135
|
the category. A denied category may be fixed by policy, so opening the
|
|
136
136
|
preference center does not guarantee that the visitor can grant it.
|
|
137
137
|
|
|
@@ -58,7 +58,11 @@ signals. Hydration and notice dismissal do not become explicit choices.
|
|
|
58
58
|
|
|
59
59
|
An externally owned runtime can be passed through `runtime`. Its owner must
|
|
60
60
|
start and dispose it. A provider borrowing that runtime must not initialize or
|
|
61
|
-
dispose a second copy.
|
|
61
|
+
dispose a second copy. Keep the runtime stable for the provider's lifetime and
|
|
62
|
+
unmount the borrowing provider when disposing the runtime. IAB actions taken
|
|
63
|
+
before its handle is ready wait for that handle. If the provider unmounts first,
|
|
64
|
+
a pending `save()` rejects with an `AbortError` instead of waiting indefinitely.
|
|
65
|
+
See [consent state](../../../guides/consent-state.md) and
|
|
62
66
|
[deployment modes](../../../guides/deployment-modes.md).
|
|
63
67
|
|
|
64
68
|
## Clear data when consent is denied
|
|
@@ -85,6 +85,28 @@ Privacy Control overrides shows a note under its row: "Your saved choice is
|
|
|
85
85
|
restricted by the current privacy settings." The switch still reflects the
|
|
86
86
|
saved value; the effective permission is off.
|
|
87
87
|
|
|
88
|
+
### Vendors
|
|
89
|
+
|
|
90
|
+
When the provider declares `vendors`, each category's expanded description
|
|
91
|
+
ends with one card per vendor whose category condition names that category,
|
|
92
|
+
styled like a category row: the vendor's name and a switch on the header,
|
|
93
|
+
and its description and privacy policy link behind the card's own expand
|
|
94
|
+
control. Cards start collapsed, so a long list stays one line per vendor,
|
|
95
|
+
and the category list scrolls inside the dialog rather than growing it.
|
|
96
|
+
Vendor switches edit the same draft as the category
|
|
97
|
+
switches and record on Save. Saving with one vendor off denies that vendor
|
|
98
|
+
only; the category stays granted and its other vendors keep loading. While
|
|
99
|
+
the category is off in the draft the vendor switches are disabled, with the
|
|
100
|
+
hint "Turn on this category to choose vendors." A vendor declared
|
|
101
|
+
`disabled`, or one that only falls under `necessary`, is listed without a
|
|
102
|
+
switch. Accept all and Reject all clear every vendor denial, including one
|
|
103
|
+
staged but not yet saved. Under an `iab` policy no vendor rows render.
|
|
104
|
+
Vendors that are only referenced by a script slug, without a name and
|
|
105
|
+
privacy policy URL, still gate loading but are not listed, and so does a
|
|
106
|
+
vendor whose condition negates a category, since no category row can
|
|
107
|
+
host it. See
|
|
108
|
+
[granular consent](../../../integrations/granular-consent.md).
|
|
109
|
+
|
|
88
110
|
### Actions
|
|
89
111
|
|
|
90
112
|
The preference center always renders Reject all, Accept all and Save, with
|
|
@@ -102,8 +124,12 @@ such as `['disclosure']`, renders the widget and Save completes without
|
|
|
102
124
|
writing a consent record.
|
|
103
125
|
|
|
104
126
|
For a fully custom preference center, `useConsentDraft()` returns the same
|
|
105
|
-
draft: `values`, `displayedCategories`, `
|
|
106
|
-
`update`, `acceptAll`, `rejectAll`, `save` and `reset`.
|
|
127
|
+
draft: `values`, `displayedCategories`, `vendors`, `isDirty`, `isStale`,
|
|
128
|
+
`set`, `update`, `setVendor`, `acceptAll`, `rejectAll`, `save` and `reset`.
|
|
129
|
+
A custom vendor control alone takes `useVendorDraft()`, the vendor slice of
|
|
130
|
+
that draft: `vendors`, `setVendor`, `isDirty`, `isStale`, `save` and `reset`.
|
|
131
|
+
`useDeclaredVendors()`, `useVendorChoice()` and `useVendorAllowed(id)` read
|
|
132
|
+
the declared list, the recorded denials and one vendor's effective result.
|
|
107
133
|
|
|
108
134
|
`useConsentDraft` and `ConsentDraftProvider` import from `c15t/react`.
|
|
109
135
|
|
|
@@ -112,7 +138,10 @@ draft: `values`, `displayedCategories`, `isDirty`, `isStale`, `set`,
|
|
|
112
138
|
Each row is a disclosure: a button that expands the category description
|
|
113
139
|
and a switch beside it, so a visitor can read the description without
|
|
114
140
|
changing the choice. Each switch has the category title as its accessible
|
|
115
|
-
name.
|
|
141
|
+
name. A category's vendor cards sit in a `region` named "Vendors" with the
|
|
142
|
+
count; each card's expand button carries `aria-expanded`, each vendor
|
|
143
|
+
switch is named "Allow" followed by the vendor name, and is described by
|
|
144
|
+
the vendor's name element. The policy-change alert uses `role="alert"`, and a restriction note is
|
|
116
145
|
an `output` element linked to its switch through `aria-describedby`. The
|
|
117
146
|
root's `dir` attribute follows the active language.
|
|
118
147
|
|
|
@@ -122,7 +151,8 @@ Every part is available as `ConsentWidget.<Part>`. `Root` provides the
|
|
|
122
151
|
draft and accepts `noStyle`, `disableAnimation` and `uiSource`. `Accordion`
|
|
123
152
|
and `AccordionItems` render the stock rows; `AccordionItem`,
|
|
124
153
|
`AccordionTrigger`, `AccordionTriggerInner`, `AccordionContent`,
|
|
125
|
-
`AccordionArrow` and `Switch` build your own
|
|
154
|
+
`AccordionArrow` and `Switch` build your own; `VendorList` renders one
|
|
155
|
+
category's vendor rows and takes a `category` prop. `PolicyActions` renders the
|
|
126
156
|
resolved actions in `Footer` and `FooterSubGroup` and accepts `renderAction`
|
|
127
157
|
to replace one button; `AcceptAllButton`, `RejectButton`, `SaveButton` and
|
|
128
158
|
`CustomizeButton` are the individual buttons.
|
|
@@ -155,8 +185,11 @@ export function PreferenceCenter() {
|
|
|
155
185
|
Provider component slots for the stock structure are `manager.root`,
|
|
156
186
|
`manager.footer`, `manager.actionGroup`, `accordion.root`,
|
|
157
187
|
`accordion.triggerRow`, `accordion.title`, `accordion.control`,
|
|
158
|
-
`accordion-item.root`, `accordion-item.trigger`, `accordion-item.content
|
|
159
|
-
|
|
188
|
+
`accordion-item.root`, `accordion-item.trigger`, `accordion-item.content`,
|
|
189
|
+
`vendor-list.root`, `vendor-list.trigger`, `vendor-list.content`,
|
|
190
|
+
`vendor-list.item`, `vendor-list.header`,
|
|
191
|
+
`vendor-list.name`, `vendor-list.description`, `vendor-list.link`,
|
|
192
|
+
`vendor-list.control` and `tag.manager`.
|
|
160
193
|
|
|
161
194
|
The compound parts import from `c15t/react` as properties of `ConsentWidget`.
|
|
162
195
|
See [Styling](../styling/overview.md) for slots and tokens.
|
|
@@ -17,8 +17,23 @@ group: frameworks
|
|
|
17
17
|
|
|
18
18
|
`necessary` is always permitted. Assign categories based on what an integration
|
|
19
19
|
does in your application; renaming analytics to necessary does not change its
|
|
20
|
-
purpose.
|
|
21
|
-
|
|
20
|
+
purpose.
|
|
21
|
+
|
|
22
|
+
c15t discovers categories from registered scripts, network rules, React `ConsentGate`
|
|
23
|
+
components, and iframes with `data-category` handled by the iframe blocker.
|
|
24
|
+
The browser client also discovers inert scripts tagged with `data-c15t-category`.
|
|
25
|
+
Compound script and network conditions contribute every category they reference.
|
|
26
|
+
|
|
27
|
+
Discovered categories are added to `consentCategories`, when supplied. The dialog
|
|
28
|
+
always includes Necessary and offers the optional categories in that combined
|
|
29
|
+
set that are also in the resolved policy scope. Choice completion uses the same
|
|
30
|
+
set. If neither configuration nor integrations supply categories, the dialog
|
|
31
|
+
uses the full policy scope.
|
|
32
|
+
|
|
33
|
+
Categories discovered later are added immediately and retained until the provider
|
|
34
|
+
or runtime is recreated. Adding a category can require a new choice; removing a
|
|
35
|
+
script or unmounting a frame does not remove its category or erase consent.
|
|
36
|
+
Discovery does not grant consent or change backend permission restrictions.
|
|
22
37
|
|
|
23
38
|
## Respect policy scope
|
|
24
39
|
|
|
@@ -28,6 +43,20 @@ only some optional categories, set `scopeMode` explicitly. An omitted scope,
|
|
|
28
43
|
`['*']`, or a list containing only `necessary` expands to the default optional
|
|
29
44
|
categories; a necessary-only list is not a shortcut for disabling all tracking.
|
|
30
45
|
|
|
46
|
+
For example, a backend rule with `categories: ['necessary']` and scripts assigned
|
|
47
|
+
to `marketing` and `measurement` displays Necessary, Marketing, and Analytics,
|
|
48
|
+
even without `consentCategories`. Accept All records both optional choices and
|
|
49
|
+
keeps the banner dismissed after reload. An explicit list of
|
|
50
|
+
`['necessary', 'measurement']` with no other integrations displays Necessary and
|
|
51
|
+
Analytics.
|
|
52
|
+
|
|
53
|
+
Hidden optional categories do not need a choice to dismiss the banner. Their
|
|
54
|
+
permissions still follow the backend policy, so hidden opt-in categories remain
|
|
55
|
+
denied without a valid grant. React providers enable DOM iframe blocking and
|
|
56
|
+
discovery by default; set `iframeBlocker: false` to disable it, or
|
|
57
|
+
`iframeBlocker: { disableAutomaticBlocking: true }` to scan manually with
|
|
58
|
+
`useIframeBlocker({ disableAutomaticBlocking: true }).processAllIframes()`.
|
|
59
|
+
|
|
31
60
|
Use effective permissions to gate work and explicit choices to inspect what the
|
|
32
61
|
visitor confirmed. Read [consent state](../../../guides/consent-state.md) for that
|
|
33
62
|
distinction and [migration](../../../upgrade-v3.md) for v3 policy configuration.
|
|
@@ -30,6 +30,18 @@ in your application while consent writes still go to Inth. Regular backend
|
|
|
30
30
|
browser setup. See [data fetching and transports](./data-fetching.md) for
|
|
31
31
|
the comparison, including custom transports and offline mode.
|
|
32
32
|
|
|
33
|
+
Manifest resolution removes the per-visitor `/init` request, and with it the
|
|
34
|
+
backend's only count of visitors. The server adapters replace it with a session
|
|
35
|
+
report: after each resolution, on a server-rendered page or the same-origin
|
|
36
|
+
init route, the host posts a small report to the backend's `POST /sessions`,
|
|
37
|
+
server-to-server and detached from the response. The browser makes no request
|
|
38
|
+
and the report stores no identity; the visitor's IP and user agent travel as
|
|
39
|
+
forwarded headers under the backend's usual IP handling. Each report is one
|
|
40
|
+
resolution; a page view can produce a `render` and a `route` report, and the
|
|
41
|
+
consuming side groups them into sessions by address and user agent within a
|
|
42
|
+
window. Static output resolves in the browser and sends none. Set `reportSessions: false` on an adapter to turn
|
|
43
|
+
it off.
|
|
44
|
+
|
|
33
45
|
## Match initialization to your application output
|
|
34
46
|
|
|
35
47
|
| Application output | Initial state | Required setup |
|
|
@@ -31,6 +31,11 @@ Replace the example URL and implement the vendor's initialization. This is a
|
|
|
31
31
|
loader template, not a functioning analytics SDK. The script stays blocked
|
|
32
32
|
while measurement permission is denied.
|
|
33
33
|
|
|
34
|
+
Add `vendor: 'example-analytics'` and declare the vendor in the runtime's
|
|
35
|
+
`vendors` option or in the backend manifest when visitors should be able to
|
|
36
|
+
turn this vendor off inside a granted category. See
|
|
37
|
+
[granular consent](./granular-consent.md).
|
|
38
|
+
|
|
34
39
|
## Define revocation deliberately
|
|
35
40
|
|
|
36
41
|
`onConsentChange` receives current permission information. Use it to update the
|