@c15t/react 3.0.0-alpha.8 → 3.0.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 +10 -12
- package/README.md +41 -70
- package/SKILL.md +1 -1
- package/dist/aggregate-components.js +1 -1
- package/dist/components/consent-gate/atoms.js +1 -1
- package/dist/components/consent-gate/frame.js +2 -0
- package/dist/components/consent-gate/index.js +1 -1
- package/dist/components/iab-panel/atoms/root.js +1 -1
- package/dist/components/iab-panel/iab-panel.js +1 -1
- package/dist/components/iab-prompt/atoms/root.js +1 -1
- package/dist/components/iab-prompt/iab-prompt.js +1 -1
- package/dist/components/panel/atoms/root.js +1 -1
- package/dist/components/panel-trigger/atoms/root.js +1 -1
- package/dist/components/panel-trigger/panel-trigger.js +1 -1
- package/dist/components/panel-trigger/toolbar-loader.js +2 -0
- package/dist/components/preferences/atoms/root.js +1 -1
- package/dist/components/prompt/atoms/early-tap-script.js +2 -0
- package/dist/components/prompt/atoms/root.js +1 -1
- package/dist/components/prompt/prompt.js +1 -1
- package/dist/components/shared/dialog-sheets.js +1 -0
- package/dist/components/shared/first-paint-sheets.js +1 -0
- package/dist/components/shared/iab-dialog-sheets.js +1 -0
- package/dist/components/shared/iab-first-paint-sheets.js +1 -0
- package/dist/components/shared/primitives/button.js +1 -1
- package/dist/components/shared/surface-styles.js +2 -0
- package/dist/consent-gate.js +1 -1
- package/dist/context/index.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/hooks/use-iab-policy-guard.js +1 -0
- package/dist/iab/styles.tw3.css +2 -2
- package/dist/iab-context.js +1 -1
- package/dist/iab-dialog-deferred.js +2 -0
- package/dist/iab.js +1 -1
- package/dist/index-parts/consent-gate.js +1 -1
- package/dist/index-parts/core.js +1 -1
- package/dist/index-parts/frame.js +1 -0
- package/dist/index-parts/hosted.js +1 -0
- package/dist/index-parts/offline.js +1 -0
- package/dist/index-parts/presets.js +1 -0
- package/dist/index.js +1 -1
- package/dist/modes.js +1 -0
- package/dist/panel-link.js +1 -1
- package/dist/panel-trigger.js +1 -1
- package/dist/provider.js +1 -1
- package/dist/styles.tw3.css +2 -2
- package/dist/transports/hosted.js +1 -0
- package/dist/transports/manifest.js +1 -0
- package/dist/utils/deferred-module.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/chunk-warming.d.ts +7 -6
- package/dist-types/components/consent-gate/frame.d.ts +19 -0
- package/dist-types/components/consent-gate/index.d.ts +3 -19
- package/dist-types/components/iab-prompt/iab-prompt.d.ts +1 -1
- package/dist-types/components/panel/index.d.ts +1 -1
- package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
- package/dist-types/components/preferences/index.d.ts +1 -1
- package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
- package/dist-types/components/prompt/index.d.ts +1 -1
- package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
- package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
- package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
- package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
- package/dist-types/components/shared/surface-styles.d.ts +60 -0
- package/dist-types/consent-gate.d.ts +1 -1
- package/dist-types/context/index.d.ts +3 -3
- package/dist-types/context.d.ts +2 -0
- package/dist-types/gpp.d.ts +1 -1
- package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
- package/dist-types/iab-dialog-deferred.d.ts +36 -0
- package/dist-types/iab.d.ts +3 -2
- package/dist-types/index-parts/consent-gate.d.ts +1 -1
- package/dist-types/index-parts/core.d.ts +1 -2
- package/dist-types/index-parts/frame.d.ts +7 -0
- package/dist-types/index-parts/hosted.d.ts +7 -0
- package/dist-types/index-parts/offline.d.ts +7 -0
- package/dist-types/index-parts/presets.d.ts +7 -0
- package/dist-types/index.d.ts +5 -1
- package/dist-types/modes.d.ts +26 -0
- package/dist-types/panel-link.d.ts +1 -1
- package/dist-types/panel-trigger.d.ts +1 -1
- package/dist-types/provider.d.ts +22 -4
- package/dist-types/transports/hosted.d.ts +36 -0
- package/dist-types/transports/manifest.d.ts +48 -0
- package/dist-types/ui-config-context.d.ts +4 -0
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +10 -12
- package/docs/concepts/choose-your-setup.md +45 -8
- package/docs/concepts/consent-categories.md +1 -1
- package/docs/concepts/consent-state.md +5 -2
- package/docs/concepts/data-fetching.md +100 -40
- package/docs/concepts/modes.md +281 -0
- package/docs/customization/dark-mode.md +1 -1
- package/docs/customization/motion.md +2 -2
- package/docs/customization/overview.md +3 -2
- package/docs/customization/recipes.md +4 -4
- package/docs/customization/slots.md +25 -25
- package/docs/customization/stylesheets.md +161 -50
- package/docs/customization/tailwind.md +71 -50
- package/docs/customization/tokens.md +42 -13
- package/docs/frameworks/react/components/consent-banner.md +14 -12
- package/docs/frameworks/react/components/consent-dialog.md +15 -13
- package/docs/frameworks/react/components/consent-provider.md +51 -46
- package/docs/frameworks/react/components.md +16 -13
- package/docs/frameworks/react/compose.md +3 -3
- package/docs/frameworks/react/content-security-policy.md +35 -12
- package/docs/frameworks/react/customize.md +21 -13
- package/docs/frameworks/react/hooks.md +2 -2
- package/docs/frameworks/react/iab.md +56 -6
- package/docs/frameworks/react/quickstart.md +65 -99
- package/docs/frameworks/react/rendering.md +170 -94
- package/docs/frameworks/react/scripts.md +19 -30
- package/docs/frameworks/react/troubleshooting.md +100 -32
- package/docs/frameworks/react/upgrade-v3.md +133 -79
- package/docs/frameworks/react/vendor-consent.md +19 -7
- package/docs/guides/banner-experiments.md +21 -8
- package/docs/guides/troubleshooting.md +90 -26
- package/docs/guides/verify-consent.md +23 -8
- package/docs/integrations/adobe-analytics.md +60 -64
- package/docs/integrations/ahrefs-analytics.md +58 -63
- package/docs/integrations/amplitude.md +60 -64
- package/docs/integrations/clearbit.md +59 -63
- package/docs/integrations/cloudflare-web-analytics.md +56 -60
- package/docs/integrations/cloudflare-zaraz.md +55 -57
- package/docs/integrations/crisp.md +64 -69
- package/docs/integrations/databuddy.md +62 -64
- package/docs/integrations/fathom-analytics.md +56 -60
- package/docs/integrations/front-chat.md +56 -60
- package/docs/integrations/google-maps.md +25 -13
- package/docs/integrations/google-tag-manager.md +153 -77
- package/docs/integrations/google-tag.md +134 -78
- package/docs/integrations/heap.md +56 -60
- package/docs/integrations/hightouch.md +55 -60
- package/docs/integrations/hotjar.md +60 -64
- package/docs/integrations/intercom.md +55 -60
- package/docs/integrations/klaviyo.md +65 -66
- package/docs/integrations/linkedin-insights.md +58 -63
- package/docs/integrations/logrocket.md +55 -60
- package/docs/integrations/matomo-analytics.md +58 -60
- package/docs/integrations/meta-pixel.md +56 -60
- package/docs/integrations/microsoft-clarity.md +57 -60
- package/docs/integrations/microsoft-uet.md +58 -61
- package/docs/integrations/mixpanel-analytics.md +73 -75
- package/docs/integrations/one-dollar-stats.md +53 -59
- package/docs/integrations/openai-pixel.md +58 -60
- package/docs/integrations/overview.md +59 -42
- package/docs/integrations/pinterest-tag.md +56 -60
- package/docs/integrations/pirsch.md +54 -60
- package/docs/integrations/plausible-analytics.md +55 -60
- package/docs/integrations/posthog.md +56 -60
- package/docs/integrations/promptwatch.md +57 -63
- package/docs/integrations/reddit-pixel.md +57 -60
- package/docs/integrations/rudderstack.md +65 -67
- package/docs/integrations/rybbit-analytics.md +70 -75
- package/docs/integrations/segment.md +56 -60
- package/docs/integrations/sentry.md +65 -60
- package/docs/integrations/snapchat-pixel.md +54 -60
- package/docs/integrations/tiktok-pixel.md +59 -63
- package/docs/integrations/umami-analytics.md +54 -60
- package/docs/integrations/vercel-analytics.md +53 -59
- package/docs/integrations/vercel-speed-insights.md +317 -0
- package/docs/integrations/x-pixel.md +57 -63
- package/docs/integrations/youtube.md +25 -13
- package/package.json +18 -8
- package/docs/upgrade-v3.md +0 -429
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c15t/react",
|
|
3
|
-
"version": "3.0.0
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "React cookie banner, consent manager, preference center, and headless CMP components with IAB TCF and Consent Mode support.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ccpa",
|
|
@@ -67,6 +67,11 @@
|
|
|
67
67
|
"import": "./dist/index.js",
|
|
68
68
|
"default": "./dist/index.js"
|
|
69
69
|
},
|
|
70
|
+
"./modes": {
|
|
71
|
+
"types": "./dist-types/modes.d.ts",
|
|
72
|
+
"import": "./dist/modes.js",
|
|
73
|
+
"default": "./dist/modes.js"
|
|
74
|
+
},
|
|
70
75
|
"./provider": {
|
|
71
76
|
"types": "./dist-types/provider.d.ts",
|
|
72
77
|
"import": "./dist/provider.js",
|
|
@@ -82,6 +87,11 @@
|
|
|
82
87
|
"import": "./dist/draft.js",
|
|
83
88
|
"default": "./dist/draft.js"
|
|
84
89
|
},
|
|
90
|
+
"./theme": {
|
|
91
|
+
"types": "./dist-types/index-parts/theme.d.ts",
|
|
92
|
+
"import": "./dist/index-parts/theme.js",
|
|
93
|
+
"default": "./dist/index-parts/theme.js"
|
|
94
|
+
},
|
|
85
95
|
"./module-hooks": {
|
|
86
96
|
"types": "./dist-types/module-hooks.d.ts",
|
|
87
97
|
"import": "./dist/module-hooks.js",
|
|
@@ -254,16 +264,16 @@
|
|
|
254
264
|
"test:watch": "bun prebuild && vitest"
|
|
255
265
|
},
|
|
256
266
|
"dependencies": {
|
|
257
|
-
"@c15t/core": "3.0.0
|
|
258
|
-
"@c15t/dev-tools": "3.0.0
|
|
259
|
-
"@c15t/iab": "3.0.0
|
|
260
|
-
"@c15t/schema": "3.0.0
|
|
261
|
-
"@c15t/translations": "3.0.0
|
|
262
|
-
"@c15t/ui": "3.0.0
|
|
267
|
+
"@c15t/core": "3.0.0",
|
|
268
|
+
"@c15t/dev-tools": "3.0.0",
|
|
269
|
+
"@c15t/iab": "3.0.0",
|
|
270
|
+
"@c15t/schema": "3.0.0",
|
|
271
|
+
"@c15t/translations": "3.0.0",
|
|
272
|
+
"@c15t/ui": "3.0.0",
|
|
263
273
|
"@types/google.maps": "3.65.3"
|
|
264
274
|
},
|
|
265
275
|
"devDependencies": {
|
|
266
|
-
"@c15t/backend": "3.0.0
|
|
276
|
+
"@c15t/backend": "3.0.0",
|
|
267
277
|
"@c15t/conformance": "0.0.1",
|
|
268
278
|
"@c15t/typescript-config": "0.0.1",
|
|
269
279
|
"@c15t/vitest-config": "1.0.0",
|
package/docs/upgrade-v3.md
DELETED
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Migrate to v3
|
|
3
|
-
description: Upgrade from c15t v2 to v3. Pick the guide for the v2 package you
|
|
4
|
-
use (@c15t/nextjs, @c15t/react or the c15t store), rename @c15t/scripts, keep
|
|
5
|
-
visitors' choices, and upgrade a self-hosted backend and the Node.js SDK.
|
|
6
|
-
group: reference
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Hand the upgrade to a coding agent
|
|
10
|
-
|
|
11
|
-
**Upgrade this app to c15t v3**
|
|
12
|
-
|
|
13
|
-
Paste into Claude Code, Codex, Cursor or another coding agent at the root of your app.
|
|
14
|
-
|
|
15
|
-
```prompt
|
|
16
|
-
Upgrade this app from c15t v2 to c15t v3.
|
|
17
|
-
|
|
18
|
-
1. Check `package.json` for c15t packages. `@c15t/nextjs` means Next.js, `@c15t/react` without it means React, and `c15t` alone means the JavaScript store.
|
|
19
|
-
2. Read the matching guide before you change anything: <https://c15t.com/docs/frameworks/next/upgrade-v3.md>, <https://c15t.com/docs/frameworks/react/upgrade-v3.md> or <https://c15t.com/docs/frameworks/javascript/upgrade-v3.md>. Follow it in order and do not guess v3 APIs from memory.
|
|
20
|
-
3. If the app also runs its own c15t backend with `@c15t/backend`, read <https://c15t.com/docs/upgrade-v3.md> and upgrade the backend in the same change. Start with `npx @c15t/cli@alpha codemods backend-config-to-v3 node-sdk-to-v3 --dry-run --json`, then run it without `--dry-run`.
|
|
21
|
-
4. Keep the existing backend URL.
|
|
22
|
-
5. Run the typecheck and build when you finish.
|
|
23
|
-
|
|
24
|
-
List the files you changed, anything you could not migrate, and how you checked that vendor requests still wait for consent.
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## What changes in v3
|
|
28
|
-
|
|
29
|
-
* One package, `c15t`, replaces `@c15t/nextjs`, `@c15t/react` and the v2
|
|
30
|
-
`c15t` store. Import from its subpaths: `c15t/next`, `c15t/react`, and `c15t`
|
|
31
|
-
for the headless engine.
|
|
32
|
-
* The vendor helpers move from `@c15t/scripts` to `@c15t/integrations`, with
|
|
33
|
-
the same subpaths and helper names.
|
|
34
|
-
* `ConsentManagerProvider` becomes `ConsentProvider` in React. Next.js apps
|
|
35
|
-
that resolve consent on the server use `ConsentRoot`.
|
|
36
|
-
* `mode` and `backendURL` become one transport, `hosted({ url })` or
|
|
37
|
-
`offline()`.
|
|
38
|
-
* Policy packs become policy rules. You set them in your Inth project, in a
|
|
39
|
-
self-hosted backend's `manifest.policyRules`, or in `offline({ policyRules })`.
|
|
40
|
-
* `useConsentManager()` is gone. Each field has its own hook, and a codemod
|
|
41
|
-
rewrites most calls.
|
|
42
|
-
* Callbacks have new names, and each reports either a recorded choice or a
|
|
43
|
-
permission change.
|
|
44
|
-
* `theme` tokens no longer generate CSS on their own. Render `ConsentTheme` or
|
|
45
|
-
add `generateThemeCSS()` output to your stylesheet.
|
|
46
|
-
* IAB moves from the `iab` provider option to an `IABProvider` component in
|
|
47
|
-
React and Next.js.
|
|
48
|
-
* Every package ships ESM only. `require()` of a c15t package no longer
|
|
49
|
-
resolves.
|
|
50
|
-
* Visitors' existing choices keep working. v3 reads the v2 cookie.
|
|
51
|
-
* A self-hosted backend takes `database` instead of `adapter`, and needs a
|
|
52
|
-
schema migration.
|
|
53
|
-
* `@c15t/node-sdk` has a new client, `createC15tClient()`. Its methods return
|
|
54
|
-
results instead of throwing, and it reads no environment variables.
|
|
55
|
-
|
|
56
|
-
## Pick your guide
|
|
57
|
-
|
|
58
|
-
Each guide covers one v2 package from start to finish.
|
|
59
|
-
|
|
60
|
-
| You use in v2 | Follow |
|
|
61
|
-
| ----------------------------------------------------- | -------------------------------------------------------------------- |
|
|
62
|
-
| `@c15t/nextjs` | [Next.js](https://c15t.com/docs/frameworks/next/upgrade-v3) |
|
|
63
|
-
| `@c15t/react` | [React](./frameworks/react/upgrade-v3.md) |
|
|
64
|
-
| `c15t`, with `getOrCreateConsentRuntime` or the store | [JavaScript](https://c15t.com/docs/frameworks/javascript/upgrade-v3) |
|
|
65
|
-
|
|
66
|
-
v3 also adds TanStack Start, Nuxt, Vue, Astro, Svelte, SvelteKit and a script
|
|
67
|
-
tag. If you want to move to one of them, start with its quickstart from
|
|
68
|
-
[Choose your setup](./concepts/choose-your-setup.md).
|
|
69
|
-
|
|
70
|
-
If you run your own c15t backend, upgrade it in the same release as the
|
|
71
|
-
clients, following [Upgrade a self-hosted backend](#upgrade-a-self-hosted-backend).
|
|
72
|
-
Server code that calls the API with `@c15t/node-sdk` follows
|
|
73
|
-
[Update the Node.js SDK](#update-the-nodejs-sdk).
|
|
74
|
-
|
|
75
|
-
The sections below apply to every app.
|
|
76
|
-
|
|
77
|
-
## Rename the integrations dependency
|
|
78
|
-
|
|
79
|
-
v3 renames `@c15t/scripts` to `@c15t/integrations`. Remove `@c15t/scripts`
|
|
80
|
-
from your dependencies and install `@c15t/integrations` from the `alpha`
|
|
81
|
-
dist-tag:
|
|
82
|
-
|
|
83
|
-
| Package manager | Command |
|
|
84
|
-
| :-------------- | :------------------------------------- |
|
|
85
|
-
| npm | `npm install @c15t/integrations@alpha` |
|
|
86
|
-
| pnpm | `pnpm add @c15t/integrations@alpha` |
|
|
87
|
-
| yarn | `yarn add @c15t/integrations@alpha` |
|
|
88
|
-
| bun | `bun add @c15t/integrations@alpha` |
|
|
89
|
-
|
|
90
|
-
Replace the package name in each import. Vendor subpaths and helper names stay
|
|
91
|
-
the same.
|
|
92
|
-
|
|
93
|
-
Before, in v2:
|
|
94
|
-
|
|
95
|
-
```ts
|
|
96
|
-
import { googleTagManager } from '@c15t/scripts/google-tag-manager';
|
|
97
|
-
import { posthog } from '@c15t/scripts/posthog';
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
After:
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
import { googleTagManager } from '@c15t/integrations/google-tag-manager';
|
|
104
|
-
import { posthog } from '@c15t/integrations/posthog';
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
The `scripts` configuration option and the `Script` type keep their names.
|
|
108
|
-
|
|
109
|
-
Two helper behaviors change. A helper that needs an ID, such as `metaPixel`,
|
|
110
|
-
`googleTagManager` or `posthog`, now throws when the ID is empty or only
|
|
111
|
-
whitespace, where v2 loaded a broken script. And if your code reads
|
|
112
|
-
`@c15t/integrations/registry`, an entry's `consentCategory` can now be a
|
|
113
|
-
compound condition such as `{ and: ['marketing', 'measurement'] }`, not only a
|
|
114
|
-
category name.
|
|
115
|
-
|
|
116
|
-
`@c15t/scripts` stays available as a deprecated compatibility package for all
|
|
117
|
-
of v3. It re-exports the implementation and types of `@c15t/integrations`, so
|
|
118
|
-
you can migrate imports separately from the rest of the upgrade. Compatibility
|
|
119
|
-
ends in v4; versions already published stay on npm.
|
|
120
|
-
|
|
121
|
-
To preview the import changes in JavaScript and TypeScript files:
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
npx @c15t/cli@alpha codemods scripts-to-integrations --dry-run --json
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Review the output, then run it again without `--dry-run`. The codemod runs
|
|
128
|
-
only when you name it. It does not change `package.json`, lockfiles, or
|
|
129
|
-
imports inside `.vue`, `.svelte` or `.astro` files; update those by hand, then
|
|
130
|
-
reinstall dependencies and build the app.
|
|
131
|
-
|
|
132
|
-
## Replace `useConsentManager()`
|
|
133
|
-
|
|
134
|
-
`useConsentManager()` returned the whole consent state, so every component
|
|
135
|
-
that called it re-rendered on every change. v3 has one hook per field. Run the
|
|
136
|
-
codemod first:
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
npx @c15t/cli@alpha codemods use-consent-manager-to-hooks --dry-run --json
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Review the proposed files, then run it again without `--dry-run`. For this v2
|
|
143
|
-
component:
|
|
144
|
-
|
|
145
|
-
```tsx title="Before (v2): components/accept-button.tsx"
|
|
146
|
-
import { useConsentManager } from '@c15t/react';
|
|
147
|
-
|
|
148
|
-
export function AcceptButton() {
|
|
149
|
-
const { activeUI, has, saveConsents } = useConsentManager();
|
|
150
|
-
if (activeUI !== 'banner' || has('marketing')) return null;
|
|
151
|
-
return (
|
|
152
|
-
<button type="button" onClick={() => void saveConsents('all')}>
|
|
153
|
-
Accept
|
|
154
|
-
</button>
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
the codemod writes:
|
|
160
|
-
|
|
161
|
-
```tsx title="After (v3): components/accept-button.tsx"
|
|
162
|
-
import { useActiveUI, useConsent } from '@c15t/react';
|
|
163
|
-
import { useHeadlessConsentUI } from '@c15t/react/headless';
|
|
164
|
-
|
|
165
|
-
export function AcceptButton() {
|
|
166
|
-
const activeUI = useActiveUI() ?? 'none';
|
|
167
|
-
const hasMarketing = useConsent('marketing');
|
|
168
|
-
const { saveCustomPreferences: saveConsents } = useHeadlessConsentUI();
|
|
169
|
-
if (activeUI !== 'banner' || hasMarketing) return null;
|
|
170
|
-
return (
|
|
171
|
-
<button type="button" onClick={() => void saveConsents('all')}>
|
|
172
|
-
Accept
|
|
173
|
-
</button>
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
The codemod keeps the entry you imported from. Change `@c15t/react` to
|
|
179
|
-
`c15t/react` afterwards if you moved to the umbrella package. Fields it cannot
|
|
180
|
-
rewrite stay on a `useConsentManager()` call under a `TODO(c15t v3)` comment,
|
|
181
|
-
which fails the build until you replace them. The table lists the v2 fields
|
|
182
|
-
components read. The other fields held provider configuration, such as
|
|
183
|
-
`legalLinks`, `scripts` and `storageConfig`, or store internals; set
|
|
184
|
-
configuration through `ConsentProvider` props.
|
|
185
|
-
Import hooks from `c15t/react`, `c15t/next` or `c15t/tanstack-start`, and
|
|
186
|
-
`useHeadlessConsentUI` from the matching `/headless` entry.
|
|
187
|
-
|
|
188
|
-
| v2 field | v3 replacement |
|
|
189
|
-
| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
190
|
-
| `activeUI` | `useActiveUI()`. It returns `null` until c15t picks a surface, where v2 returned `'none'`. |
|
|
191
|
-
| `setActiveUI(ui)` | `useSetActiveUI()` |
|
|
192
|
-
| `has(category)` | `useConsent(category)`, one call per category at the top of the component |
|
|
193
|
-
| `consents` | `useConsents()` |
|
|
194
|
-
| `saveConsents('all')` | `useHeadlessConsentUI().saveCustomPreferences('all')` |
|
|
195
|
-
| `saveConsents('necessary')` | `useHeadlessConsentUI().saveCustomPreferences('none')` |
|
|
196
|
-
| `saveConsents('custom')` | `useConsentDraft().save()`, or `useHeadlessConsentUI().saveCustomPreferences()` inside a `ConsentDraftProvider` |
|
|
197
|
-
| `selectedConsents` | `useConsentDraft().values` |
|
|
198
|
-
| `setSelectedConsent(name, value)` | `useConsentDraft().set(name, value)` |
|
|
199
|
-
| `setConsent(name, value)` | `useSaveConsents()`, called with `{ [name]: value }` |
|
|
200
|
-
| `consentInfo` | `useExplicitChoice()` |
|
|
201
|
-
| `hasConsented()` | `useExplicitChoice() !== null` |
|
|
202
|
-
| `consentCategories`, `consentTypes`, `getDisplayedConsents()` | `useConsentDraft().displayedCategories`, with labels from `useTranslations().consentTypes` |
|
|
203
|
-
| `policyCategories` | `usePolicyCategories()`. The v2 list started with `'necessary'`; this one does not. |
|
|
204
|
-
| `policyScopeMode` | `usePolicyScopeMode()` |
|
|
205
|
-
| `policyBanner` | `usePromptPresentation()` |
|
|
206
|
-
| `policyDialog` | `usePreferencesPresentation()` |
|
|
207
|
-
| `model` | `useModel()`. It returns `null` while no policy matches, where v2 returned `'opt-in'`. |
|
|
208
|
-
| `branding` | `useBranding()`. It returns `null` when unset, where v2 returned `'c15t'`. |
|
|
209
|
-
| `iab` | `useIABSnapshot()` |
|
|
210
|
-
| `locationInfo` | `useLocation()` |
|
|
211
|
-
| `overrides`, `setOverrides()` | `useOverrides()`, `useSetOverrides()` |
|
|
212
|
-
| `setLanguage()` | `useSetLanguage()` |
|
|
213
|
-
| `user`, `identifyUser()` | `useUser()`, `useIdentify()` |
|
|
214
|
-
| `translationConfig` | `useTranslations()` for the active strings |
|
|
215
|
-
| `subscribeToConsentChanges(listener)` | `useSubscribeToConsentChanges()`, or the `onPermissionsChanged` callback |
|
|
216
|
-
| `updateConsentCategories(categories)` | `useRegisterConsentCategories()` |
|
|
217
|
-
| `manager` | Nothing. Use the hooks above. |
|
|
218
|
-
|
|
219
|
-
`saveCustomPreferences()` saves the way the stock buttons do. It closes the
|
|
220
|
-
banner or dialog after a successful save. `useSaveConsents()` calls the engine
|
|
221
|
-
directly and does not close anything.
|
|
222
|
-
|
|
223
|
-
In v2, `useConsentManager()` kept one draft per component. In v3,
|
|
224
|
-
`useConsentDraft()` and `useHeadlessConsentUI()` share a draft only inside a
|
|
225
|
-
`ConsentDraftProvider`. Without one, `saveCustomPreferences()` saves a fresh
|
|
226
|
-
draft and ignores what `useConsentDraft().set()` staged, even in the same
|
|
227
|
-
component. Save with `useConsentDraft().save()`, or render the code that stages
|
|
228
|
-
and the code that saves inside one `ConsentDraftProvider`. `ConsentWidget`
|
|
229
|
-
already includes one. The codemod
|
|
230
|
-
adds a `TODO(c15t v3)` comment where this applies.
|
|
231
|
-
|
|
232
|
-
## Keep visitors' existing choices
|
|
233
|
-
|
|
234
|
-
v3 uses the same `c15t` cookie and storage key as v2 and reads v2 records. It
|
|
235
|
-
does not rewrite them on page load; the next accept, reject or save writes a
|
|
236
|
-
v3 record.
|
|
237
|
-
|
|
238
|
-
A v2 denial keeps restricting its category. A v2 grant keeps applying until
|
|
239
|
-
the policy's validity period runs out, and then c15t asks again. If the rule
|
|
240
|
-
comes from a preset and the v2 record noted the policy it was made under, c15t
|
|
241
|
-
also asks again when that policy has changed. Under custom rules, a v2 grant
|
|
242
|
-
applies until it expires. Do not copy permissions into new
|
|
243
|
-
records yourself; c15t decides which v2 choices still count.
|
|
244
|
-
|
|
245
|
-
## Choose the HTML bundle
|
|
246
|
-
|
|
247
|
-
For HTML script tags, `c15t.js` is now the hosted bundle. Keep that filename
|
|
248
|
-
for Inth or a self-hosted backend and supply `data-backend-url`, a queued
|
|
249
|
-
`backendURL`, or a hosted factory. Loading it without a backend no longer
|
|
250
|
-
starts offline mode.
|
|
251
|
-
|
|
252
|
-
If an earlier v3 script tag used local policy rules, switch its URL to
|
|
253
|
-
`c15t.offline.js`. For manifest mode, custom transports or a page that selects
|
|
254
|
-
its mode at runtime, use the root ES module `@c15t/browser`, which still
|
|
255
|
-
accepts every mode. The headless script supports those modes with your own
|
|
256
|
-
UI, and the IAB script supports them for IAB policies. The self-hosted
|
|
257
|
-
backend's `/c15t.js` route now resolves policies through `/init`; its headless
|
|
258
|
-
and IAB routes still preload the manifest. See the
|
|
259
|
-
[script file reference](https://c15t.com/docs/frameworks/html/attributes-and-api#script-files).
|
|
260
|
-
|
|
261
|
-
## Upgrade a self-hosted backend
|
|
262
|
-
|
|
263
|
-
Deploy the v3 backend and the v3 clients in the same release. A v3 client
|
|
264
|
-
cannot read a v2 backend's `/init` response. Policy resolution fails, optional
|
|
265
|
-
categories stay denied and no banner appears.
|
|
266
|
-
|
|
267
|
-
1. Install `@c15t/backend@alpha` and the SQL driver for your database.
|
|
268
|
-
2. Replace `adapter` with `database` in your config. The Drizzle, Prisma,
|
|
269
|
-
TypeORM and Kysely adapters are gone; point `database` at the same SQL
|
|
270
|
-
database instead. MongoDB has no migration path.
|
|
271
|
-
3. Move `policyPacks`, `branding`, `customTranslations`, `i18n` and `appName`
|
|
272
|
-
under `manifest`, and rename `policyPacks` to `policyRules`. Split `iab`
|
|
273
|
-
between `manifest.iab` and `gvl`, as the table below shows.
|
|
274
|
-
4. Back up the database, then plan and apply the schema migration:
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
npx @c15t/cli@alpha self-host migrate --config ./c15t-backend.config.ts --plan
|
|
278
|
-
npx @c15t/cli@alpha self-host migrate --config ./c15t-backend.config.ts --apply
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
The migrator recognizes the v2 schema, adopts it, and adds the v3 tables and
|
|
282
|
-
columns. Apply it before the v3 backend serves traffic: v3 records policy
|
|
283
|
-
decisions without the v2 `jurisdiction` label, which the migration makes
|
|
284
|
-
nullable. [Database setup](https://c15t.com/docs/self-host/guides/database-setup#upgrade-a-v2-backend)
|
|
285
|
-
covers the details, and the [backend quickstart](https://c15t.com/docs/self-host/quickstart)
|
|
286
|
-
shows a complete v3 config and route.
|
|
287
|
-
|
|
288
|
-
The `backend-config-to-v3` codemod does step 3 for the keys that move as they
|
|
289
|
-
are, and leaves a `TODO(c15t v3)` comment on `adapter`, `iab`,
|
|
290
|
-
`disableGeoLocation` and the other options in the table below:
|
|
291
|
-
|
|
292
|
-
```bash
|
|
293
|
-
npx @c15t/cli@alpha codemods backend-config-to-v3 policy-packs-to-policy-rules --dry-run --json
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
Preset calls such as `policyRulePresets.europeOptIn()` need no other change.
|
|
297
|
-
A hand-written v2 pack uses `consent` and `ui` keys, which v3 rules replace
|
|
298
|
-
with flat keys such as `model` and `prompt`. See
|
|
299
|
-
[policy configuration](https://c15t.com/docs/self-host/guides/policy-packs).
|
|
300
|
-
|
|
301
|
-
The v3 backend stores timestamps in UTC. Convert rows that a v2 backend wrote
|
|
302
|
-
in another time zone before you deploy. Database setup lists the checks.
|
|
303
|
-
|
|
304
|
-
Other backend options and entries change too:
|
|
305
|
-
|
|
306
|
-
| v2 | v3 |
|
|
307
|
-
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
308
|
-
| `tablePrefix` | Removed. The migrator refuses a database with prefixed c15t tables, so rename them first. On PostgreSQL, `database.schema` keeps c15t's tables in their own schema. |
|
|
309
|
-
| `iab.vendorIds`, `iab.endpoint`, `cache.adapter` | `gvl: { vendorIds, endpoint, cache }` |
|
|
310
|
-
| `iab.enabled`, `iab.cmpId`, `iab.customVendors` | `manifest.iab` |
|
|
311
|
-
| `logger`, `telemetry` | `observability`, passed to `c15tInstance()` |
|
|
312
|
-
| `background`, `iab.bundled` | Removed |
|
|
313
|
-
| `openapi.docsPath`, `openapi.options`, `openapi.customUiTemplate` and the `/docs` page | Removed. The spec is still at `/spec.json`. |
|
|
314
|
-
| `policySnapshot.onValidationFailure` | Removed |
|
|
315
|
-
| `GET /` as an alias of `/status` | Removed. Call `/status`. |
|
|
316
|
-
| `@c15t/backend/define-config`, `/router`, `/types`, `/db/schema`, `/db/adapters/*`, `/db/migrator`, `/edge` | Removed. Import `defineConfig`, `createMigrator` and `policyRulePresets` from `@c15t/backend`. |
|
|
317
|
-
|
|
318
|
-
### Remove `disableGeoLocation`
|
|
319
|
-
|
|
320
|
-
v3 removes the top-level `disableGeoLocation` option. Policy rules decide by
|
|
321
|
-
country and region. To show every visitor the same banner, configure one rule
|
|
322
|
-
with `match: { isDefault: true }`. It applies wherever the visitor is, so the
|
|
323
|
-
browser can resolve it without asking the backend for a location.
|
|
324
|
-
|
|
325
|
-
To test one region's rule from anywhere, set the country in the client's
|
|
326
|
-
`overrides`, for example `overrides: { country: 'US' }`. See
|
|
327
|
-
[runtime options](https://c15t.com/docs/frameworks/javascript/api/runtime).
|
|
328
|
-
|
|
329
|
-
### Stop reading `jurisdiction`
|
|
330
|
-
|
|
331
|
-
`/init` responses, session reports and `sessions.onReport` no longer carry a
|
|
332
|
-
`jurisdiction` label such as `GDPR`. Read the matched policy from
|
|
333
|
-
`policyResolution` instead, or the report's `policy`, `country` and `region`.
|
|
334
|
-
The backend still accepts `jurisdiction` in a v2 client's save request and
|
|
335
|
-
ignores it.
|
|
336
|
-
|
|
337
|
-
## Update the Node.js SDK
|
|
338
|
-
|
|
339
|
-
Install `@c15t/node-sdk@alpha`. The v2 client is gone: create one with
|
|
340
|
-
`createC15tClient()` and pass the backend URL and API key yourself.
|
|
341
|
-
|
|
342
|
-
| Package manager | Command |
|
|
343
|
-
| :-------------- | :--------------------------------- |
|
|
344
|
-
| npm | `npm install @c15t/node-sdk@alpha` |
|
|
345
|
-
| pnpm | `pnpm add @c15t/node-sdk@alpha` |
|
|
346
|
-
| yarn | `yarn add @c15t/node-sdk@alpha` |
|
|
347
|
-
| bun | `bun add @c15t/node-sdk@alpha` |
|
|
348
|
-
|
|
349
|
-
```ts
|
|
350
|
-
import { createC15tClient } from '@c15t/node-sdk';
|
|
351
|
-
|
|
352
|
-
const apiKey = process.env.C15T_API_KEY;
|
|
353
|
-
if (!apiKey) throw new Error('Set C15T_API_KEY');
|
|
354
|
-
|
|
355
|
-
const c15t = createC15tClient({
|
|
356
|
-
baseUrl: 'https://app.example.com/api/c15t',
|
|
357
|
-
apiKey,
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
const result = await c15t.consents.check({
|
|
361
|
-
externalId: 'user_123',
|
|
362
|
-
types: ['privacy_policy', 'marketing_communications'],
|
|
363
|
-
});
|
|
364
|
-
if (result.ok) {
|
|
365
|
-
console.log(result.data.results.privacy_policy.hasConsent);
|
|
366
|
-
}
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
| v2 | v3 |
|
|
370
|
-
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
371
|
-
| `c15tClient(options)`, `new C15TClient(options)` | `createC15tClient(options)` |
|
|
372
|
-
| `C15T_API_URL`, `C15T_API_TOKEN` read from the environment | Not read. Pass `baseUrl` and `apiKey`. |
|
|
373
|
-
| `token` | `apiKey` |
|
|
374
|
-
| `prefix` | Part of `baseUrl`. v2 replaced the base URL's path with `prefix`, so use the origin plus the prefix, such as `https://app.example.com/api/c15t`. |
|
|
375
|
-
| `timeout` | `timeoutMs`, per attempt. The default drops from 30 to 10 seconds. |
|
|
376
|
-
| `retryConfig` | `retry: { maxRetries, initialDelayMs, maxDelayMs }`, or `false`. `backoffFactor`, `retryableStatusCodes`, `nonRetryableStatusCodes` and `retryOnNetworkError` are gone. |
|
|
377
|
-
| `debug`, `C15T_DEBUG` | `onEvent` |
|
|
378
|
-
| `client.meta.status()`, `client.status()` | `c15t.status()` |
|
|
379
|
-
| `client.meta.init(options)`, `client.init(options)` | `c15t.init({ language, country, region, gpc }, options)`. Per-call options move to the second argument. |
|
|
380
|
-
| `getSubject(id, { type: 'a,b' })`, `subjects.get(id, { type: 'a,b' })` | `subjects.get(id, { types: ['a', 'b'] })` |
|
|
381
|
-
| `createSubject(input)` | `subjects.create(input)`. `givenAt` also takes a `Date`. |
|
|
382
|
-
| `patchSubject(id, input)`, `subjects.patch(id, input)` | `subjects.identify(id, { externalId, identityProvider })` |
|
|
383
|
-
| `listSubjects({ externalId })`, `subjects.list({ externalId })` | `subjects.list({ externalId })`, on a client with `apiKey` |
|
|
384
|
-
| `checkConsent(query)`, `consent.check({ externalId, type: 'a,b' })` | `consents.check({ externalId, types: ['a', 'b'] })`, on a client with `apiKey` |
|
|
385
|
-
| `ResponseContext` with `data: T \|null` | `{ ok: true, data } \|{ ok: false, error }`. Check `ok` first. |
|
|
386
|
-
| `unwrap()`, `expect()` on the response | `unwrap(result)`, imported from `@c15t/node-sdk` |
|
|
387
|
-
| `unwrapOr()`, `map()` on the response | Check `result.ok` |
|
|
388
|
-
| `throw: true` | `unwrap(result)` |
|
|
389
|
-
| `onSuccess`, `onError` | Check `result.ok` after the call |
|
|
390
|
-
| `C15TError`, `isC15TError()` | `C15tError`, `isC15tError(error, ...codes)` |
|
|
391
|
-
| `C15TClient`, `C15TClientOptions`, `RetryConfig`, `FetchOptions`, `ResponseContext` types | `C15tClient`, `C15tClientOptions`, `C15tRetryOptions`, `C15tCallOptions`, `C15tResult` |
|
|
392
|
-
| Per-call `timeout`, `retryConfig` | `timeoutMs`, `retry` |
|
|
393
|
-
| Per-call `body`, `query`, `method` | Removed. Pass the body and query as the method's arguments. |
|
|
394
|
-
| `$fetch`, `fetcher`, `resolveUrl`, `createResponseContext` | Removed. Pass a custom `fetch` to `createC15tClient` if you need one. |
|
|
395
|
-
| `createMockClient`, `createMockResponse`, `createMockErrorResponse` | `createMockC15tClient`, `ok`, `err` from `@c15t/node-sdk/testing` |
|
|
396
|
-
|
|
397
|
-
`patchSubject` returned `{ success, subject }`. `subjects.identify` returns
|
|
398
|
-
`{ subject }`, and `subject.identityProvider` is always set. Dates in
|
|
399
|
-
responses, such as `givenAt` and `createdAt`, are now `Date` objects rather
|
|
400
|
-
than strings.
|
|
401
|
-
|
|
402
|
-
`consents.check` and `subjects.list` count only verified links. Links made by
|
|
403
|
-
v2 don't count until you relink them with `subjects.identify` on a keyed
|
|
404
|
-
client, or [with an identity token](https://c15t.com/docs/self-host/api/node-sdk#verify-a-link-made-in-the-browser) on the user's next sign-in.
|
|
405
|
-
|
|
406
|
-
The `node-sdk-to-v3` codemod renames the factory, client options, methods,
|
|
407
|
-
types and errors in files that create a client. It turns `type` strings into
|
|
408
|
-
`types` arrays, and leaves a `TODO(c15t v3)` comment at each call, because
|
|
409
|
-
results are now `{ ok, data }` or `{ ok, error }`. It renames per-call
|
|
410
|
-
`timeout` and `retryConfig` too. It also marks `prefix`, `debug`, per-call
|
|
411
|
-
`throw`, `onSuccess`, `onError`, `body`, `query` and `method`, and a client
|
|
412
|
-
built from environment variables:
|
|
413
|
-
|
|
414
|
-
```bash
|
|
415
|
-
npx @c15t/cli@alpha codemods node-sdk-to-v3 --dry-run --json
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
The new client also adds `manifest()`, `legalDocuments.publish()` and
|
|
419
|
-
`experiments.summary()`. The last two need a client with `apiKey`. See the
|
|
420
|
-
[Node.js SDK reference](https://c15t.com/docs/self-host/api/node-sdk).
|
|
421
|
-
|
|
422
|
-
## Update the CLI
|
|
423
|
-
|
|
424
|
-
* Run `c15t login` again. The CLI signs in through Inth now and no longer
|
|
425
|
-
reads sessions saved by v2.
|
|
426
|
-
* `c15t setup` no longer writes `.env.local` or `.env.example` and no longer
|
|
427
|
-
accepts `--env`. It writes the backend URL into the files it generates.
|
|
428
|
-
* `c15t setup` no longer detects Remix or Gatsby. Pick a guide from
|
|
429
|
-
[Choose your setup](./concepts/choose-your-setup.md) for those apps.
|