@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
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Google Tag
|
|
3
|
-
description: Load gtag.js for Google Analytics or Google Ads
|
|
4
|
-
Mode v2 signals, and verify the consent commands in
|
|
3
|
+
description: Load gtag.js for Google Analytics or Google Ads before or after
|
|
4
|
+
consent with c15t Consent Mode v2 signals, and verify the consent commands in
|
|
5
|
+
DevTools.
|
|
6
|
+
seoTitle: Google Tag Consent Mode v2 with c15t
|
|
7
|
+
seoDescription: Send Google Consent Mode v2 signals before gtag.js runs. c15t
|
|
8
|
+
maps consent to analytics_storage, ad_storage, ad_user_data and
|
|
9
|
+
ad_personalization.
|
|
5
10
|
icon: google-analytics
|
|
6
11
|
group: integrations
|
|
7
12
|
---
|
|
8
13
|
|
|
14
|
+
The c15t `gtag` helper loads Google's gtag.js for Google Analytics or Google
|
|
15
|
+
Ads. With the default `loadMode: 'always'`, gtag.js loads on every page, before
|
|
16
|
+
the visitor chooses. You must give a category, usually `measurement` or
|
|
17
|
+
`marketing`, but in this mode the category does not delay the load. With
|
|
18
|
+
`loadMode: 'after-consent'`, c15t sends nothing to Google until the category has
|
|
19
|
+
consent. In both modes, the helper sends the Google Consent Mode v2 default with
|
|
20
|
+
`gtag('consent', 'default', ...)` before `config`. Each consent change sends an
|
|
21
|
+
`update`. `measurement` controls `analytics_storage`, and `marketing` controls
|
|
22
|
+
`ad_storage`, `ad_user_data`, and `ad_personalization`. The `consentMapping`
|
|
23
|
+
option replaces this map.
|
|
24
|
+
|
|
9
25
|
## Configure the Google tag
|
|
10
26
|
|
|
11
27
|
Copy the tag ID, for example `G-XXXXXXXXXX` for Google Analytics or
|
|
12
28
|
`AW-XXXXXXXXX` for Google Ads. Remove any `gtag.js` snippet already in your
|
|
13
29
|
HTML and any tag-manager entry that loads the same tag.
|
|
14
30
|
|
|
15
|
-
| Package manager | Command
|
|
16
|
-
| :-------------- |
|
|
17
|
-
| npm | `npm install @c15t/integrations
|
|
18
|
-
| pnpm | `pnpm add @c15t/integrations
|
|
19
|
-
| yarn | `yarn add @c15t/integrations
|
|
20
|
-
| bun | `bun add @c15t/integrations
|
|
31
|
+
| Package manager | Command |
|
|
32
|
+
| :-------------- | :------------------------------- |
|
|
33
|
+
| npm | `npm install @c15t/integrations` |
|
|
34
|
+
| pnpm | `pnpm add @c15t/integrations` |
|
|
35
|
+
| yarn | `yarn add @c15t/integrations` |
|
|
36
|
+
| bun | `bun add @c15t/integrations` |
|
|
21
37
|
|
|
22
38
|
```ts title="src/consent-scripts.ts"
|
|
23
39
|
import { gtag } from '@c15t/integrations/google-tag';
|
|
@@ -32,51 +48,41 @@ endpoint, policy, styles and consent UI. Remove the vendor's original script,
|
|
|
32
48
|
SDK initializer or tag-manager entry, so the vendor loads only through c15t.
|
|
33
49
|
|
|
34
50
|
The vendor pages put the helper in `src/consent-scripts.ts`. If your framework
|
|
35
|
-
quickstart already
|
|
36
|
-
Next.js guide, add the helper to that array instead of creating a
|
|
51
|
+
quickstart already has a `scripts` array, such as the one in `c15t.config.ts`
|
|
52
|
+
in the Next.js guide, add the helper to that array instead of creating a
|
|
53
|
+
second file.
|
|
37
54
|
The `scripts` export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
|
|
38
55
|
point for your framework below. These are edits to that provider, not a second
|
|
39
56
|
provider.
|
|
40
57
|
|
|
41
58
|
**Next.js**
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import { ConsentRoot } from 'c15t/next';
|
|
47
|
-
import { scripts } from './consent-scripts';
|
|
48
|
-
```
|
|
60
|
+
Add the configuration to `scripts` in `c15t.config.ts`, next to
|
|
61
|
+
`next.config.ts`:
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
```ts title="c15t.config.ts"
|
|
64
|
+
import { defineConsentConfig } from 'c15t/next';
|
|
65
|
+
import { scripts } from './src/consent-scripts';
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
<ConsentRoot state={state} config={consentConfig} scripts={scripts}>
|
|
56
|
-
{children}
|
|
57
|
-
</ConsentRoot>
|
|
67
|
+
export default defineConsentConfig({ scripts });
|
|
58
68
|
```
|
|
59
69
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
Keep the rest of your config, such as `mode` and `routePrefix`, in the
|
|
71
|
+
same call. `ConsentRoot` reads the config in the browser, so the layout
|
|
72
|
+
keeps passing only `state`. App Router, Pages Router and static export all
|
|
73
|
+
read the same file. See
|
|
63
74
|
[Next.js scripts and embeds](https://c15t.com/docs/frameworks/next/scripts).
|
|
64
75
|
|
|
65
76
|
**TanStack Start**
|
|
66
77
|
|
|
67
78
|
Import the configuration into your root route and pass it to the existing
|
|
68
|
-
`ConsentRoot` as a top-level prop. Keep the loader
|
|
69
|
-
|
|
79
|
+
`ConsentRoot` as a top-level prop. Keep the loader from the
|
|
80
|
+
[TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart):
|
|
70
81
|
|
|
71
82
|
```tsx title="src/routes/__root.tsx"
|
|
72
83
|
import { scripts } from '../consent-scripts';
|
|
73
84
|
|
|
74
|
-
<ConsentRoot
|
|
75
|
-
state={consent}
|
|
76
|
-
backendURL={backendURL}
|
|
77
|
-
initRoute={false}
|
|
78
|
-
scripts={scripts}
|
|
79
|
-
>
|
|
85
|
+
<ConsentRoot state={consent} scripts={scripts}>
|
|
80
86
|
```
|
|
81
87
|
|
|
82
88
|
Import vendor helpers in the root route module, not in a server function.
|
|
@@ -95,8 +101,8 @@ import { scripts } from './consent-scripts';
|
|
|
95
101
|
<ConsentProvider options={{ mode, scripts }}>
|
|
96
102
|
```
|
|
97
103
|
|
|
98
|
-
`mode` is the `
|
|
99
|
-
|
|
104
|
+
`mode` is the `manifest()` value from the
|
|
105
|
+
[React quickstart](../frameworks/react/quickstart.md). Keep the banner,
|
|
100
106
|
dialog and preferences link inside the provider. See
|
|
101
107
|
[React scripts and embeds](../frameworks/react/scripts.md).
|
|
102
108
|
|
|
@@ -125,15 +131,16 @@ callbacks. Write the vendor IDs into `consent-scripts.ts`. See
|
|
|
125
131
|
Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
|
|
126
132
|
|
|
127
133
|
```ts title="src/main.ts"
|
|
134
|
+
import { c15tVue, manifest } from 'c15t/vue/vue-plugin';
|
|
128
135
|
import { scripts } from './consent-scripts';
|
|
129
136
|
|
|
130
137
|
app.use(c15tVue, {
|
|
131
|
-
|
|
138
|
+
mode: manifest(),
|
|
132
139
|
scripts,
|
|
133
140
|
});
|
|
134
141
|
```
|
|
135
142
|
|
|
136
|
-
Keep your existing
|
|
143
|
+
Keep your existing `mode` and other options. The plugin starts one
|
|
137
144
|
script loader when the app mounts, after it has applied the visitor's stored
|
|
138
145
|
choice. Do not also call `createScriptLoader` from a component. See
|
|
139
146
|
[Vue scripts and embeds](https://c15t.com/docs/frameworks/vue/scripts).
|
|
@@ -141,12 +148,11 @@ choice. Do not also call `createScriptLoader` from a component. See
|
|
|
141
148
|
**Astro**
|
|
142
149
|
|
|
143
150
|
Add the scripts to the client entrypoint from the
|
|
144
|
-
[Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart),
|
|
145
|
-
integration
|
|
146
|
-
|
|
147
|
-
already exports scripts, combine the two arrays.
|
|
151
|
+
[Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart), `src/c15t.client.ts`,
|
|
152
|
+
which the integration finds on its own. Keep `astro.config.mjs` as it is.
|
|
153
|
+
If the module already exports scripts, combine the two arrays.
|
|
148
154
|
|
|
149
|
-
```ts title="src/
|
|
155
|
+
```ts title="src/c15t.client.ts"
|
|
150
156
|
import type { C15tClientOptionsExtension } from 'c15t/astro';
|
|
151
157
|
import { scripts } from './consent-scripts';
|
|
152
158
|
|
|
@@ -166,15 +172,13 @@ pass them as a top-level prop:
|
|
|
166
172
|
|
|
167
173
|
```svelte title="src/App.svelte"
|
|
168
174
|
<script lang="ts">
|
|
169
|
-
import {
|
|
175
|
+
import { ConsentProvider, manifest } from '@c15t/svelte';
|
|
170
176
|
import { scripts } from './consent-scripts';
|
|
171
|
-
|
|
172
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
173
177
|
</script>
|
|
174
178
|
|
|
175
|
-
<
|
|
179
|
+
<ConsentProvider mode={manifest()} {scripts}>
|
|
176
180
|
<!-- Keep your application, consent UI and preferences link here. -->
|
|
177
|
-
</
|
|
181
|
+
</ConsentProvider>
|
|
178
182
|
```
|
|
179
183
|
|
|
180
184
|
Retain the styles and consent UI from the [Svelte quickstart](https://c15t.com/docs/frameworks/svelte/quickstart).
|
|
@@ -182,22 +186,21 @@ The provider owns the loader and disposes it on unmount.
|
|
|
182
186
|
|
|
183
187
|
**SvelteKit**
|
|
184
188
|
|
|
185
|
-
Add the scripts to the existing root layout
|
|
186
|
-
and
|
|
189
|
+
Add the scripts to the existing `ConsentRoot` in the root layout. Keep the
|
|
190
|
+
handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs/frameworks/sveltekit/quickstart).
|
|
187
191
|
|
|
188
192
|
```svelte title="src/routes/+layout.svelte"
|
|
189
193
|
<script lang="ts">
|
|
190
|
-
import {
|
|
194
|
+
import { ConsentRoot } from '@c15t/svelte';
|
|
191
195
|
import { scripts } from '../consent-scripts';
|
|
192
196
|
|
|
193
197
|
let { children, data } = $props();
|
|
194
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
195
198
|
</script>
|
|
196
199
|
|
|
197
|
-
<
|
|
200
|
+
<ConsentRoot state={data.consent} {scripts}>
|
|
198
201
|
{@render children()}
|
|
199
202
|
<!-- Keep your consent UI and preferences link here. -->
|
|
200
|
-
</
|
|
203
|
+
</ConsentRoot>
|
|
201
204
|
```
|
|
202
205
|
|
|
203
206
|
Import vendor helpers in the layout component, not in `+layout.server.ts`:
|
|
@@ -224,20 +227,19 @@ to a pasted snippet. See [HTML scripts](https://c15t.com/docs/frameworks/html/sc
|
|
|
224
227
|
|
|
225
228
|
**JavaScript**
|
|
226
229
|
|
|
227
|
-
Pass the scripts to `init()` from `@c15t/browser`, next to your
|
|
228
|
-
URL:
|
|
230
|
+
Pass the scripts to `init()` from `@c15t/browser`, next to your mode:
|
|
229
231
|
|
|
230
232
|
```ts
|
|
231
|
-
import { init } from '@c15t/browser';
|
|
233
|
+
import { init, manifest } from '@c15t/browser';
|
|
232
234
|
import { scripts } from './consent-scripts';
|
|
233
235
|
|
|
234
236
|
const consent = init({
|
|
235
|
-
|
|
237
|
+
mode: manifest(),
|
|
236
238
|
scripts,
|
|
237
239
|
});
|
|
238
240
|
```
|
|
239
241
|
|
|
240
|
-
Keep the
|
|
242
|
+
Keep the mode from your quickstart. With
|
|
241
243
|
`createConsentRuntime` from `c15t/runtime`, pass `scripts` to it instead.
|
|
242
244
|
A kernel you create yourself needs a loader from
|
|
243
245
|
`c15t/modules/script-loader`. Attach one loader per kernel. See
|
|
@@ -245,28 +247,69 @@ A kernel you create yourself needs a loader from
|
|
|
245
247
|
|
|
246
248
|
## Options
|
|
247
249
|
|
|
248
|
-
| Option | Default | Behavior
|
|
249
|
-
| ---------------- | --------------- |
|
|
250
|
-
| `id` | Required | Tag ID passed to `gtag('config', ...)` and the loader URL. The helper trims it. Empty or whitespace-only values
|
|
251
|
-
| `category` | Required | `measurement` for Analytics, `marketing` for Ads and Floodlight.
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
250
|
+
| Option | Default | Behavior |
|
|
251
|
+
| ---------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
252
|
+
| `id` | Required | Tag ID passed to `gtag('config', ...)` and the loader URL. The helper trims it. Empty or whitespace-only values log an error and the script does not load. |
|
|
253
|
+
| `category` | Required | `measurement` for Analytics, `marketing` for Ads and Floodlight. With `loadMode: 'after-consent'`, `gtag/js` waits for it. With `'always'`, it sets the script's permission, which callbacks receive, but does not delay loading. |
|
|
254
|
+
| `loadMode` | `'always'` | When `gtag/js` loads. See [choose when Google loads](#choose-when-google-loads). |
|
|
255
|
+
| `config` | None | Parameters passed as the third argument to `gtag('config', id, config)`. |
|
|
256
|
+
| `consentMapping` | The table below | Replaces the category-to-Google mapping. |
|
|
254
257
|
|
|
255
258
|
The deprecated `script` option overrides fields of the returned script. Use the
|
|
256
259
|
options above instead.
|
|
257
260
|
|
|
258
|
-
## Google loads
|
|
261
|
+
## Choose when Google loads
|
|
262
|
+
|
|
263
|
+
| `loadMode` | Until the category is allowed | After the category is allowed |
|
|
264
|
+
| ----------------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
265
|
+
| `'always'` | Loads `gtag/js` and sends `consent` `default` with the current permissions, then `config`. | Sends `consent` `update` with the mapped types granted. |
|
|
266
|
+
| `'after-consent'` | Sends nothing to Google. The helper creates no `dataLayer` or `gtag` function. | Loads `gtag/js` once. `consent` `default` carries the current permissions and comes before `config`. Later changes send `update`. |
|
|
259
267
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
Use `'after-consent'` when your policy forbids any request to Google before
|
|
269
|
+
the visitor opts in:
|
|
270
|
+
|
|
271
|
+
```ts title="src/consent-scripts.ts (partial)"
|
|
272
|
+
gtag({ id: 'G-XXXXXXXXXX', category: 'measurement', loadMode: 'after-consent' }),
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`'after-consent'` waits for the category to be allowed, not for a recorded
|
|
276
|
+
choice. Under an `opt-in` policy, that happens when the visitor allows it.
|
|
277
|
+
Under an `opt-out` or `none` policy, optional categories are allowed before a
|
|
278
|
+
choice, so `gtag/js` loads on the first page unless a saved refusal or a
|
|
279
|
+
privacy signal restricts the category; see
|
|
280
|
+
[policies](../concepts/policies.md). `necessary` is always allowed, so
|
|
281
|
+
`category: 'necessary'` loads `gtag/js` before a choice in either mode. Use
|
|
282
|
+
`measurement` or `marketing`.
|
|
283
|
+
|
|
284
|
+
This gives up part of Consent Mode. With `'always'`, Google tags send
|
|
285
|
+
cookieless pings while a type is denied, and Google uses them to model
|
|
286
|
+
conversions and behavior for visitors who refused or have not chosen. With
|
|
287
|
+
`'after-consent'`, visitors whose category is denied send nothing, so Google
|
|
288
|
+
has no data to model them from. Reports cover only visitors who allowed the
|
|
289
|
+
category.
|
|
290
|
+
|
|
291
|
+
When the visitor withdraws the category, c15t reloads the page and the new
|
|
292
|
+
page does not load `gtag/js`. With `reloadOnConsentRevoked: false`, the tag
|
|
293
|
+
already running stays on the page and gets an `update` that denies the
|
|
294
|
+
withdrawn types. A later grant reuses it instead of loading a second copy.
|
|
295
|
+
|
|
296
|
+
## Google loads before a choice by default
|
|
297
|
+
|
|
298
|
+
With the default `loadMode: 'always'`, the `googleTagManager` and `gtag`
|
|
299
|
+
helpers set `alwaysLoad: true`. Before the visitor chooses, the helper creates
|
|
300
|
+
the `dataLayer` queue, sends `gtag('consent', 'default', ...)` with the current
|
|
301
|
+
permissions and loads Google's script. After each permission change it sends
|
|
264
302
|
`gtag('consent', 'update', ...)`. Google's tags then adjust what they store and
|
|
265
303
|
send; see Google's
|
|
266
304
|
[Consent Mode overview](https://developers.google.com/tag-platform/security/concepts/consent-mode).
|
|
267
305
|
|
|
268
|
-
So the browser
|
|
269
|
-
Google request until the visitor allows it,
|
|
306
|
+
So the browser contacts Google before consent. If your policy requires no
|
|
307
|
+
Google request until the visitor allows it, set `loadMode: 'after-consent'`.
|
|
308
|
+
The helper then creates nothing and requests nothing until its category is
|
|
309
|
+
allowed. When it loads, it sends the `default` command first, with the
|
|
310
|
+
permissions at that moment, and `update` commands after later changes. Under
|
|
311
|
+
an `opt-out` or `none` policy, optional categories are allowed before a
|
|
312
|
+
choice, so the helper loads on the first page.
|
|
270
313
|
|
|
271
314
|
## How categories map to Google consent types
|
|
272
315
|
|
|
@@ -288,11 +331,12 @@ visitor has chosen anything. That is a permission, not a recorded choice.
|
|
|
288
331
|
|
|
289
332
|
## Verify the Google tag
|
|
290
333
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
instead and it loads only after consent; see
|
|
334
|
+
On a plain HTML page with the script tag, you gate Google's snippet instead
|
|
335
|
+
and it loads only after consent; see
|
|
294
336
|
[HTML scripts](https://c15t.com/docs/frameworks/html/scripts#google-consent-mode-and-tag-managers).
|
|
295
337
|
|
|
338
|
+
With the default `loadMode: 'always'`:
|
|
339
|
+
|
|
296
340
|
1. In a private window with an opt-in policy, load the page. `gtag/js` loads.
|
|
297
341
|
In Google Tag Assistant, the `consent` `default` command comes before
|
|
298
342
|
`config`, with `analytics_storage` and `ad_storage` set to `denied`.
|
|
@@ -300,9 +344,21 @@ instead and it loads only after consent; see
|
|
|
300
344
|
`update` command that grants the mapped types.
|
|
301
345
|
3. Turn the category off again and save. c15t reloads the page, and the new
|
|
302
346
|
page starts with those types denied.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
347
|
+
|
|
348
|
+
With `loadMode: 'after-consent'`:
|
|
349
|
+
|
|
350
|
+
1. In a private window with an opt-in policy, filter DevTools Network by
|
|
351
|
+
`google` and load the page. No request appears, and `window.dataLayer` is
|
|
352
|
+
`undefined` in the Console.
|
|
353
|
+
2. Allow the tag's category. `gtag/js` loads once. In Tag Assistant, the first
|
|
354
|
+
command is `consent` `default` with the mapped types granted, before
|
|
355
|
+
`config`.
|
|
356
|
+
3. Turn the category off again and save. c15t reloads the page, and the new
|
|
357
|
+
page makes no request to Google.
|
|
358
|
+
|
|
359
|
+
In either mode, with client-side navigation, check that each route change
|
|
360
|
+
sends one page view. A separate router integration that also sends
|
|
361
|
+
`page_view` doubles the count.
|
|
306
362
|
|
|
307
363
|
See the [consent verification guide](../guides/verify-consent.md) for hosting
|
|
308
364
|
checks.
|
|
@@ -2,22 +2,32 @@
|
|
|
2
2
|
title: Heap
|
|
3
3
|
description: Load the Heap config script and heap.js only after measurement
|
|
4
4
|
consent with the c15t heap helper, and check it in DevTools.
|
|
5
|
+
seoTitle: Heap cookie consent with c15t
|
|
6
|
+
seoDescription: Load Heap only with measurement consent. The c15t heap helper
|
|
7
|
+
keeps heap_config.js off the page and stops Heap when a visitor withdraws
|
|
8
|
+
consent.
|
|
5
9
|
icon: heap
|
|
6
10
|
group: integrations
|
|
7
11
|
---
|
|
8
12
|
|
|
13
|
+
The c15t `heap` helper keeps Heap off the page until `measurement` has consent.
|
|
14
|
+
Until then, c15t does not define `window.heap` or load `heap_config.js`, which
|
|
15
|
+
loads the heap.js runtime. The helper never calls `heap.stopTracking`. If the
|
|
16
|
+
visitor withdraws consent, c15t removes the config script element. By default,
|
|
17
|
+
c15t also reloads the page. The reload stops heap.js.
|
|
18
|
+
|
|
9
19
|
## Configure Heap
|
|
10
20
|
|
|
11
21
|
Copy the environment ID from your Heap installation snippet. The `heap` helper
|
|
12
22
|
loads that environment's `heap_config.js`, which then loads the heap.js
|
|
13
23
|
runtime. Remove the original Heap snippet.
|
|
14
24
|
|
|
15
|
-
| Package manager | Command
|
|
16
|
-
| :-------------- |
|
|
17
|
-
| npm | `npm install @c15t/integrations
|
|
18
|
-
| pnpm | `pnpm add @c15t/integrations
|
|
19
|
-
| yarn | `yarn add @c15t/integrations
|
|
20
|
-
| bun | `bun add @c15t/integrations
|
|
25
|
+
| Package manager | Command |
|
|
26
|
+
| :-------------- | :------------------------------- |
|
|
27
|
+
| npm | `npm install @c15t/integrations` |
|
|
28
|
+
| pnpm | `pnpm add @c15t/integrations` |
|
|
29
|
+
| yarn | `yarn add @c15t/integrations` |
|
|
30
|
+
| bun | `bun add @c15t/integrations` |
|
|
21
31
|
|
|
22
32
|
```ts title="src/consent-scripts.ts"
|
|
23
33
|
import { heap } from '@c15t/integrations/heap';
|
|
@@ -32,51 +42,41 @@ endpoint, policy, styles and consent UI. Remove the vendor's original script,
|
|
|
32
42
|
SDK initializer or tag-manager entry, so the vendor loads only through c15t.
|
|
33
43
|
|
|
34
44
|
The vendor pages put the helper in `src/consent-scripts.ts`. If your framework
|
|
35
|
-
quickstart already
|
|
36
|
-
Next.js guide, add the helper to that array instead of creating a
|
|
45
|
+
quickstart already has a `scripts` array, such as the one in `c15t.config.ts`
|
|
46
|
+
in the Next.js guide, add the helper to that array instead of creating a
|
|
47
|
+
second file.
|
|
37
48
|
The `scripts` export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
|
|
38
49
|
point for your framework below. These are edits to that provider, not a second
|
|
39
50
|
provider.
|
|
40
51
|
|
|
41
52
|
**Next.js**
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import { ConsentRoot } from 'c15t/next';
|
|
47
|
-
import { scripts } from './consent-scripts';
|
|
48
|
-
```
|
|
54
|
+
Add the configuration to `scripts` in `c15t.config.ts`, next to
|
|
55
|
+
`next.config.ts`:
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
```ts title="c15t.config.ts"
|
|
58
|
+
import { defineConsentConfig } from 'c15t/next';
|
|
59
|
+
import { scripts } from './src/consent-scripts';
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
<ConsentRoot state={state} config={consentConfig} scripts={scripts}>
|
|
56
|
-
{children}
|
|
57
|
-
</ConsentRoot>
|
|
61
|
+
export default defineConsentConfig({ scripts });
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
Keep the rest of your config, such as `mode` and `routePrefix`, in the
|
|
65
|
+
same call. `ConsentRoot` reads the config in the browser, so the layout
|
|
66
|
+
keeps passing only `state`. App Router, Pages Router and static export all
|
|
67
|
+
read the same file. See
|
|
63
68
|
[Next.js scripts and embeds](https://c15t.com/docs/frameworks/next/scripts).
|
|
64
69
|
|
|
65
70
|
**TanStack Start**
|
|
66
71
|
|
|
67
72
|
Import the configuration into your root route and pass it to the existing
|
|
68
|
-
`ConsentRoot` as a top-level prop. Keep the loader
|
|
69
|
-
|
|
73
|
+
`ConsentRoot` as a top-level prop. Keep the loader from the
|
|
74
|
+
[TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart):
|
|
70
75
|
|
|
71
76
|
```tsx title="src/routes/__root.tsx"
|
|
72
77
|
import { scripts } from '../consent-scripts';
|
|
73
78
|
|
|
74
|
-
<ConsentRoot
|
|
75
|
-
state={consent}
|
|
76
|
-
backendURL={backendURL}
|
|
77
|
-
initRoute={false}
|
|
78
|
-
scripts={scripts}
|
|
79
|
-
>
|
|
79
|
+
<ConsentRoot state={consent} scripts={scripts}>
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
Import vendor helpers in the root route module, not in a server function.
|
|
@@ -95,8 +95,8 @@ import { scripts } from './consent-scripts';
|
|
|
95
95
|
<ConsentProvider options={{ mode, scripts }}>
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
`mode` is the `
|
|
99
|
-
|
|
98
|
+
`mode` is the `manifest()` value from the
|
|
99
|
+
[React quickstart](../frameworks/react/quickstart.md). Keep the banner,
|
|
100
100
|
dialog and preferences link inside the provider. See
|
|
101
101
|
[React scripts and embeds](../frameworks/react/scripts.md).
|
|
102
102
|
|
|
@@ -125,15 +125,16 @@ callbacks. Write the vendor IDs into `consent-scripts.ts`. See
|
|
|
125
125
|
Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
|
|
126
126
|
|
|
127
127
|
```ts title="src/main.ts"
|
|
128
|
+
import { c15tVue, manifest } from 'c15t/vue/vue-plugin';
|
|
128
129
|
import { scripts } from './consent-scripts';
|
|
129
130
|
|
|
130
131
|
app.use(c15tVue, {
|
|
131
|
-
|
|
132
|
+
mode: manifest(),
|
|
132
133
|
scripts,
|
|
133
134
|
});
|
|
134
135
|
```
|
|
135
136
|
|
|
136
|
-
Keep your existing
|
|
137
|
+
Keep your existing `mode` and other options. The plugin starts one
|
|
137
138
|
script loader when the app mounts, after it has applied the visitor's stored
|
|
138
139
|
choice. Do not also call `createScriptLoader` from a component. See
|
|
139
140
|
[Vue scripts and embeds](https://c15t.com/docs/frameworks/vue/scripts).
|
|
@@ -141,12 +142,11 @@ choice. Do not also call `createScriptLoader` from a component. See
|
|
|
141
142
|
**Astro**
|
|
142
143
|
|
|
143
144
|
Add the scripts to the client entrypoint from the
|
|
144
|
-
[Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart),
|
|
145
|
-
integration
|
|
146
|
-
|
|
147
|
-
already exports scripts, combine the two arrays.
|
|
145
|
+
[Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart), `src/c15t.client.ts`,
|
|
146
|
+
which the integration finds on its own. Keep `astro.config.mjs` as it is.
|
|
147
|
+
If the module already exports scripts, combine the two arrays.
|
|
148
148
|
|
|
149
|
-
```ts title="src/
|
|
149
|
+
```ts title="src/c15t.client.ts"
|
|
150
150
|
import type { C15tClientOptionsExtension } from 'c15t/astro';
|
|
151
151
|
import { scripts } from './consent-scripts';
|
|
152
152
|
|
|
@@ -166,15 +166,13 @@ pass them as a top-level prop:
|
|
|
166
166
|
|
|
167
167
|
```svelte title="src/App.svelte"
|
|
168
168
|
<script lang="ts">
|
|
169
|
-
import {
|
|
169
|
+
import { ConsentProvider, manifest } from '@c15t/svelte';
|
|
170
170
|
import { scripts } from './consent-scripts';
|
|
171
|
-
|
|
172
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
173
171
|
</script>
|
|
174
172
|
|
|
175
|
-
<
|
|
173
|
+
<ConsentProvider mode={manifest()} {scripts}>
|
|
176
174
|
<!-- Keep your application, consent UI and preferences link here. -->
|
|
177
|
-
</
|
|
175
|
+
</ConsentProvider>
|
|
178
176
|
```
|
|
179
177
|
|
|
180
178
|
Retain the styles and consent UI from the [Svelte quickstart](https://c15t.com/docs/frameworks/svelte/quickstart).
|
|
@@ -182,22 +180,21 @@ The provider owns the loader and disposes it on unmount.
|
|
|
182
180
|
|
|
183
181
|
**SvelteKit**
|
|
184
182
|
|
|
185
|
-
Add the scripts to the existing root layout
|
|
186
|
-
and
|
|
183
|
+
Add the scripts to the existing `ConsentRoot` in the root layout. Keep the
|
|
184
|
+
handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs/frameworks/sveltekit/quickstart).
|
|
187
185
|
|
|
188
186
|
```svelte title="src/routes/+layout.svelte"
|
|
189
187
|
<script lang="ts">
|
|
190
|
-
import {
|
|
188
|
+
import { ConsentRoot } from '@c15t/svelte';
|
|
191
189
|
import { scripts } from '../consent-scripts';
|
|
192
190
|
|
|
193
191
|
let { children, data } = $props();
|
|
194
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
195
192
|
</script>
|
|
196
193
|
|
|
197
|
-
<
|
|
194
|
+
<ConsentRoot state={data.consent} {scripts}>
|
|
198
195
|
{@render children()}
|
|
199
196
|
<!-- Keep your consent UI and preferences link here. -->
|
|
200
|
-
</
|
|
197
|
+
</ConsentRoot>
|
|
201
198
|
```
|
|
202
199
|
|
|
203
200
|
Import vendor helpers in the layout component, not in `+layout.server.ts`:
|
|
@@ -224,20 +221,19 @@ to a pasted snippet. See [HTML scripts](https://c15t.com/docs/frameworks/html/sc
|
|
|
224
221
|
|
|
225
222
|
**JavaScript**
|
|
226
223
|
|
|
227
|
-
Pass the scripts to `init()` from `@c15t/browser`, next to your
|
|
228
|
-
URL:
|
|
224
|
+
Pass the scripts to `init()` from `@c15t/browser`, next to your mode:
|
|
229
225
|
|
|
230
226
|
```ts
|
|
231
|
-
import { init } from '@c15t/browser';
|
|
227
|
+
import { init, manifest } from '@c15t/browser';
|
|
232
228
|
import { scripts } from './consent-scripts';
|
|
233
229
|
|
|
234
230
|
const consent = init({
|
|
235
|
-
|
|
231
|
+
mode: manifest(),
|
|
236
232
|
scripts,
|
|
237
233
|
});
|
|
238
234
|
```
|
|
239
235
|
|
|
240
|
-
Keep the
|
|
236
|
+
Keep the mode from your quickstart. With
|
|
241
237
|
`createConsentRuntime` from `c15t/runtime`, pass `scripts` to it instead.
|
|
242
238
|
A kernel you create yourself needs a loader from
|
|
243
239
|
`c15t/modules/script-loader`. Attach one loader per kernel. See
|
|
@@ -247,7 +243,7 @@ A kernel you create yourself needs a loader from
|
|
|
247
243
|
|
|
248
244
|
| Option | Default | Behavior |
|
|
249
245
|
| -------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
250
|
-
| `envId` | Required | Environment ID. Set as `heap.envId` and `heap.appid`, and used in the default loader URL. The helper trims it. Empty values
|
|
246
|
+
| `envId` | Required | Environment ID. Set as `heap.envId` and `heap.appid`, and used in the default loader URL. The helper trims it. Empty values log an error and the script does not load. |
|
|
251
247
|
| `clientConfig` | `{}` | Client configuration set on `heap.clientConfig`. Values must be JSON-serializable with finite numbers; other values throw a `TypeError`. The helper always sets `shouldFetchServerConfig: false` and overrides any value you pass for it. |
|
|
252
248
|
| `scriptUrl` | `https://cdn.us.heap-api.com/config/<envId>/heap_config.js` | Config loader URL override. A blank value falls back to the default. |
|
|
253
249
|
|
|
@@ -293,8 +289,8 @@ permission before each of your own event calls. The reload does not delete
|
|
|
293
289
|
cookies the vendor already set; see
|
|
294
290
|
[clear on revocation for your framework](./overview.md#vendor-switches-and-cookie-cleanup).
|
|
295
291
|
|
|
296
|
-
The helper
|
|
297
|
-
|
|
292
|
+
The helper lists its vendor by name in the preference dialog, so a visitor can
|
|
293
|
+
turn it off inside an allowed category. See
|
|
298
294
|
[vendor consent for your framework](./overview.md#vendor-switches-and-cookie-cleanup). The
|
|
299
295
|
[consent verification guide](../guides/verify-consent.md) covers navigation,
|
|
300
296
|
expiry and hosting checks.
|