@c15t/react 3.0.0-alpha.9 → 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 +7 -9
- 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/shared/primitives/button.js +1 -1
- package/dist/components/shared/surface-styles.js +1 -1
- package/dist/consent-gate.js +1 -1
- package/dist/context/index.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/iab/styles.tw3.css +2 -2
- 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/surface-styles.d.ts +26 -2
- 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/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 +3 -3
- package/dist-types/transports/hosted.d.ts +36 -0
- package/dist-types/transports/manifest.d.ts +48 -0
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +7 -9
- package/docs/concepts/choose-your-setup.md +45 -10
- package/docs/concepts/consent-categories.md +1 -1
- package/docs/concepts/consent-state.md +5 -2
- package/docs/concepts/data-fetching.md +100 -42
- 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/recipes.md +4 -4
- package/docs/customization/slots.md +25 -25
- package/docs/customization/stylesheets.md +12 -14
- package/docs/customization/tailwind.md +17 -11
- package/docs/customization/tokens.md +36 -7
- package/docs/frameworks/react/components/consent-banner.md +14 -10
- package/docs/frameworks/react/components/consent-dialog.md +14 -10
- package/docs/frameworks/react/components/consent-provider.md +51 -44
- package/docs/frameworks/react/components.md +14 -10
- package/docs/frameworks/react/content-security-policy.md +21 -12
- package/docs/frameworks/react/hooks.md +2 -2
- package/docs/frameworks/react/iab.md +20 -2
- package/docs/frameworks/react/quickstart.md +63 -97
- package/docs/frameworks/react/rendering.md +168 -94
- package/docs/frameworks/react/scripts.md +19 -28
- package/docs/frameworks/react/troubleshooting.md +57 -25
- package/docs/frameworks/react/upgrade-v3.md +110 -62
- package/docs/guides/banner-experiments.md +21 -6
- package/docs/guides/troubleshooting.md +89 -25
- 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
|
@@ -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,21 +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 stops Next.js, TanStack
|
|
59
|
-
Start, SvelteKit and Vite builds. By default, Astro and Nuxt log a warning
|
|
60
|
-
instead and fetch the policy at runtime.
|
|
61
65
|
* Consent choices still go to the backend.
|
|
62
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
|
+
|
|
63
100
|
## How manifest mode counts visitors
|
|
64
101
|
|
|
65
102
|
The backend counts visitors from `/init` requests, and manifest resolution
|
|
@@ -75,10 +112,10 @@ no report. Set `reportSessions: false` on an adapter to turn it off.
|
|
|
75
112
|
Each page load gets a journey id, a random UUID sent on requests c15t already
|
|
76
113
|
makes:
|
|
77
114
|
|
|
78
|
-
| Request | Query parameters
|
|
79
|
-
| ---------------- |
|
|
80
|
-
| `GET /init` | `
|
|
81
|
-
| `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` |
|
|
82
119
|
|
|
83
120
|
Session reports carry it as `journey: { id, scope, storedChoice, prompt, domain }`.
|
|
84
121
|
A report and a save with the same `id` belong to one page load. `prompt` is
|
|
@@ -98,35 +135,46 @@ Saves replayed after going offline carry none.
|
|
|
98
135
|
|
|
99
136
|
Set it on the runtime or provider. In Next.js use `defineConsentConfig({ journey })`;
|
|
100
137
|
in TanStack Start pass the same value to `resolveConsent` and `ConsentRoot`; with
|
|
101
|
-
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
|
|
102
143
|
and the script tag use `'page'`. A manifest that resolves locally in the
|
|
103
144
|
browser reports no init, so it sends no journey.
|
|
104
145
|
|
|
105
|
-
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.
|
|
106
147
|
|
|
107
148
|
## What does regular `/init` do?
|
|
108
149
|
|
|
109
|
-
`hosted(
|
|
110
|
-
consent submissions. The name `hosted` describes
|
|
111
|
-
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.
|
|
112
153
|
|
|
113
|
-
```ts title="
|
|
114
|
-
import { hosted } from 'c15t';
|
|
154
|
+
```ts title="c15t.config.ts"
|
|
155
|
+
import { defineConsentConfig, hosted } from 'c15t/next';
|
|
115
156
|
|
|
116
|
-
export
|
|
117
|
-
return hosted({ url: backendURL });
|
|
118
|
-
}
|
|
157
|
+
export default defineConsentConfig({ mode: hosted() });
|
|
119
158
|
```
|
|
120
159
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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.
|
|
124
164
|
|
|
125
165
|
A regular backend `/init` request lets the backend resolve the visitor context.
|
|
126
166
|
A same-origin URL named `/api/c15t/init` can instead resolve from a cached
|
|
127
167
|
manifest in your application. The URL name alone does not tell you which path
|
|
128
168
|
runs.
|
|
129
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
|
+
|
|
130
178
|
## How do transports and proxies differ?
|
|
131
179
|
|
|
132
180
|
A transport implements initialization, saving and optional record operations.
|
|
@@ -135,28 +183,35 @@ resolver or make personalized responses safe to cache.
|
|
|
135
183
|
|
|
136
184
|
For a same-origin init route that resolves a manifest, the hosted transport can
|
|
137
185
|
separate policy reads and record writes. With a backend rewrite mounted at
|
|
138
|
-
`/api/c15t`, a
|
|
186
|
+
`/api/c15t`, a single-page app can use the transport `hosted()` from
|
|
187
|
+
`c15t`:
|
|
139
188
|
|
|
140
189
|
```ts title="src/consent-mode.ts"
|
|
141
190
|
import { hosted } from 'c15t';
|
|
142
191
|
|
|
143
192
|
export const mode = hosted({
|
|
144
|
-
|
|
193
|
+
backendURL: '/api/c15t',
|
|
145
194
|
initURL: '/api/c15t/init',
|
|
146
|
-
assertDecisionInputs: true,
|
|
147
195
|
});
|
|
148
196
|
```
|
|
149
197
|
|
|
150
|
-
The route must return the c15t init response contract.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
`
|
|
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.
|
|
155
208
|
|
|
156
209
|
The init route resolves policy; the backend rewrite forwards `/api/c15t/subjects`
|
|
157
210
|
and other record endpoints. Configure both if you choose this optional proxy
|
|
158
|
-
variant.
|
|
159
|
-
|
|
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)
|
|
160
215
|
shows the configuration. A direct absolute backend URL works
|
|
161
216
|
without a rewrite.
|
|
162
217
|
|
|
@@ -181,9 +236,8 @@ saves locally. The runtime's persistence module stores the choice in browser
|
|
|
181
236
|
storage. There is no backend audit history, cross-device record service or IP
|
|
182
237
|
geolocation supplied by this transport.
|
|
183
238
|
|
|
184
|
-
Use your
|
|
185
|
-
included.
|
|
186
|
-
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`:
|
|
187
241
|
|
|
188
242
|
```ts title="src/consent-mode.ts"
|
|
189
243
|
import { offline } from 'c15t/react';
|
|
@@ -191,6 +245,10 @@ import { offline } from 'c15t/react';
|
|
|
191
245
|
export const mode = offline();
|
|
192
246
|
```
|
|
193
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
|
+
|
|
194
252
|
With no `policyRules`, the current offline transport uses the recommended rule
|
|
195
253
|
pack. Supplying `policyRules` replaces that pack. Unknown country and region are
|
|
196
254
|
real resolution inputs; offline mode does not discover a visitor's location.
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Consent modes
|
|
3
|
+
description: Reference for manifest(), hosted() and offline() in every c15t
|
|
4
|
+
framework package, where each one resolves the visitor's policy, what it adds
|
|
5
|
+
to first-load JavaScript, the build-time manifest fetch and its failure
|
|
6
|
+
policy, and the backend URL variable each framework reads.
|
|
7
|
+
group: concepts
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Choose a mode
|
|
11
|
+
|
|
12
|
+
A mode decides how c15t finds the policy that applies to a visitor. Every
|
|
13
|
+
framework package exports the same three factories, `manifest()`, `hosted()`
|
|
14
|
+
and `offline()`. Consent choices go to the backend in `manifest()` and
|
|
15
|
+
`hosted()`, whether that backend is [Inth](https://inth.com) or a
|
|
16
|
+
[self-hosted c15t backend](https://c15t.com/docs/self-host/quickstart).
|
|
17
|
+
|
|
18
|
+
| Mode | Where the policy resolves | Backend requests on a first visit | Use it when |
|
|
19
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `manifest()`, the default | Your server, from the policy the build downloaded. With `resolve: 'browser'`, or in a single-page app, the browser. | None to resolve the policy, unless the browser needs a location it doesn't have. Choices post to `/subjects`. | Server-rendered apps. Rebuild to ship policy changes, or set `source: 'runtime'`. |
|
|
21
|
+
| `hosted()` | The backend's `GET /init` | One `/init` per page that resolves consent. | Single-page apps and static hosting without a server, where the backend reads each visitor's location from the request. Policy edits apply without a rebuild. |
|
|
22
|
+
| `offline()` | The browser, from rules in your bundle | None. Choices stay in the browser. | Local development, tests and demos. Not recommended for production environments. |
|
|
23
|
+
|
|
24
|
+
`manifest()` is the default in Next.js, TanStack Start, Nuxt, Astro and
|
|
25
|
+
SvelteKit. React, Vue, Svelte and `@c15t/browser` have no default: pass a
|
|
26
|
+
mode yourself. The React, Vue and Svelte quickstarts use `hosted()`, because
|
|
27
|
+
a browser has no request location and a bundled regional policy still needs
|
|
28
|
+
`/init` on a first visit. The JavaScript quickstart uses `manifest()`. The
|
|
29
|
+
script tag picks its
|
|
30
|
+
mode from the bundle file; see
|
|
31
|
+
[choose a mode](https://c15t.com/docs/frameworks/html/attributes-and-api#choose-a-mode).
|
|
32
|
+
|
|
33
|
+
[Data fetching](./data-fetching.md) compares these paths with the
|
|
34
|
+
custom transport and same-origin proxies.
|
|
35
|
+
|
|
36
|
+
## Import the factories from your framework package
|
|
37
|
+
|
|
38
|
+
There are two kinds of factory, and each framework package exports the kind it
|
|
39
|
+
needs under the same three names.
|
|
40
|
+
|
|
41
|
+
| Framework | Import from | Pass the mode to | Kind |
|
|
42
|
+
| -------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------- |
|
|
43
|
+
| Next.js | `c15t/next` | `mode` in `c15t.config.ts` | Data |
|
|
44
|
+
| TanStack Start | `c15t/tanstack-start` | `createConsentStateHandler({ mode })` | Data |
|
|
45
|
+
| Nuxt | `c15t/vue` | `c15t.mode` in `nuxt.config.ts` | Data |
|
|
46
|
+
| Astro | `c15t/astro` | `c15t({ mode })` in `astro.config.mjs` | Data |
|
|
47
|
+
| SvelteKit | `@c15t/svelte/kit` | `c15tHandle({ mode })` in `src/hooks.server.ts` | Data |
|
|
48
|
+
| React | `c15t/react` | `ConsentProvider`'s `options.mode` | Transport |
|
|
49
|
+
| Vue | `c15t/vue/vue-plugin` | `app.use(c15tVue, { mode })` | Transport |
|
|
50
|
+
| Svelte | `@c15t/svelte` | `<ConsentProvider mode={...}>` | Transport |
|
|
51
|
+
| JavaScript | `@c15t/browser` | `init({ mode })` | Transport |
|
|
52
|
+
| Script tag | none | The bundle file: `c15t.js` is hosted, `c15t.offline.js` offline. The headless and IAB scripts also take `data-mode="manifest"`. | Name |
|
|
53
|
+
|
|
54
|
+
**Data factories** return a plain object such as `{ type: 'manifest' }`.
|
|
55
|
+
Server-rendered frameworks read their config on the server and in the
|
|
56
|
+
browser, and Nuxt and Astro serialize it, so the mode has to be data. The
|
|
57
|
+
framework turns it into a transport in the browser and loads the code of
|
|
58
|
+
any mode other than the default with `import()`. The same factories are
|
|
59
|
+
available from `c15t/modes` (or `@c15t/core/modes`) for shared code.
|
|
60
|
+
|
|
61
|
+
**Transport factories** return the transport itself, with the same `type` and
|
|
62
|
+
options attached as properties. A single-page app has one environment, so
|
|
63
|
+
the bundler keeps only the mode you import and drops the others.
|
|
64
|
+
|
|
65
|
+
A server-rendered root that receives a transport factory still works, for
|
|
66
|
+
example `hosted()` from `c15t/react` passed to Next.js `ConsentRoot` as
|
|
67
|
+
`options.mode`. Outside production it warns that the transport's code is now
|
|
68
|
+
in the first-load bundle. `custom(transport)` exists only as a transport, so
|
|
69
|
+
it cannot go in a serializable config. Pass it through the root's
|
|
70
|
+
`options.mode` instead.
|
|
71
|
+
|
|
72
|
+
## manifest()
|
|
73
|
+
|
|
74
|
+
`manifest()` resolves the visitor's policy from the backend's public consent
|
|
75
|
+
manifest instead of asking the backend's `/init`. A
|
|
76
|
+
[consent manifest](./data-fetching.md#what-is-a-consent-manifest)
|
|
77
|
+
holds your policy rules and copy, and no visitor data.
|
|
78
|
+
|
|
79
|
+
| Option | Default | Behavior |
|
|
80
|
+
| ------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `source` | `'build'` | `'build'` uses the snapshot the build integration downloaded. Without one, such as in dev after a failed fetch, it fetches the manifest at runtime. `'runtime'` always fetches at runtime, so policy edits apply without a rebuild. |
|
|
82
|
+
| `snapshot` | none | A manifest you supply. You can pass `snapshot` or `source`, not both. |
|
|
83
|
+
| `resolve` | `'server'` | `'server'` resolves each visitor on the server and ships no resolver to the browser. `'browser'` resolves in the browser, for pages the server does not render per visitor. Server-rendered frameworks only. |
|
|
84
|
+
| `manifestURL` | see below | Where to fetch the manifest at runtime. On the server, `${backendURL}/manifest`. In the browser, `${routePrefix}/manifest`, else `${backendURL}/manifest`. |
|
|
85
|
+
| `geoURL` | none | A same-origin route that answers with the visitor's `{ country, region }`. Browser resolution only. |
|
|
86
|
+
| `inputs` | none | `{ country, region }` when the page already knows the visitor's location, for example from an edge worker. Browser resolution only. |
|
|
87
|
+
|
|
88
|
+
The transport `manifest()` from `c15t/react`, `c15t/vue/vue-plugin`,
|
|
89
|
+
`@c15t/svelte` and `@c15t/browser` always resolves in the browser, so it has
|
|
90
|
+
no `resolve` option. It also takes `backendURL`, `headers`, `credentials`,
|
|
91
|
+
`domain`, `fetch` and `initFallback`. With no options it reads the snapshot
|
|
92
|
+
and the backend URL your build integration downloaded. With `manifestURL`,
|
|
93
|
+
the browser fetches that URL when the page loads and the build's snapshot is
|
|
94
|
+
not used. Saves still go to `backendURL`, or the build's backend URL.
|
|
95
|
+
|
|
96
|
+
When the policy depends on where the visitor is, and the browser does not
|
|
97
|
+
know the country or region, browser resolution asks `geoURL`, then the
|
|
98
|
+
backend's `/init`. Set `initFallback: false` to resolve for an unknown location
|
|
99
|
+
instead. A policy with location rules therefore saves no request in a
|
|
100
|
+
single-page app unless you pass `inputs` or `geoURL`. The `consentManifest()`
|
|
101
|
+
plugins from `c15t/build`, `c15t/vue/vite` and `@c15t/svelte/vite` warn
|
|
102
|
+
about this when a single-page app build bundles such a policy.
|
|
103
|
+
|
|
104
|
+
## hosted()
|
|
105
|
+
|
|
106
|
+
`hosted()` asks the backend's `GET /init` for each visitor's policy and posts
|
|
107
|
+
choices to `${backendURL}/subjects`.
|
|
108
|
+
|
|
109
|
+
| Option | Default | Behavior |
|
|
110
|
+
| ------------ | --------------------------- | ------------------------------------------------------ |
|
|
111
|
+
| `backendURL` | the framework's backend URL | Backend URL, absolute or relative such as `/api/c15t`. |
|
|
112
|
+
| `headers` | none | Headers sent with `GET /init`. |
|
|
113
|
+
|
|
114
|
+
The transport `hosted()` also takes `initURL`, `assertDecisionInputs`,
|
|
115
|
+
`domain` and `fetch`. `initURL` sends `GET /init` to another URL, usually a
|
|
116
|
+
same-origin route that resolves the manifest, while saves keep going to
|
|
117
|
+
`${backendURL}/subjects`. `assertDecisionInputs` defaults to `true` when
|
|
118
|
+
`initURL` is set, so each save carries the policy decision it was made
|
|
119
|
+
against and the backend can reject a save made against a stale policy.
|
|
120
|
+
|
|
121
|
+
`hosted()` from `c15t` (`@c15t/core`) is the plain transport and requires
|
|
122
|
+
`backendURL`. The framework exports fill it in from your config or your
|
|
123
|
+
build.
|
|
124
|
+
|
|
125
|
+
## offline()
|
|
126
|
+
|
|
127
|
+
Not recommended for production environments.
|
|
128
|
+
|
|
129
|
+
`offline()` resolves policy rules in the browser and stores choices in browser
|
|
130
|
+
storage. Nothing reaches a backend, so there is no consent record, no
|
|
131
|
+
cross-device history and no IP geolocation.
|
|
132
|
+
|
|
133
|
+
| Option | Default | Behavior |
|
|
134
|
+
| ------------- | ------------------------- | ----------------------------------------------------------- |
|
|
135
|
+
| `policyRules` | the recommended rule pack | Rules to resolve. Passing rules replaces the pack entirely. |
|
|
136
|
+
|
|
137
|
+
Unknown country and region are real inputs: test the missing-location case
|
|
138
|
+
against your rules. See [policy rules](./policies.md).
|
|
139
|
+
|
|
140
|
+
## What each mode adds to first-load JavaScript
|
|
141
|
+
|
|
142
|
+
In a server-rendered framework, the browser receives the resolved state with
|
|
143
|
+
the page. It only needs the code to save a choice, and loads the rest when it
|
|
144
|
+
runs:
|
|
145
|
+
|
|
146
|
+
| Mode | First-load JavaScript | Loaded with `import()` when it runs |
|
|
147
|
+
| ---------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
148
|
+
| `manifest()` | The code that saves choices and builds an init request | The hosted init path, if the browser has to resolve consent again |
|
|
149
|
+
| `manifest({ resolve: 'browser' })` | The code that saves choices | The browser resolver, English copy and the fetch of `${routePrefix}/manifest` or `${backendURL}/manifest`. Other languages load per language. |
|
|
150
|
+
| `hosted()` | The code that saves choices | The hosted init path |
|
|
151
|
+
| `offline()` | Nothing mode-specific | The offline transport, the rule pack and its copy |
|
|
152
|
+
|
|
153
|
+
With `manifest()` resolved on the server, the manifest snapshot, the resolver,
|
|
154
|
+
the offline rule pack and other languages stay out of the browser bundle.
|
|
155
|
+
|
|
156
|
+
In a single-page app the bundle contains the mode you imported:
|
|
157
|
+
|
|
158
|
+
| Mode | In the bundle |
|
|
159
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
160
|
+
| `manifest()` | The snapshot, when the build downloaded one, and the code that saves choices. The resolver starts loading when `manifest()` runs, unless the policy needs a location the page does not know. English copy is bundled; other languages load the first time a visitor needs one. |
|
|
161
|
+
| `hosted()` | The hosted transport |
|
|
162
|
+
| `offline()` | The offline transport, the recommended rule pack and its copy |
|
|
163
|
+
|
|
164
|
+
## Set the backend URL
|
|
165
|
+
|
|
166
|
+
Each framework reads its backend URL from a public environment variable, so
|
|
167
|
+
the quickstarts never write it in code. Put it in `.env` or your host's build
|
|
168
|
+
settings. The value is public configuration, not a secret.
|
|
169
|
+
|
|
170
|
+
| Framework | Variable | Inth alternative |
|
|
171
|
+
| --------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
|
|
172
|
+
| Next.js | `NEXT_PUBLIC_C15T_BACKEND_URL` | `NEXT_PUBLIC_INTH_PROJECT_URL` |
|
|
173
|
+
| Nuxt | `NUXT_PUBLIC_C15T_BACKEND_URL` | `NUXT_PUBLIC_INTH_PROJECT_URL` |
|
|
174
|
+
| Astro | `PUBLIC_C15T_BACKEND_URL` | `PUBLIC_INTH_PROJECT_URL` |
|
|
175
|
+
| SvelteKit and Svelte | `PUBLIC_C15T_BACKEND_URL`, then `VITE_C15T_BACKEND_URL` | `PUBLIC_INTH_PROJECT_URL`, then `VITE_INTH_PROJECT_URL` |
|
|
176
|
+
| TanStack Start, React, Vue and JavaScript with Vite | `VITE_C15T_BACKEND_URL` | `VITE_INTH_PROJECT_URL` |
|
|
177
|
+
| Script tag | `data-backend-url` on the script element | – |
|
|
178
|
+
|
|
179
|
+
Set either variable. The Inth one holds your Inth project URL, so other Inth
|
|
180
|
+
SDKs in the same app can read it too. When both are set, the c15t variable
|
|
181
|
+
wins.
|
|
182
|
+
|
|
183
|
+
A backend URL resolves in this order: the mode's own `backendURL`, then the
|
|
184
|
+
framework's top-level `backendURL` option, then the c15t variable, then the
|
|
185
|
+
Inth variable. The build reads each variable from the process environment,
|
|
186
|
+
then from `.env.[mode].local`, `.env.[mode]`, `.env.local` and `.env` in the
|
|
187
|
+
project root, so a c15t variable in `.env` still beats an Inth variable in
|
|
188
|
+
the environment. The Vite plugins set an unset `VITE_C15T_BACKEND_URL` to the
|
|
189
|
+
URL they used, so `import.meta.env.VITE_C15T_BACKEND_URL` in app code reads
|
|
190
|
+
the same value. `withConsentManifest()` does the same for
|
|
191
|
+
`NEXT_PUBLIC_C15T_BACKEND_URL` in Next.js.
|
|
192
|
+
|
|
193
|
+
Next.js inlines `NEXT_PUBLIC_` variables at build time. Changing the variable
|
|
194
|
+
on a built app has no effect until you rebuild.
|
|
195
|
+
|
|
196
|
+
## Download the manifest at build time
|
|
197
|
+
|
|
198
|
+
`manifest()` with the default `source: 'build'` resolves from a snapshot that a
|
|
199
|
+
build integration downloads from `${backendURL}/manifest`:
|
|
200
|
+
|
|
201
|
+
| Framework | Build integration | Name in messages |
|
|
202
|
+
| -------------------- | ------------------------------------------------------------------- | ---------------------------- |
|
|
203
|
+
| Next.js | `withConsentManifest()` from `c15t/next/build`, in `next.config.ts` | `@c15t/nextjs/build` |
|
|
204
|
+
| TanStack Start | `consentManifest()` from `c15t/tanstack-start/build` | `@c15t/tanstack-start/build` |
|
|
205
|
+
| React and JavaScript | `consentManifest()` from `c15t/build` | `@c15t/core/build` |
|
|
206
|
+
| Vue | `consentManifest()` from `c15t/vue/vite` | `@c15t/vue/vite` |
|
|
207
|
+
| Svelte and SvelteKit | `consentManifest()` from `@c15t/svelte/vite` | `@c15t/svelte/vite` |
|
|
208
|
+
| Nuxt | the `c15t/vue` module | `@c15t/vue` |
|
|
209
|
+
| Astro | the `c15t()` integration | `@c15t/astro` |
|
|
210
|
+
|
|
211
|
+
The integration downloads the manifest when the production build or the dev
|
|
212
|
+
server starts, and waits at most 10 seconds. Nothing is written into your
|
|
213
|
+
source tree. App code reads the result from `c15t/generated`:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { backendURL, snapshot } from 'c15t/generated';
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Both exports are `undefined` when the build has no snapshot, so imports
|
|
220
|
+
compile on a fresh checkout. In the browser bundle of a server-rendered
|
|
221
|
+
framework, `snapshot` is always `undefined`. Next.js goes further: a client
|
|
222
|
+
component that imports `c15t/generated` fails the build.
|
|
223
|
+
|
|
224
|
+
Rebuild after you change policies, translations or vendors in your project. If
|
|
225
|
+
your CI caches build output, force a fresh build.
|
|
226
|
+
|
|
227
|
+
## What happens when the download fails
|
|
228
|
+
|
|
229
|
+
The same policy applies in every framework:
|
|
230
|
+
|
|
231
|
+
| Command | Default when the download fails or no backend URL is set |
|
|
232
|
+
| ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
233
|
+
| Production build: `next build`, `vite build`, `nuxt build`, `astro build` | The build stops with an error. |
|
|
234
|
+
| Dev: `next dev`, `vite dev`, `nuxt dev`, `astro dev` | A warning. The server, or a single-page app's browser, fetches the manifest at runtime. |
|
|
235
|
+
|
|
236
|
+
`onBuildError` picks one behavior for both commands:
|
|
237
|
+
|
|
238
|
+
* `'fail'` stops dev too.
|
|
239
|
+
* `'runtime'` lets a production build finish without a snapshot. The manifest
|
|
240
|
+
is then fetched at runtime.
|
|
241
|
+
|
|
242
|
+
Pass it where you configure the integration: the second argument of
|
|
243
|
+
`withConsentManifest()`, `consentManifest({ onBuildError })`, the `c15t` key
|
|
244
|
+
in `nuxt.config.ts`, or `c15t({ onBuildError })` in Astro.
|
|
245
|
+
|
|
246
|
+
The `C15T_ON_BUILD_ERROR` environment variable overrides the option, so you
|
|
247
|
+
can deploy during a backend outage without a code change:
|
|
248
|
+
|
|
249
|
+
```sh
|
|
250
|
+
C15T_ON_BUILD_ERROR=runtime npm run build
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Any value other than `fail` or `runtime` stops the command. Turborepo's strict
|
|
254
|
+
environment mode hides undeclared variables from tasks, so list
|
|
255
|
+
`C15T_ON_BUILD_ERROR` in the build task's `passThroughEnv` there.
|
|
256
|
+
|
|
257
|
+
A missing backend URL follows the same policy as a failed download: a
|
|
258
|
+
production build stops, dev warns, and an explicit `'runtime'` logs a notice
|
|
259
|
+
and continues. Astro and Nuxt are stricter in `manifest()` mode, including
|
|
260
|
+
`manifest({ snapshot })`: the browser saves consent to the backend, so a
|
|
261
|
+
missing backend URL stops `astro dev` and `nuxt dev` as well.
|
|
262
|
+
|
|
263
|
+
The download is skipped without an error when the build cannot use a
|
|
264
|
+
snapshot:
|
|
265
|
+
|
|
266
|
+
* The backend URL is relative, such as `/api/c15t`. With an explicit
|
|
267
|
+
`onBuildError: 'fail'`, a relative URL stops the build instead.
|
|
268
|
+
* Next.js builds with `output: 'export'`, which has no server.
|
|
269
|
+
* The mode is `hosted()`, `offline()`, `manifest({ snapshot })` or
|
|
270
|
+
`manifest({ source: 'runtime' })` in Next.js, Nuxt and Astro. Next.js reads
|
|
271
|
+
the mode from `c15t.config.ts`.
|
|
272
|
+
* A single-page app built with Vite (React, Vue, Svelte, JavaScript) does
|
|
273
|
+
not use `manifest()`. The mode is set in app code, so the plugin downloads
|
|
274
|
+
the manifest only once the bundle turns out to read it, after unused code
|
|
275
|
+
is dropped. A `hosted()` or `offline()` build never contacts the backend.
|
|
276
|
+
SvelteKit and TanStack Start choose the mode on the server at runtime, so
|
|
277
|
+
their builds always download it.
|
|
278
|
+
|
|
279
|
+
A failed download never reuses an older snapshot. The
|
|
280
|
+
[troubleshooting guide](../guides/troubleshooting.md#why-does-the-build-fail-to-download-the-manifest)
|
|
281
|
+
lists each message and its fix.
|
|
@@ -35,7 +35,7 @@ your site and let c15t follow it.
|
|
|
35
35
|
| Nuxt | `colorScheme` under the `c15t` key in `nuxt.config.ts`, or in `app/app.config.ts` | Unset: copies `dark` |
|
|
36
36
|
| Vue | `colorScheme` in the `c15tVue` options | Unset: copies `dark` |
|
|
37
37
|
| Astro | `colorScheme` in the `c15t()` integration options | `'system'` |
|
|
38
|
-
| Svelte, SvelteKit | `colorScheme` on `
|
|
38
|
+
| Svelte, SvelteKit | `colorScheme` on `ConsentProvider` (Svelte) or `ConsentRoot` (SvelteKit) | Unset: copies `dark` |
|
|
39
39
|
| HTML | `data-color-scheme` on the script tag: `light`, `dark`, `system` or `none` | `system` |
|
|
40
40
|
| JavaScript | `ui.colorScheme` in `init()` | `'system'` |
|
|
41
41
|
|
|
@@ -55,12 +55,12 @@ surface where your framework allows:
|
|
|
55
55
|
|
|
56
56
|
| Framework | For every surface | For one surface |
|
|
57
57
|
| ----------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
-
| Next.js, TanStack Start | `options.disableAnimation` on `ConsentRoot`
|
|
58
|
+
| Next.js, TanStack Start | `options.disableAnimation` in Next.js `c15t.config.ts`, or on `ConsentRoot` | `disableAnimation` prop on `ConsentBanner`, `ConsentDialog`, `IABConsentBanner`, `IABConsentDialog` |
|
|
59
59
|
| React | `disableAnimation` in the `ConsentProvider` options | The same component props |
|
|
60
60
|
| Nuxt | `disableAnimation` in the `c15t` module options | `disableAnimation` prop on `consent-banner.vue`, `consent-manager.vue` and the IAB banner and dialog, when you render them yourself |
|
|
61
61
|
| Vue | `disableAnimation` in the `c15tVue` options | The same component props |
|
|
62
62
|
| Astro | `disableAnimation` in the `c15t()` integration options | `disableAnimation` prop on `ConsentBanner`, `ConsentDialog`, `IABConsentBanner`, `IABConsentDialog` |
|
|
63
|
-
| Svelte, SvelteKit | `disableAnimation` on `
|
|
63
|
+
| Svelte, SvelteKit | `disableAnimation` on `ConsentProvider` (Svelte) or `ConsentRoot` (SvelteKit) | `disableAnimation` prop on `ConsentBanner`, `ConsentDialog`, `IABConsentBanner`, `IABConsentDialog` |
|
|
64
64
|
| HTML | `data-disable-animation` on the script tag, or `ui.disableAnimation` in `config` | `ui.banner.disableAnimation`, `ui.dialog.disableAnimation` |
|
|
65
65
|
| JavaScript | `ui.disableAnimation` in `init()` | `ui.banner.disableAnimation`, `ui.dialog.disableAnimation` |
|
|
66
66
|
|
|
@@ -82,7 +82,7 @@ presentation: {
|
|
|
82
82
|
**Svelte**
|
|
83
83
|
|
|
84
84
|
Render `CookieBanner` in place of `ConsentBanner`, inside
|
|
85
|
-
`
|
|
85
|
+
`ConsentProvider` and next to `ConsentDialog`.
|
|
86
86
|
|
|
87
87
|
```svelte title="src/lib/cookie-banner.svelte"
|
|
88
88
|
<script lang="ts">
|
|
@@ -245,7 +245,7 @@ export const slimBar = {
|
|
|
245
245
|
|
|
246
246
|
**Svelte**
|
|
247
247
|
|
|
248
|
-
Spread `slimBar` into the
|
|
248
|
+
Spread `slimBar` into the props you pass to `ConsentProvider`.
|
|
249
249
|
Svelte scopes component styles, so the classes live in a global
|
|
250
250
|
stylesheet.
|
|
251
251
|
|
|
@@ -255,7 +255,7 @@ import type { ConsentManagerOptions } from '@c15t/svelte';
|
|
|
255
255
|
import './slim-bar.css';
|
|
256
256
|
|
|
257
257
|
/**
|
|
258
|
-
* Spread into the options you pass to `
|
|
258
|
+
* Spread into the options you pass to `ConsentProvider`. The bar
|
|
259
259
|
* keeps the stock markup and actions; the slot classes put it on one row.
|
|
260
260
|
*/
|
|
261
261
|
export const slimBar = {
|
|
@@ -451,7 +451,7 @@ const run = (action: string) => {
|
|
|
451
451
|
|
|
452
452
|
`getHeadlessConsent()` returns the banner state and `performAction`.
|
|
453
453
|
Render `CookieBar` in place of `ConsentBanner`, inside
|
|
454
|
-
`
|
|
454
|
+
`ConsentProvider`, and keep `ConsentDialog`, which Preferences
|
|
455
455
|
opens.
|
|
456
456
|
|
|
457
457
|
```svelte title="src/lib/cookie-bar.svelte"
|