@c15t/react 3.0.0-alpha.10 → 3.0.0-alpha.11
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 +1 -0
- package/dist/aggregate-components.js +1 -1
- package/dist/chunk-warming.js +1 -1
- package/dist/components/consent-gate/atoms.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/root.js +1 -1
- package/dist/components/shared/surface-styles.js +1 -1
- package/dist/devtools.js +1 -1
- package/dist/iab-dialog-deferred.js +2 -0
- package/dist/iab.js +1 -1
- package/dist/utils/deferred-module.js +1 -1
- package/dist/version.js +1 -1
- package/dist-types/chunk-warming.d.ts +8 -11
- package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
- package/dist-types/components/shared/surface-styles.d.ts +26 -2
- package/dist-types/iab-dialog-deferred.d.ts +36 -0
- package/dist-types/iab.d.ts +2 -1
- package/dist-types/version.d.ts +1 -1
- package/docs/README.md +1 -0
- package/docs/concepts/choose-your-setup.md +5 -2
- package/docs/concepts/data-fetching.md +24 -10
- package/docs/concepts/modes.md +9 -6
- package/docs/frameworks/react/components/consent-banner.md +3 -3
- package/docs/frameworks/react/components/consent-dialog.md +3 -3
- package/docs/frameworks/react/components/consent-provider.md +12 -9
- package/docs/frameworks/react/components.md +3 -3
- package/docs/frameworks/react/content-security-policy.md +8 -2
- package/docs/frameworks/react/iab.md +19 -0
- package/docs/frameworks/react/quickstart.md +25 -79
- package/docs/frameworks/react/rendering.md +161 -139
- package/docs/frameworks/react/scripts.md +3 -3
- package/docs/frameworks/react/troubleshooting.md +17 -16
- package/docs/frameworks/react/upgrade-v3.md +5 -4
- package/docs/guides/banner-experiments.md +16 -0
- package/docs/integrations/overview.md +1 -0
- package/docs/integrations/vercel-speed-insights.md +306 -0
- package/package.json +7 -7
|
@@ -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
|
|
|
@@ -53,7 +53,9 @@ download fails.
|
|
|
53
53
|
The framework quickstarts include the build integration for supported
|
|
54
54
|
deployments. Server resolution uses the snapshot without an upstream manifest
|
|
55
55
|
request. Browser resolution includes the policy and resolver in the client
|
|
56
|
-
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
|
|
57
59
|
Astro sites and script-tag sites keep the runtime setup from their guides.
|
|
58
60
|
|
|
59
61
|
The snapshot is fixed at build time:
|
|
@@ -133,7 +135,11 @@ Saves replayed after going offline carry none.
|
|
|
133
135
|
|
|
134
136
|
Set it on the runtime or provider. In Next.js use `defineConsentConfig({ journey })`;
|
|
135
137
|
in TanStack Start pass the same value to `resolveConsent` and `ConsentRoot`; with
|
|
136
|
-
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
|
|
137
143
|
and the script tag use `'page'`. A manifest that resolves locally in the
|
|
138
144
|
browser reports no init, so it sends no journey.
|
|
139
145
|
|
|
@@ -161,6 +167,14 @@ A same-origin URL named `/api/c15t/init` can instead resolve from a cached
|
|
|
161
167
|
manifest in your application. The URL name alone does not tell you which path
|
|
162
168
|
runs.
|
|
163
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
|
+
|
|
164
178
|
## How do transports and proxies differ?
|
|
165
179
|
|
|
166
180
|
A transport implements initialization, saving and optional record operations.
|
package/docs/concepts/modes.md
CHANGED
|
@@ -15,15 +15,18 @@ and `offline()`. Consent choices go to the backend in `manifest()` and
|
|
|
15
15
|
`hosted()`, whether that backend is [Inth](https://inth.com) or a
|
|
16
16
|
[self-hosted c15t backend](https://v3.c15t.com/docs/self-host/quickstart).
|
|
17
17
|
|
|
18
|
-
| Mode | Where the policy resolves | Backend requests on a first visit
|
|
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. Choices post to `/subjects`. |
|
|
21
|
-
| `hosted()` | The backend's `GET /init` | One `/init` per page that resolves consent.
|
|
22
|
-
| `offline()` | The browser, from rules in your bundle | None. Choices stay in the browser.
|
|
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
23
|
|
|
24
24
|
`manifest()` is the default in Next.js, TanStack Start, Nuxt, Astro and
|
|
25
25
|
SvelteKit. React, Vue, Svelte and `@c15t/browser` have no default: pass a
|
|
26
|
-
mode yourself.
|
|
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
|
|
27
30
|
mode from the bundle file; see
|
|
28
31
|
[choose a mode](https://v3.c15t.com/docs/frameworks/html/attributes-and-api#choose-a-mode).
|
|
29
32
|
|
|
@@ -18,13 +18,13 @@ import {
|
|
|
18
18
|
ConsentDialog,
|
|
19
19
|
ConsentDialogLink,
|
|
20
20
|
ConsentProvider,
|
|
21
|
-
|
|
21
|
+
hosted,
|
|
22
22
|
} from 'c15t/react';
|
|
23
23
|
import type { ReactNode } from 'react';
|
|
24
24
|
|
|
25
25
|
const options = {
|
|
26
|
-
//
|
|
27
|
-
mode:
|
|
26
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
27
|
+
mode: hosted(),
|
|
28
28
|
scripts: [
|
|
29
29
|
posthog({
|
|
30
30
|
id: 'phc_your_project_key',
|
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
ConsentDialog,
|
|
21
21
|
ConsentDialogLink,
|
|
22
22
|
ConsentProvider,
|
|
23
|
-
|
|
23
|
+
hosted,
|
|
24
24
|
} from 'c15t/react';
|
|
25
25
|
import type { ReactNode } from 'react';
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
|
-
//
|
|
29
|
-
mode:
|
|
28
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
29
|
+
mode: hosted(),
|
|
30
30
|
scripts: [
|
|
31
31
|
posthog({
|
|
32
32
|
id: 'phc_your_project_key',
|
|
@@ -20,13 +20,13 @@ import {
|
|
|
20
20
|
ConsentDialog,
|
|
21
21
|
ConsentDialogLink,
|
|
22
22
|
ConsentProvider,
|
|
23
|
-
|
|
23
|
+
hosted,
|
|
24
24
|
} from 'c15t/react';
|
|
25
25
|
import type { ReactNode } from 'react';
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
|
-
//
|
|
29
|
-
mode:
|
|
28
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
29
|
+
mode: hosted(),
|
|
30
30
|
scripts: [
|
|
31
31
|
posthog({
|
|
32
32
|
id: 'phc_your_project_key',
|
|
@@ -48,11 +48,14 @@ export const Consent = ({ children }: { children: ReactNode }) => (
|
|
|
48
48
|
);
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
`
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
to the backend URL from your Inth project. To
|
|
55
|
-
|
|
51
|
+
`hosted()` from `c15t/react` asks the backend's `/init` for the visitor's
|
|
52
|
+
policy on each page load, and sends consent choices to the same backend. It
|
|
53
|
+
uses the backend URL `consentManifest()` read from `VITE_C15T_BACKEND_URL` or
|
|
54
|
+
`VITE_INTH_PROJECT_URL`. Set one to the backend URL from your Inth project. To
|
|
55
|
+
resolve a bundled policy in the browser instead, pass `manifest()` from
|
|
56
|
+
`c15t/react`; see
|
|
57
|
+
[rendering](../rendering.md#bundle-the-policy-at-build-time).
|
|
58
|
+
The Next.js and TanStack Start adapters export `ConsentRoot` instead, which wraps
|
|
56
59
|
this provider and passes it server-resolved state.
|
|
57
60
|
|
|
58
61
|
## Provider options
|
|
@@ -67,7 +70,7 @@ the provider to change them. `scripts`, `vendors`, `networkBlocker`,
|
|
|
67
70
|
|
|
68
71
|
| Option | Purpose |
|
|
69
72
|
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
70
|
-
| `mode` | Required. `
|
|
73
|
+
| `mode` | Required. `hosted()` for the backend's `/init`, `manifest()` for a bundled policy, `offline()` for local policies, all from `c15t/react`, or `custom()` for your own transport. See [consent modes](../../../concepts/modes.md) |
|
|
71
74
|
| `prefetch` | Server-resolved state, or a promise of it, from a framework adapter's server helper |
|
|
72
75
|
| `scripts` | Consent-gated vendor scripts. See [scripts and embeds](../scripts.md) |
|
|
73
76
|
| `vendors` | Vendors listed under their category with their own switch. See [vendor consent](../vendor-consent.md) |
|
|
@@ -42,13 +42,13 @@ import {
|
|
|
42
42
|
ConsentDialog,
|
|
43
43
|
ConsentDialogLink,
|
|
44
44
|
ConsentProvider,
|
|
45
|
-
|
|
45
|
+
hosted,
|
|
46
46
|
} from 'c15t/react';
|
|
47
47
|
import type { ReactNode } from 'react';
|
|
48
48
|
|
|
49
49
|
const options = {
|
|
50
|
-
//
|
|
51
|
-
mode:
|
|
50
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
51
|
+
mode: hosted(),
|
|
52
52
|
scripts: [
|
|
53
53
|
posthog({
|
|
54
54
|
id: 'phc_your_project_key',
|
|
@@ -16,6 +16,7 @@ A React app with c15t adds these to the page, and your policy must allow them:
|
|
|
16
16
|
| `c15t/react/styles.css`, only if you import it with `styles: false` | `style-src 'self'` |
|
|
17
17
|
| The `<style id="c15t-theme">` element, if you render `ConsentTheme` | `style-src` with a nonce or its hash |
|
|
18
18
|
| `<script>` elements the script loader creates for `scripts` entries, both `src` and inline | `script-src` with each vendor's host, or a nonce |
|
|
19
|
+
| The inline `<script>` that `consentManifest()` adds to `index.html` to send `/init` early | `script-src` with a nonce or its hash |
|
|
19
20
|
| With server rendering, the inline `<script>` before the banner's buttons that holds a tap made before hydration | `script-src` with a nonce or its hash |
|
|
20
21
|
| Browser requests to your backend's `/init` and `/subjects` | `connect-src` with the backend origin |
|
|
21
22
|
| Iframes inside `ConsentGate`, and the frames, images and requests your vendors load | `frame-src`, `img-src`, `connect-src` for each vendor |
|
|
@@ -70,8 +71,9 @@ entry takes precedence for that element. The stock components put it on the
|
|
|
70
71
|
With Vite, set `html.cspNonce` to a placeholder in `vite.config.ts`, and have
|
|
71
72
|
your server replace it with a new nonce on every response. Vite then adds
|
|
72
73
|
`<meta property="csp-nonce" nonce="...">` to the page, and the browser keeps the
|
|
73
|
-
value in the tag's `nonce` property.
|
|
74
|
-
the
|
|
74
|
+
value in the tag's `nonce` property. Vite also stamps the nonce on the early
|
|
75
|
+
`/init` script. Read it where you create the provider, in the
|
|
76
|
+
quickstart's `src/consent.tsx`:
|
|
75
77
|
|
|
76
78
|
```tsx title="src/consent.tsx (partial)"
|
|
77
79
|
const nonce =
|
|
@@ -88,6 +90,10 @@ The provider reads `options.nonce` once, when it mounts. A server-rendered
|
|
|
88
90
|
React app, such as one built with React Router framework mode, reads the nonce
|
|
89
91
|
from its own request and passes it the same way.
|
|
90
92
|
|
|
93
|
+
On a static host, allow the early `/init` script by the hash in the browser's
|
|
94
|
+
`Refused to execute inline script` error. If the policy blocks it, the app
|
|
95
|
+
sends `/init` itself.
|
|
96
|
+
|
|
91
97
|
## Allow c15t's style elements
|
|
92
98
|
|
|
93
99
|
The banner, dialog and other stock components render c15t's rules as
|
|
@@ -67,6 +67,25 @@ your error boundary or the framework's error overlay shows it. Render `IABProvid
|
|
|
67
67
|
`c15t/react/iab` for those visitors, or remove the `iab` model from the
|
|
68
68
|
policy.
|
|
69
69
|
|
|
70
|
+
## When the dialog loads
|
|
71
|
+
|
|
72
|
+
`IABConsentDialog` loads its code on demand, so the first page load
|
|
73
|
+
carries the banner without the preference center. The code downloads at
|
|
74
|
+
the first of:
|
|
75
|
+
|
|
76
|
+
* The browser's first idle period after the page's `load` event, while
|
|
77
|
+
the IAB banner is shown.
|
|
78
|
+
* Hover or focus on the banner's Customize button or partners link.
|
|
79
|
+
* The dialog opening.
|
|
80
|
+
|
|
81
|
+
A visitor who opens the dialog before the download finishes waits for
|
|
82
|
+
it. `open={true}` and `showTrigger` load it on mount, under a model the
|
|
83
|
+
dialog's `models` prop lists. Under another model, `showTrigger` loads
|
|
84
|
+
only the trigger. Set
|
|
85
|
+
`preloadDialog: 'intent'` in the consent provider options to skip the
|
|
86
|
+
idle download. Idle loading is also skipped with Save-Data on, on `2g`
|
|
87
|
+
and `slow-2g` connections, and while offline.
|
|
88
|
+
|
|
70
89
|
## Verify vendor and purpose choices
|
|
71
90
|
|
|
72
91
|
Test category choices alongside vendor, purpose, legitimate-interest and special
|
|
@@ -7,11 +7,10 @@ group: frameworks
|
|
|
7
7
|
|
|
8
8
|
## Before you start
|
|
9
9
|
|
|
10
|
-
This guide sets up a client-rendered React app built with Vite. The
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
the
|
|
14
|
-
request.
|
|
10
|
+
This guide sets up a client-rendered React app built with Vite. The browser
|
|
11
|
+
loads the page and asks your consent backend for the visitor's policy, then
|
|
12
|
+
shows the banner or runs the scripts the visitor allowed. The backend reads the
|
|
13
|
+
visitor's location from the request, so regional policies need no extra setup.
|
|
15
14
|
|
|
16
15
|
* **Next.js or TanStack Start?** Use that framework's guide from the
|
|
17
16
|
[framework list](https://v3.c15t.com/docs/frameworks). Their adapters resolve consent on the
|
|
@@ -28,8 +27,8 @@ the backend URL.
|
|
|
28
27
|
[Choose your setup](../../concepts/choose-your-setup.md#decide-who-runs-the-consent-backend)
|
|
29
28
|
covers self-hosting and offline mode.
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
The guide uses `hosted()` mode. Policy, translation and vendor edits in your
|
|
31
|
+
project reach visitors on their next page load, without a rebuild.
|
|
33
32
|
|
|
34
33
|
## Install c15t
|
|
35
34
|
|
|
@@ -43,7 +42,7 @@ Rebuild after changing policies, translations or vendors.
|
|
|
43
42
|
`c15t` contains the React adapter at `c15t/react` and the Vite plugin at
|
|
44
43
|
`c15t/build`. `@c15t/integrations` holds the vendor loaders used below.
|
|
45
44
|
|
|
46
|
-
##
|
|
45
|
+
## Add the Vite plugin
|
|
47
46
|
|
|
48
47
|
Add `consentManifest` to `vite.config.ts`:
|
|
49
48
|
|
|
@@ -66,60 +65,14 @@ VITE_C15T_BACKEND_URL=https://your-project.inth.app
|
|
|
66
65
|
If your app already sets `VITE_INTH_PROJECT_URL` for other Inth SDKs, that works
|
|
67
66
|
too. When both are set, `VITE_C15T_BACKEND_URL` wins.
|
|
68
67
|
|
|
69
|
-
`consentManifest`
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
from `c15t/generated`. No file is written into your project.
|
|
68
|
+
`consentManifest` hands the backend URL to `hosted()` through
|
|
69
|
+
`c15t/generated`. No file is written into your project. Without the plugin,
|
|
70
|
+
pass the URL as `hosted({ backendURL })`.
|
|
73
71
|
|
|
74
|
-
The
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* Consent choices still go to the backend.
|
|
79
|
-
|
|
80
|
-
The build reads the backend URL from your public backend URL variable when
|
|
81
|
-
the config doesn't pass one: `NEXT_PUBLIC_C15T_BACKEND_URL` in Next.js,
|
|
82
|
-
`NUXT_PUBLIC_C15T_BACKEND_URL` in Nuxt, `PUBLIC_C15T_BACKEND_URL` in Astro,
|
|
83
|
-
Svelte and SvelteKit, and `VITE_C15T_BACKEND_URL` in TanStack Start and other
|
|
84
|
-
Vite apps. Each also reads the matching Inth variable, such as
|
|
85
|
-
`NEXT_PUBLIC_INTH_PROJECT_URL`, when the c15t one is unset. See
|
|
86
|
-
[set the backend URL](../../concepts/modes.md#set-the-backend-url).
|
|
87
|
-
|
|
88
|
-
The fetch waits at most 10 seconds. When it fails, or no backend URL is set,
|
|
89
|
-
every framework does the same thing:
|
|
90
|
-
|
|
91
|
-
| Command | Default when the fetch fails |
|
|
92
|
-
| ------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
93
|
-
| Production build: `next build`, `vite build`, `nuxt build`, `astro build` | The build stops with an error. |
|
|
94
|
-
| Dev: `next dev`, `vite dev`, `nuxt dev`, `astro dev` | A warning, and the server fetches the policy at runtime. |
|
|
95
|
-
|
|
96
|
-
Set `onBuildError` to use one behaviour for both. `'fail'` stops dev too.
|
|
97
|
-
`'runtime'` lets a production build finish, and the server fetches the policy
|
|
98
|
-
at runtime. The `C15T_ON_BUILD_ERROR` environment variable overrides the
|
|
99
|
-
option, so you can deploy during a backend outage without a code change:
|
|
100
|
-
|
|
101
|
-
```sh
|
|
102
|
-
C15T_ON_BUILD_ERROR=runtime npm run build
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Turborepo's strict environment mode hides undeclared variables from tasks, so
|
|
106
|
-
list `C15T_ON_BUILD_ERROR` in the build task's `passThroughEnv` there.
|
|
107
|
-
|
|
108
|
-
The build skips the fetch, without an error, when it can't use a snapshot,
|
|
109
|
-
for example when the backend URL is relative. With `onBuildError: 'fail'`, a
|
|
110
|
-
relative URL stops the build. [Consent modes](../../concepts/modes.md#what-happens-when-the-download-fails)
|
|
111
|
-
lists every case.
|
|
112
|
-
|
|
113
|
-
`vite build` and `vite dev` fetch the manifest when they start. `vite preview`
|
|
114
|
-
serves the last build without fetching. The plugin writes no file into your
|
|
115
|
-
app, so there is nothing to keep out of Git. `c15t/generated` ships its own
|
|
116
|
-
types, so `tsc`, `vue-tsc` and `svelte-check` pass on a fresh checkout without
|
|
117
|
-
a build first.
|
|
118
|
-
|
|
119
|
-
The plugin can't see the options your app passes to `manifest()`. When the
|
|
120
|
-
app passes `source: 'runtime'` or `manifestURL`, set
|
|
121
|
-
`consentManifest({ source: 'runtime' })` too. The build then downloads no
|
|
122
|
-
manifest, so it doesn't fail when the backend's `/manifest` is down.
|
|
72
|
+
The plugin also adds a small script to `index.html` that sends `/init` while
|
|
73
|
+
your JavaScript downloads, so the banner shows sooner.
|
|
74
|
+
[Rendering](./rendering.md#send-init-before-the-app-loads)
|
|
75
|
+
covers when to turn it off.
|
|
123
76
|
|
|
124
77
|
## Mount the provider
|
|
125
78
|
|
|
@@ -135,13 +88,13 @@ import {
|
|
|
135
88
|
ConsentDialog,
|
|
136
89
|
ConsentDialogLink,
|
|
137
90
|
ConsentProvider,
|
|
138
|
-
|
|
91
|
+
hosted,
|
|
139
92
|
} from 'c15t/react';
|
|
140
93
|
import type { ReactNode } from 'react';
|
|
141
94
|
|
|
142
95
|
const options = {
|
|
143
|
-
//
|
|
144
|
-
mode:
|
|
96
|
+
// Asks VITE_C15T_BACKEND_URL for each visitor's policy.
|
|
97
|
+
mode: hosted(),
|
|
145
98
|
scripts: [
|
|
146
99
|
posthog({
|
|
147
100
|
id: 'phc_your_project_key',
|
|
@@ -163,18 +116,11 @@ export const Consent = ({ children }: { children: ReactNode }) => (
|
|
|
163
116
|
);
|
|
164
117
|
```
|
|
165
118
|
|
|
166
|
-
`
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
current policy, which can be newer than the snapshot. Vite reads
|
|
172
|
-
`VITE_C15T_BACKEND_URL` at build time, so set it before you build, not when
|
|
173
|
-
you serve the files.
|
|
174
|
-
|
|
175
|
-
To apply policy edits without rebuilding, use `hosted()` from `c15t/react` as
|
|
176
|
-
the mode. The browser then requests the policy from `/init` on every page load.
|
|
177
|
-
[Consent modes](../../concepts/modes.md) compares the three modes.
|
|
119
|
+
`hosted()` makes one `/init` request to your backend, started early by the
|
|
120
|
+
script in `index.html`. The backend picks the policy from the visitor's
|
|
121
|
+
location and language and returns its current version. Consent choices go to
|
|
122
|
+
the same backend. Vite reads `VITE_C15T_BACKEND_URL` at build time, so set it
|
|
123
|
+
before you build, not when you serve the files.
|
|
178
124
|
|
|
179
125
|
PostHog waits for measurement permission, so your policy must include that
|
|
180
126
|
category. Replace `phc_your_project_key` with your PostHog project key.
|
|
@@ -234,7 +180,8 @@ Build and preview the production bundle with `vite build` and `vite preview`,
|
|
|
234
180
|
then open the site in a private window with DevTools open on the Network tab.
|
|
235
181
|
Test under a policy that asks for a choice, such as an EU opt-in policy.
|
|
236
182
|
|
|
237
|
-
1. **Before a choice.**
|
|
183
|
+
1. **Before a choice.** One `/init` request goes to your backend URL, starting
|
|
184
|
+
before your JavaScript finishes downloading, and the banner shows. There
|
|
238
185
|
are no requests to `posthog.com`.
|
|
239
186
|
2. **Reject All.** The banner closes and the vendor requests stay absent.
|
|
240
187
|
3. **Reload.** The banner stays closed and the vendor requests stay absent.
|
|
@@ -243,8 +190,7 @@ Test under a policy that asks for a choice, such as an EU opt-in policy.
|
|
|
243
190
|
save. PostHog's `array.js` loads.
|
|
244
191
|
5. **Turn Analytics off again.** The page reloads and PostHog does not load.
|
|
245
192
|
|
|
246
|
-
If the banner never appears, check the
|
|
247
|
-
request to `/init` on your backend URL. [Troubleshooting](./troubleshooting.md)
|
|
193
|
+
If the banner never appears, check the `/init` request to your backend URL. [Troubleshooting](./troubleshooting.md)
|
|
248
194
|
covers the common causes. [Verify consent](../../guides/verify-consent.md) has the
|
|
249
195
|
full release checklist.
|
|
250
196
|
|