@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/docs/README.md
CHANGED
|
@@ -6,7 +6,7 @@ These docs ship inside the package so coding agents can read them offline. Open
|
|
|
6
6
|
|
|
7
7
|
## Using these docs
|
|
8
8
|
|
|
9
|
-
These docs describe c15t v3. Find your app's row in Choose your setup, then follow that framework guide from start to finish; it names the files to create and the backend URL to use.
|
|
9
|
+
These docs describe c15t v3. Find your app's row in Choose your setup, then follow that framework guide from start to finish; it names the files to create and the backend URL to use. A visible banner does not prove anything: check that vendor requests wait for consent, that rejection survives a reload, and that preferences can be reopened.
|
|
10
10
|
|
|
11
11
|
## Start here
|
|
12
12
|
|
|
@@ -15,7 +15,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
15
15
|
- [How consent works](./concepts/how-consent-works.md): What c15t decides on each page load, the difference between a permission and a recorded choice, and what happens when a visitor saves.
|
|
16
16
|
- [Customize the interface](./customization/overview.md): Change c15t's consent banner and dialog one step at a time, from a prop to your own markup, and find where each step lives in your framework.
|
|
17
17
|
- [Verify consent](./guides/verify-consent.md): Check in a production build that vendor requests wait for consent, rejection survives a reload, preferences reopen and privacy signals apply.
|
|
18
|
-
- [
|
|
18
|
+
- [Upgrade a React app from v2](./frameworks/react/upgrade-v3.md): Upgrade a React app from c15t v2 (@c15t/react) to v3. Covers packages, ConsentProvider and transports, the useConsentManager codemod, callbacks, policies, styles, IAB and stored consent.
|
|
19
19
|
|
|
20
20
|
## More documentation
|
|
21
21
|
|
|
@@ -36,7 +36,7 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
36
36
|
- [DevTools](./frameworks/react/components/dev-tools.md): Inspect consent state, location, loaded scripts and consent events in a React app during development with the c15t DevTools panel.
|
|
37
37
|
- [Compose your own banner](./frameworks/react/compose.md): Build a React consent banner from the ConsentBanner parts in c15t/react, with your own markup and buttons, while the policy still decides which actions appear.
|
|
38
38
|
- [Content Security Policy](./frameworks/react/content-security-policy.md): Run c15t in a React app under a Content Security Policy, allow the consent backend and vendor hosts, and pass a nonce to ConsentProvider and ConsentTheme.
|
|
39
|
-
- [Customize](./frameworks/react/customize.md): Change the colors, fonts, layout, button styles and copy of the c15t banner and dialog in a React app with
|
|
39
|
+
- [Customize](./frameworks/react/customize.md): Change the colors, fonts, layout, button styles and copy of the c15t banner and dialog in a React app with theme tokens, provider options and slots, and load the stylesheet yourself when you need to.
|
|
40
40
|
- [Embeds](./frameworks/react/embeds.md): Keep YouTube videos, maps and other iframes out of a React page until their consent category is allowed, with ConsentGate or the iframe blocker in ConsentProvider.
|
|
41
41
|
- [IAB GPP](./frameworks/react/gpp.md): Add the IAB Global Privacy Platform API (__gpp) to a React app with ConsentGPP from @c15t/react/gpp, so ad tech can read US state opt-outs and the TCF EU consent string.
|
|
42
42
|
- [Headless](./frameworks/react/headless.md): Build a custom consent banner in React with the c15t/react/headless hooks inside your ConsentProvider.
|
|
@@ -58,12 +58,13 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
58
58
|
- [Consent state reference](./concepts/consent-state.md): How c15t saves choices, gates IAB vendors, hydrates server records and keeps browser tabs and storage in step.
|
|
59
59
|
- [Data fetching](./concepts/data-fetching.md): Choose the recommended build-time policy snapshot or runtime manifest fetching, backend /init, browser resolution or offline rules, and understand where consent choices are saved.
|
|
60
60
|
- [How consent works](./concepts/how-consent-works.md): What c15t decides on each page load, the difference between a permission and a recorded choice, and what happens when a visitor saves.
|
|
61
|
+
- [Consent modes](./concepts/modes.md): Reference for manifest(), hosted() and offline() in every c15t framework package, where each one resolves the visitor's policy, what it adds to first-load JavaScript, the build-time manifest fetch and its failure policy, and the backend URL variable each framework reads.
|
|
61
62
|
- [Policies](./concepts/policies.md): How policy models, prompts and scope decide what c15t asks visitors, where to change the rules, and why a banner may not appear.
|
|
62
63
|
|
|
63
64
|
## Guides
|
|
64
65
|
|
|
65
66
|
- [Banner experiments](./guides/banner-experiments.md): Run A/B tests on consent banner presentation with any feature-flag provider or built-in weighted assignment, and attribute every impression and choice to its arm.
|
|
66
|
-
- [Troubleshooting](./guides/troubleshooting.md): Fix a missing banner, analytics that load before consent, choices lost on reload, CORS errors, hydration differences and failed static builds in c15t v3.
|
|
67
|
+
- [Troubleshooting](./guides/troubleshooting.md): Fix a missing banner, analytics that load before consent, choices lost on reload, CORS errors, hydration differences, failed manifest downloads, mode errors and failed static builds in c15t v3.
|
|
67
68
|
- [Verify consent](./guides/verify-consent.md): Check in a production build that vendor requests wait for consent, rejection survives a reload, preferences reopen and privacy signals apply.
|
|
68
69
|
|
|
69
70
|
## Customization
|
|
@@ -74,8 +75,8 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
74
75
|
- [Customize the interface](./customization/overview.md): Change c15t's consent banner and dialog one step at a time, from a prop to your own markup, and find where each step lives in your framework.
|
|
75
76
|
- [Banner designs](./customization/recipes.md): Five consent banner designs built with c15t, from one prop to your own markup, with tested code for React, Vue, Svelte, Astro and plain HTML.
|
|
76
77
|
- [Component parts](./customization/slots.md): Find every part of c15t's banner, dialog, widget, trigger and ConsentGate placeholder, its key in your framework's part API, and the data attributes to select on.
|
|
77
|
-
- [Stylesheets and CSS layers](./customization/stylesheets.md):
|
|
78
|
-
- [Tailwind CSS](./customization/tailwind.md):
|
|
78
|
+
- [Stylesheets and CSS layers](./customization/stylesheets.md): See how c15t delivers its styles in each framework without a render-blocking stylesheet, when to import styles.css yourself with styles false, which file holds the dialog's rules, and how c15t's cascade layer meets your own.
|
|
79
|
+
- [Tailwind CSS](./customization/tailwind.md): Use c15t's styles with Tailwind CSS 4 or 3 in every framework, put utilities on c15t component parts, and use Tailwind's dark variant with c15t.
|
|
79
80
|
- [Theme tokens](./customization/tokens.md): Change c15t's colors, type, radius, spacing, shadows and motion with theme tokens, and see every --c15t-* variable with its default.
|
|
80
81
|
- [Copy and translations](./customization/translations.md): Change consent wording through i18n and test the complete prompt and preferences flow.
|
|
81
82
|
|
|
@@ -93,8 +94,8 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
93
94
|
- [Fathom Analytics](./integrations/fathom-analytics.md): Load Fathom Analytics only after measurement consent with the c15t fathomAnalytics helper, set its SPA mode, and check it in DevTools.
|
|
94
95
|
- [Front Chat](./integrations/front-chat.md): Load the Front Chat widget only after functionality consent with the c15t frontChat helper, forward CSP nonces, clear the session on revocation and check it in DevTools.
|
|
95
96
|
- [Google Maps](./integrations/google-maps.md): Gate a Google Maps iframe embed with c15t v3 so the map loads only after the visitor allows its consent category, in Next.js, TanStack Start, React, Nuxt, Vue, Astro, Svelte, SvelteKit, HTML or JavaScript.
|
|
96
|
-
- [Google Tag](./integrations/google-tag.md): Load gtag.js for Google Analytics or Google Ads with c15t Consent Mode v2 signals, and verify the consent commands in DevTools.
|
|
97
|
-
- [Google Tag Manager](./integrations/google-tag-manager.md): Load a Google Tag Manager container with c15t Consent Mode v2 signals, configure consent checks inside the container, and verify both in DevTools.
|
|
97
|
+
- [Google Tag](./integrations/google-tag.md): Load gtag.js for Google Analytics or Google Ads before or after consent with c15t Consent Mode v2 signals, and verify the consent commands in DevTools.
|
|
98
|
+
- [Google Tag Manager](./integrations/google-tag-manager.md): Load a Google Tag Manager container before or after consent with c15t Consent Mode v2 signals, configure consent checks inside the container, and verify both in DevTools.
|
|
98
99
|
- [Heap](./integrations/heap.md): Load the Heap config script and heap.js only after measurement consent with the c15t heap helper, and check it in DevTools.
|
|
99
100
|
- [Hightouch](./integrations/hightouch.md): Load the Hightouch Events browser SDK only after measurement consent with the c15t hightouch helper, and check page events in DevTools.
|
|
100
101
|
- [Hotjar](./integrations/hotjar.md): Load Hotjar only after measurement consent with the c15t hotjar helper, and check its loader and recordings in DevTools.
|
|
@@ -124,9 +125,6 @@ These docs describe c15t v3. Find your app's row in Choose your setup, then foll
|
|
|
124
125
|
- [TikTok Pixel](./integrations/tiktok-pixel.md): Load the TikTok Pixel only after marketing consent with the c15t tiktokPixel helper, guard ttq event calls, and check it in DevTools.
|
|
125
126
|
- [Umami Analytics](./integrations/umami-analytics.md): Load the Umami Analytics tracker only after measurement consent with the c15t umamiAnalytics helper, point it at a self-hosted instance, and check it in DevTools.
|
|
126
127
|
- [Vercel Analytics](./integrations/vercel-analytics.md): Load the Vercel Web Analytics script only after measurement consent with the c15t vercelAnalytics helper, choose the debug script, and check it in DevTools.
|
|
128
|
+
- [Vercel Speed Insights](./integrations/vercel-speed-insights.md): Load the Vercel Speed Insights collector only after measurement consent with the c15t vercelSpeedInsights helper, drop Web Vitals reports on revocation, and check it in DevTools.
|
|
127
129
|
- [X Pixel](./integrations/x-pixel.md): Load the X Pixel only after marketing consent with the c15t xPixel helper, guard twq conversion events, and check it in DevTools.
|
|
128
130
|
- [YouTube](./integrations/youtube.md): Gate YouTube embeds with c15t v3 in Next.js, TanStack Start, React, Nuxt, Vue, Astro, Svelte, SvelteKit or JavaScript.
|
|
129
|
-
|
|
130
|
-
## Reference
|
|
131
|
-
|
|
132
|
-
- [Migrate to v3](./upgrade-v3.md): Upgrade from c15t v2 to v3. Pick the guide for the v2 package you use (@c15t/nextjs, @c15t/react or the c15t store), rename @c15t/scripts, keep visitors' choices, and upgrade a self-hosted backend and the Node.js SDK.
|
|
@@ -76,10 +76,15 @@ public policy manifest, never a response that contains a visitor's consent.
|
|
|
76
76
|
## How the server gets the policy
|
|
77
77
|
|
|
78
78
|
Use a build-time manifest as the default for supported production builds.
|
|
79
|
-
Next.js, TanStack Start, Nuxt
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
`manifest()` is the default mode in Next.js, TanStack Start, Nuxt, Astro and
|
|
80
|
+
SvelteKit, so their servers resolve requests from the deployment's snapshot.
|
|
81
|
+
React, Vue and Svelte single-page apps have no server, so their quickstarts
|
|
82
|
+
use `hosted()`: the backend reads each visitor's location from the `/init`
|
|
83
|
+
request. They can bundle the manifest for browser resolution too, but a
|
|
84
|
+
regional policy still needs `/init` on a first visit unless the page knows
|
|
85
|
+
the location. The framework quickstarts show the build
|
|
86
|
+
integration. [Consent modes](./modes.md) lists every mode, its
|
|
87
|
+
options and the backend URL variable each framework reads.
|
|
83
88
|
|
|
84
89
|
The build fetches your public policy once and bundles it, so the server never
|
|
85
90
|
fetches it at runtime.
|
|
@@ -88,17 +93,49 @@ The snapshot is fixed at build time:
|
|
|
88
93
|
|
|
89
94
|
* Rebuild after changing policies, translations or vendors. If your CI caches
|
|
90
95
|
build output, force a fresh build.
|
|
91
|
-
* The build must reach the backend. A failed fetch fails the build.
|
|
92
96
|
* Consent choices still go to the backend.
|
|
93
97
|
|
|
98
|
+
The build reads the backend URL from your public backend URL variable when
|
|
99
|
+
the config doesn't pass one: `NEXT_PUBLIC_C15T_BACKEND_URL` in Next.js,
|
|
100
|
+
`NUXT_PUBLIC_C15T_BACKEND_URL` in Nuxt, `PUBLIC_C15T_BACKEND_URL` in Astro,
|
|
101
|
+
Svelte and SvelteKit, and `VITE_C15T_BACKEND_URL` in TanStack Start and other
|
|
102
|
+
Vite apps. Each also reads the matching Inth variable, such as
|
|
103
|
+
`NEXT_PUBLIC_INTH_PROJECT_URL`, when the c15t one is unset. See
|
|
104
|
+
[set the backend URL](./modes.md#set-the-backend-url).
|
|
105
|
+
|
|
106
|
+
The fetch waits at most 10 seconds. When it fails, or no backend URL is set,
|
|
107
|
+
every framework does the same thing:
|
|
108
|
+
|
|
109
|
+
| Command | Default when the fetch fails |
|
|
110
|
+
| ------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
111
|
+
| Production build: `next build`, `vite build`, `nuxt build`, `astro build` | The build stops with an error. |
|
|
112
|
+
| Dev: `next dev`, `vite dev`, `nuxt dev`, `astro dev` | A warning, and the server fetches the policy at runtime. |
|
|
113
|
+
|
|
114
|
+
Set `onBuildError` to use one behaviour for both. `'fail'` stops dev too.
|
|
115
|
+
`'runtime'` lets a production build finish, and the server fetches the policy
|
|
116
|
+
at runtime. The `C15T_ON_BUILD_ERROR` environment variable overrides the
|
|
117
|
+
option, so you can deploy during a backend outage without a code change:
|
|
118
|
+
|
|
119
|
+
```sh
|
|
120
|
+
C15T_ON_BUILD_ERROR=runtime npm run build
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Turborepo's strict environment mode hides undeclared variables from tasks, so
|
|
124
|
+
list `C15T_ON_BUILD_ERROR` in the build task's `passThroughEnv` there.
|
|
125
|
+
|
|
126
|
+
The build skips the fetch, without an error, when it can't use a snapshot,
|
|
127
|
+
for example when the backend URL is relative. With `onBuildError: 'fail'`, a
|
|
128
|
+
relative URL stops the build. [Consent modes](./modes.md#what-happens-when-the-download-fails)
|
|
129
|
+
lists every case.
|
|
130
|
+
|
|
94
131
|
For deployments that need policy updates without a rebuild, choose a runtime
|
|
95
132
|
path:
|
|
96
133
|
|
|
97
|
-
* **Cached manifest
|
|
134
|
+
* **Cached manifest**, `manifest({ source: 'runtime' })`.
|
|
98
135
|
Your server downloads the project's public policy file, caches it, and
|
|
99
136
|
resolves each visitor locally. Consent saves still go to the backend.
|
|
100
|
-
* **`/init
|
|
101
|
-
every page load makes a request to the backend.
|
|
137
|
+
* **`/init`**, `hosted()`. Each visit asks the backend to resolve the visitor.
|
|
138
|
+
Simpler, but every page load makes a request to the backend.
|
|
102
139
|
|
|
103
140
|
[Data fetching](./data-fetching.md) compares them in detail,
|
|
104
141
|
including proxies and custom transports.
|
|
@@ -81,4 +81,4 @@ client render. Set
|
|
|
81
81
|
|
|
82
82
|
Use effective permissions to gate work and explicit choices to inspect what the
|
|
83
83
|
visitor confirmed. Read [how consent works](./how-consent-works.md#a-permission-is-not-a-recorded-choice) for that
|
|
84
|
-
distinction and [
|
|
84
|
+
distinction and [policies](./policies.md) for v3 policy configuration.
|
|
@@ -130,8 +130,11 @@ Forward that configuration intact. Copying an allowed category into a receipt
|
|
|
130
130
|
would invent a grant and lose its original confirmation time.
|
|
131
131
|
|
|
132
132
|
Valid v2 records can be read without a startup rewrite. The next explicit action
|
|
133
|
-
writes the v3 format.
|
|
134
|
-
|
|
133
|
+
writes the v3 format. The upgrade guides for
|
|
134
|
+
[Next.js](https://c15t.com/docs/frameworks/next/upgrade-v3#keep-visitors-existing-choices),
|
|
135
|
+
[React](../frameworks/react/upgrade-v3.md#keep-visitors-existing-choices) and
|
|
136
|
+
[JavaScript](https://c15t.com/docs/frameworks/javascript/upgrade-v3#keep-visitors-existing-choices)
|
|
137
|
+
cover how v3 treats v2 records.
|
|
135
138
|
|
|
136
139
|
## Keep open tabs in step
|
|
137
140
|
|
|
@@ -14,14 +14,14 @@ the same protocol, so every path below works with either. Only `offline()`
|
|
|
14
14
|
removes backend requests. For a recommendation by framework, start with
|
|
15
15
|
[choose your setup](./choose-your-setup.md).
|
|
16
16
|
|
|
17
|
-
| Fetching path
|
|
18
|
-
|
|
|
19
|
-
| Build-time manifest, recommended | Your server
|
|
20
|
-
| Cached manifest on your server
|
|
21
|
-
| Regular backend `/init`
|
|
22
|
-
| Manifest in the browser
|
|
23
|
-
| Offline
|
|
24
|
-
| Custom transport
|
|
17
|
+
| Fetching path | Where policy resolves | Where choices are submitted | Choose it when |
|
|
18
|
+
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| Build-time manifest, recommended for server-rendered apps | Your server resolves a bundled policy snapshot with each visitor's inputs | Inth or your c15t backend | Your framework renders on the server, supports a build integration, and policy changes can ship with a rebuild |
|
|
20
|
+
| Cached manifest on your server | Your application resolves public policy data with each request's location and signals | Inth or your c15t backend | Policy changes must reach the app without rebuilding, or builds cannot access the backend |
|
|
21
|
+
| Regular backend `/init` | The consent backend | The same backend | You have no application server, as in a React, Vue or Svelte single-page app, want the fewest moving parts, or need backend-owned request resolution |
|
|
22
|
+
| Manifest in the browser | The browser, using a supplied location, or `/init` when the policy needs one it doesn't have | Inth or your c15t backend | The policy has no location rules or the page knows the visitor's location, and you accept about 3 KB more bundle and a rebuild for policy edits |
|
|
23
|
+
| Offline | The browser or local runtime, using bundled rules | No backend submission | Local development and tests. Not recommended for production environments. |
|
|
24
|
+
| Custom transport | Your implementation | Your implementation | An existing service cannot use the c15t backend protocol |
|
|
25
25
|
|
|
26
26
|
## What is a consent manifest?
|
|
27
27
|
|
|
@@ -45,19 +45,58 @@ requires a refresh strategy for cached or build-time manifests.
|
|
|
45
45
|
The build fetches your public policy once and bundles it, so the server never
|
|
46
46
|
fetches it at runtime.
|
|
47
47
|
|
|
48
|
+
`manifest()` is the default mode in every server-rendered framework.
|
|
49
|
+
[Consent modes](./modes.md#download-the-manifest-at-build-time)
|
|
50
|
+
covers each framework's build integration and what happens when the
|
|
51
|
+
download fails.
|
|
52
|
+
|
|
48
53
|
The framework quickstarts include the build integration for supported
|
|
49
54
|
deployments. Server resolution uses the snapshot without an upstream manifest
|
|
50
55
|
request. Browser resolution includes the policy and resolver in the client
|
|
51
|
-
bundle, and
|
|
56
|
+
bundle, and still calls `/init` for a regional policy when the browser doesn't
|
|
57
|
+
know the visitor's location, so the React, Vue and Svelte quickstarts use
|
|
58
|
+
`hosted()` instead. Static Nuxt and
|
|
52
59
|
Astro sites and script-tag sites keep the runtime setup from their guides.
|
|
53
60
|
|
|
54
61
|
The snapshot is fixed at build time:
|
|
55
62
|
|
|
56
63
|
* Rebuild after changing policies, translations or vendors. If your CI caches
|
|
57
64
|
build output, force a fresh build.
|
|
58
|
-
* The build must reach the backend. A failed fetch fails the build.
|
|
59
65
|
* Consent choices still go to the backend.
|
|
60
66
|
|
|
67
|
+
The build reads the backend URL from your public backend URL variable when
|
|
68
|
+
the config doesn't pass one: `NEXT_PUBLIC_C15T_BACKEND_URL` in Next.js,
|
|
69
|
+
`NUXT_PUBLIC_C15T_BACKEND_URL` in Nuxt, `PUBLIC_C15T_BACKEND_URL` in Astro,
|
|
70
|
+
Svelte and SvelteKit, and `VITE_C15T_BACKEND_URL` in TanStack Start and other
|
|
71
|
+
Vite apps. Each also reads the matching Inth variable, such as
|
|
72
|
+
`NEXT_PUBLIC_INTH_PROJECT_URL`, when the c15t one is unset. See
|
|
73
|
+
[set the backend URL](./modes.md#set-the-backend-url).
|
|
74
|
+
|
|
75
|
+
The fetch waits at most 10 seconds. When it fails, or no backend URL is set,
|
|
76
|
+
every framework does the same thing:
|
|
77
|
+
|
|
78
|
+
| Command | Default when the fetch fails |
|
|
79
|
+
| ------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
80
|
+
| Production build: `next build`, `vite build`, `nuxt build`, `astro build` | The build stops with an error. |
|
|
81
|
+
| Dev: `next dev`, `vite dev`, `nuxt dev`, `astro dev` | A warning, and the server fetches the policy at runtime. |
|
|
82
|
+
|
|
83
|
+
Set `onBuildError` to use one behaviour for both. `'fail'` stops dev too.
|
|
84
|
+
`'runtime'` lets a production build finish, and the server fetches the policy
|
|
85
|
+
at runtime. The `C15T_ON_BUILD_ERROR` environment variable overrides the
|
|
86
|
+
option, so you can deploy during a backend outage without a code change:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
C15T_ON_BUILD_ERROR=runtime npm run build
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Turborepo's strict environment mode hides undeclared variables from tasks, so
|
|
93
|
+
list `C15T_ON_BUILD_ERROR` in the build task's `passThroughEnv` there.
|
|
94
|
+
|
|
95
|
+
The build skips the fetch, without an error, when it can't use a snapshot,
|
|
96
|
+
for example when the backend URL is relative. With `onBuildError: 'fail'`, a
|
|
97
|
+
relative URL stops the build. [Consent modes](./modes.md#what-happens-when-the-download-fails)
|
|
98
|
+
lists every case.
|
|
99
|
+
|
|
61
100
|
## How manifest mode counts visitors
|
|
62
101
|
|
|
63
102
|
The backend counts visitors from `/init` requests, and manifest resolution
|
|
@@ -73,10 +112,10 @@ no report. Set `reportSessions: false` on an adapter to turn it off.
|
|
|
73
112
|
Each page load gets a journey id, a random UUID sent on requests c15t already
|
|
74
113
|
makes:
|
|
75
114
|
|
|
76
|
-
| Request | Query parameters
|
|
77
|
-
| ---------------- |
|
|
78
|
-
| `GET /init` | `
|
|
79
|
-
| `POST /subjects` | `
|
|
115
|
+
| Request | Query parameters |
|
|
116
|
+
| ---------------- | ------------------------------------------------------------------------------------ |
|
|
117
|
+
| `GET /init` | `journey`, `journeyScope`, `stored` (`1` if a choice or notice dismissal was stored) |
|
|
118
|
+
| `POST /subjects` | `journey`, `journeyScope` |
|
|
80
119
|
|
|
81
120
|
Session reports carry it as `journey: { id, scope, storedChoice, prompt, domain }`.
|
|
82
121
|
A report and a save with the same `id` belong to one page load. `prompt` is
|
|
@@ -96,35 +135,46 @@ Saves replayed after going offline carry none.
|
|
|
96
135
|
|
|
97
136
|
Set it on the runtime or provider. In Next.js use `defineConsentConfig({ journey })`;
|
|
98
137
|
in TanStack Start pass the same value to `resolveConsent` and `ConsentRoot`; with
|
|
99
|
-
the inline prefetch script, pass it to `buildPrefetchScript
|
|
138
|
+
the inline prefetch script, pass it to `buildPrefetchScript` or to
|
|
139
|
+
`consentManifest({ initPrefetch: { journey } })`. Left unset, the script
|
|
140
|
+
continues a `'tab'` journey the tab already holds. A tab's first page has
|
|
141
|
+
none, so its `/init` reports the scope as `'page'`. The id still links it to
|
|
142
|
+
the save. Pass `journey: 'tab'` to the script too if you report on scope. Vue, Svelte, Astro
|
|
100
143
|
and the script tag use `'page'`. A manifest that resolves locally in the
|
|
101
144
|
browser reports no init, so it sends no journey.
|
|
102
145
|
|
|
103
|
-
If you pass `hosted()` a `fetch`, match on the path: URLs now carry a query string.
|
|
146
|
+
If you pass a transport `hosted()` a `fetch`, match on the path: URLs now carry a query string.
|
|
104
147
|
|
|
105
148
|
## What does regular `/init` do?
|
|
106
149
|
|
|
107
|
-
`hosted(
|
|
108
|
-
consent submissions. The name `hosted` describes
|
|
109
|
-
can belong to Inth or your own c15t backend.
|
|
150
|
+
`hosted()` uses `${backendURL}/init` for initialization and
|
|
151
|
+
`${backendURL}/subjects` for consent submissions. The name `hosted` describes
|
|
152
|
+
the protocol; the URL can belong to Inth or your own c15t backend.
|
|
110
153
|
|
|
111
|
-
```ts title="
|
|
112
|
-
import { hosted } from 'c15t';
|
|
154
|
+
```ts title="c15t.config.ts"
|
|
155
|
+
import { defineConsentConfig, hosted } from 'c15t/next';
|
|
113
156
|
|
|
114
|
-
export
|
|
115
|
-
return hosted({ url: backendURL });
|
|
116
|
-
}
|
|
157
|
+
export default defineConsentConfig({ mode: hosted() });
|
|
117
158
|
```
|
|
118
159
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
160
|
+
Each framework passes the mode in a different place, and server-rendered
|
|
161
|
+
frameworks take the data `hosted()` from their own package.
|
|
162
|
+
[Consent modes](./modes.md#import-the-factories-from-your-framework-package)
|
|
163
|
+
lists where each one goes.
|
|
122
164
|
|
|
123
165
|
A regular backend `/init` request lets the backend resolve the visitor context.
|
|
124
166
|
A same-origin URL named `/api/c15t/init` can instead resolve from a cached
|
|
125
167
|
manifest in your application. The URL name alone does not tell you which path
|
|
126
168
|
runs.
|
|
127
169
|
|
|
170
|
+
In the browser, an inline script in `<head>` can start `/init` while the
|
|
171
|
+
app's JavaScript downloads, and `hosted()` uses that response. Vite apps get
|
|
172
|
+
it from `consentManifest()` by default, Nuxt adds it to pages with
|
|
173
|
+
`ssr: false`, and TanStack Start has `consentPrefetchHead`. Elsewhere, render
|
|
174
|
+
`buildPrefetchScript({ backendURL })` from `c15t` yourself. If c15t assigns
|
|
175
|
+
a banner experiment's arm, give the script the same `experiment`, or
|
|
176
|
+
`hosted()` sends a second `/init` for visitors who have not chosen yet.
|
|
177
|
+
|
|
128
178
|
## How do transports and proxies differ?
|
|
129
179
|
|
|
130
180
|
A transport implements initialization, saving and optional record operations.
|
|
@@ -133,28 +183,35 @@ resolver or make personalized responses safe to cache.
|
|
|
133
183
|
|
|
134
184
|
For a same-origin init route that resolves a manifest, the hosted transport can
|
|
135
185
|
separate policy reads and record writes. With a backend rewrite mounted at
|
|
136
|
-
`/api/c15t`, a
|
|
186
|
+
`/api/c15t`, a single-page app can use the transport `hosted()` from
|
|
187
|
+
`c15t`:
|
|
137
188
|
|
|
138
189
|
```ts title="src/consent-mode.ts"
|
|
139
190
|
import { hosted } from 'c15t';
|
|
140
191
|
|
|
141
192
|
export const mode = hosted({
|
|
142
|
-
|
|
193
|
+
backendURL: '/api/c15t',
|
|
143
194
|
initURL: '/api/c15t/init',
|
|
144
|
-
assertDecisionInputs: true,
|
|
145
195
|
});
|
|
146
196
|
```
|
|
147
197
|
|
|
148
|
-
The route must return the c15t init response contract.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
`
|
|
198
|
+
The route must return the c15t init response contract. c15t adds its inputs to
|
|
199
|
+
`initURL` as query parameters, replacing any of your own with the same name.
|
|
200
|
+
See [query parameters and CORS](https://c15t.com/docs/self-host/api/endpoints#query-parameters-and-cors)
|
|
201
|
+
for the names. Because `initURL` is set, `assertDecisionInputs` defaults to
|
|
202
|
+
`true`: saves carry the policy decision they were made against when init
|
|
203
|
+
returned no signed policy snapshot token, so the backend can reject a save
|
|
204
|
+
made against a stale policy. Server-rendered frameworks do this for you when
|
|
205
|
+
you set `routePrefix`: the browser re-inits through `${routePrefix}/init`.
|
|
206
|
+
Every framework rejects `routePrefix: '/'` when it sets up, because a
|
|
207
|
+
catch-all consent route at the site root would catch every page.
|
|
153
208
|
|
|
154
209
|
The init route resolves policy; the backend rewrite forwards `/api/c15t/subjects`
|
|
155
210
|
and other record endpoints. Configure both if you choose this optional proxy
|
|
156
|
-
variant.
|
|
157
|
-
|
|
211
|
+
variant. Server-rendered frameworks do both with one option: `proxy: true` in
|
|
212
|
+
Next.js `c15t.config.ts` or TanStack Start's `createConsentStateHandler`,
|
|
213
|
+
with a consent route created with `proxy: true`. The
|
|
214
|
+
[Next.js recipe](https://c15t.com/docs/frameworks/next/optimization#keep-browser-consent-requests-on-your-origin)
|
|
158
215
|
shows the configuration. A direct absolute backend URL works
|
|
159
216
|
without a rewrite.
|
|
160
217
|
|
|
@@ -179,9 +236,8 @@ saves locally. The runtime's persistence module stores the choice in browser
|
|
|
179
236
|
storage. There is no backend audit history, cross-device record service or IP
|
|
180
237
|
geolocation supplied by this transport.
|
|
181
238
|
|
|
182
|
-
Use your
|
|
183
|
-
included.
|
|
184
|
-
client provider:
|
|
239
|
+
Use your framework's `offline()` so its translations and provider context are
|
|
240
|
+
included. In a React app it replaces the mode passed to `ConsentProvider`:
|
|
185
241
|
|
|
186
242
|
```ts title="src/consent-mode.ts"
|
|
187
243
|
import { offline } from 'c15t/react';
|
|
@@ -189,6 +245,10 @@ import { offline } from 'c15t/react';
|
|
|
189
245
|
export const mode = offline();
|
|
190
246
|
```
|
|
191
247
|
|
|
248
|
+
In Next.js, TanStack Start, Nuxt, Astro and SvelteKit, pass the data
|
|
249
|
+
`offline()` from the framework package where the config takes `mode`; see
|
|
250
|
+
[consent modes](./modes.md#import-the-factories-from-your-framework-package).
|
|
251
|
+
|
|
192
252
|
With no `policyRules`, the current offline transport uses the recommended rule
|
|
193
253
|
pack. Supplying `policyRules` replaces that pack. Unknown country and region are
|
|
194
254
|
real resolution inputs; offline mode does not discover a visitor's location.
|