@c15t/scripts 3.0.0-alpha.2 → 3.0.0-alpha.3
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 +129 -63
- package/README.md +8 -29
- package/SKILL.md +33 -0
- package/dist/adobe-analytics.js +2 -0
- package/dist/ahrefs-analytics.js +2 -0
- package/dist/amplitude.js +2 -0
- package/dist/clearbit.js +2 -0
- package/dist/cloudflare-web-analytics.js +2 -0
- package/dist/cloudflare-zaraz.js +2 -0
- package/dist/crisp.js +2 -0
- package/dist/databuddy.js +2 -0
- package/dist/e2e-test-utils.js +2 -139
- package/dist/engine/compile.js +2 -89
- package/dist/engine/runtime.js +2 -448
- package/dist/events.js +2 -218
- package/dist/fathom-analytics.js +2 -0
- package/dist/front-chat.js +2 -0
- package/dist/google-tag-manager.js +2 -0
- package/dist/google-tag.js +2 -0
- package/dist/heap.js +2 -0
- package/dist/hightouch.js +2 -0
- package/dist/hotjar.js +2 -0
- package/dist/intercom.js +2 -0
- package/dist/klaviyo.js +2 -0
- package/dist/linkedin-insights.js +2 -0
- package/dist/logrocket.js +2 -0
- package/dist/matomo-analytics.js +2 -0
- package/dist/meta-pixel.js +2 -0
- package/dist/microsoft-clarity.js +2 -0
- package/dist/microsoft-uet.js +2 -0
- package/dist/mixpanel-analytics.js +2 -0
- package/dist/one-dollar-stats.js +2 -0
- package/dist/openai-pixel.js +2 -0
- package/dist/pinterest-tag.js +2 -0
- package/dist/pirsch.js +2 -0
- package/dist/plausible-analytics.js +2 -0
- package/dist/posthog.js +2 -0
- package/dist/promptwatch.js +2 -0
- package/dist/reddit-pixel.js +2 -0
- package/dist/registry.js +2 -422
- package/dist/resolve.js +2 -33
- package/dist/rudderstack.js +2 -0
- package/dist/rybbit-analytics.js +2 -0
- package/dist/segment.js +2 -0
- package/dist/snapchat-pixel.js +2 -0
- package/dist/tiktok-pixel.js +2 -0
- package/dist/types.js +2 -16
- package/dist/umami-analytics.js +2 -0
- package/dist/vendors/_shared/attributes.js +2 -14
- package/dist/vendors/_shared/google-consent.js +2 -27
- package/dist/vendors/_shared/install-builders.js +2 -21
- package/dist/vendors/_shared/required-id.js +2 -0
- package/dist/vendors/_shared/script-url.js +2 -28
- package/dist/vendors/ads-and-pixels/linkedin-insights.js +2 -48
- package/dist/vendors/ads-and-pixels/meta-pixel.js +2 -153
- package/dist/vendors/ads-and-pixels/microsoft-uet.js +2 -110
- package/dist/vendors/ads-and-pixels/openai-pixel.js +2 -88
- package/dist/vendors/ads-and-pixels/pinterest-tag.js +2 -123
- package/dist/vendors/ads-and-pixels/reddit-pixel.js +2 -107
- package/dist/vendors/ads-and-pixels/snapchat-pixel.js +2 -87
- package/dist/vendors/ads-and-pixels/tiktok-pixel.js +2 -89
- package/dist/vendors/ads-and-pixels/x-pixel.js +2 -48
- package/dist/vendors/analytics/adobe-analytics.js +2 -49
- package/dist/vendors/analytics/ahrefs-analytics.js +2 -27
- package/dist/vendors/analytics/amplitude.js +2 -134
- package/dist/vendors/analytics/clearbit.js +2 -28
- package/dist/vendors/analytics/cloudflare-web-analytics.js +2 -32
- package/dist/vendors/analytics/databuddy.js +2 -103
- package/dist/vendors/analytics/fathom-analytics.js +2 -35
- package/dist/vendors/analytics/google-tag.js +2 -78
- package/dist/vendors/analytics/heap.js +2 -134
- package/dist/vendors/analytics/hightouch.js +2 -109
- package/dist/vendors/analytics/hotjar.js +2 -44
- package/dist/vendors/analytics/logrocket.js +2 -58
- package/dist/vendors/analytics/matomo-analytics.js +2 -191
- package/dist/vendors/analytics/microsoft-clarity.js +2 -100
- package/dist/vendors/analytics/mixpanel-analytics.js +2 -93
- package/dist/vendors/analytics/one-dollar-stats.js +2 -30
- package/dist/vendors/analytics/pirsch.js +2 -67
- package/dist/vendors/analytics/plausible-analytics.js +2 -81
- package/dist/vendors/analytics/posthog.js +2 -200
- package/dist/vendors/analytics/promptwatch.js +2 -29
- package/dist/vendors/analytics/rudderstack.js +2 -183
- package/dist/vendors/analytics/rybbit-analytics.js +2 -63
- package/dist/vendors/analytics/segment.js +2 -65
- package/dist/vendors/analytics/umami-analytics.js +2 -39
- package/dist/vendors/analytics/vercel-analytics.js +2 -53
- package/dist/vendors/email-and-sms/klaviyo.js +2 -0
- package/dist/vendors/functional/crisp.js +2 -100
- package/dist/vendors/functional/front-chat.js +2 -64
- package/dist/vendors/functional/intercom.js +2 -45
- package/dist/vendors/tag-managers/cloudflare-zaraz.js +2 -98
- package/dist/vendors/tag-managers/google-tag-manager.js +2 -73
- package/dist/vercel-analytics.js +2 -0
- package/dist/x-pixel.js +2 -0
- package/dist-types/adobe-analytics.d.ts +2 -0
- package/dist-types/ahrefs-analytics.d.ts +2 -0
- package/dist-types/amplitude.d.ts +2 -0
- package/dist-types/clearbit.d.ts +2 -0
- package/dist-types/cloudflare-web-analytics.d.ts +2 -0
- package/dist-types/cloudflare-zaraz.d.ts +2 -0
- package/dist-types/crisp.d.ts +2 -0
- package/dist-types/databuddy.d.ts +2 -0
- package/dist-types/e2e-test-utils.d.ts +2 -0
- package/dist-types/engine/compile.d.ts +2 -3
- package/dist-types/engine/runtime.d.ts +2 -3
- package/dist-types/events.d.ts +2 -46
- package/dist-types/fathom-analytics.d.ts +2 -0
- package/dist-types/front-chat.d.ts +2 -0
- package/dist-types/google-tag-manager.d.ts +2 -0
- package/dist-types/google-tag.d.ts +2 -0
- package/dist-types/heap.d.ts +2 -0
- package/dist-types/hightouch.d.ts +2 -0
- package/dist-types/hotjar.d.ts +2 -0
- package/dist-types/intercom.d.ts +2 -0
- package/dist-types/klaviyo.d.ts +2 -0
- package/dist-types/linkedin-insights.d.ts +2 -0
- package/dist-types/logrocket.d.ts +2 -0
- package/dist-types/matomo-analytics.d.ts +2 -0
- package/dist-types/meta-pixel.d.ts +2 -0
- package/dist-types/microsoft-clarity.d.ts +2 -0
- package/dist-types/microsoft-uet.d.ts +2 -0
- package/dist-types/mixpanel-analytics.d.ts +2 -0
- package/dist-types/one-dollar-stats.d.ts +2 -0
- package/dist-types/openai-pixel.d.ts +2 -0
- package/dist-types/pinterest-tag.d.ts +2 -0
- package/dist-types/pirsch.d.ts +2 -0
- package/dist-types/plausible-analytics.d.ts +2 -0
- package/dist-types/posthog.d.ts +2 -0
- package/dist-types/promptwatch.d.ts +2 -0
- package/dist-types/reddit-pixel.d.ts +2 -0
- package/dist-types/registry.d.ts +2 -485
- package/dist-types/resolve.d.ts +2 -9
- package/dist-types/rudderstack.d.ts +2 -0
- package/dist-types/rybbit-analytics.d.ts +2 -0
- package/dist-types/segment.d.ts +2 -0
- package/dist-types/snapchat-pixel.d.ts +2 -0
- package/dist-types/tiktok-pixel.d.ts +2 -0
- package/dist-types/types.d.ts +2 -314
- package/dist-types/umami-analytics.d.ts +2 -0
- package/dist-types/vendors/_shared/attributes.d.ts +2 -35
- package/dist-types/vendors/_shared/google-consent.d.ts +2 -47
- package/dist-types/vendors/_shared/install-builders.d.ts +2 -30
- package/dist-types/vendors/_shared/required-id.d.ts +2 -0
- package/dist-types/vendors/_shared/script-url.d.ts +2 -75
- package/dist-types/vendors/ads-and-pixels/linkedin-insights.d.ts +2 -92
- package/dist-types/vendors/ads-and-pixels/meta-pixel.d.ts +2 -289
- package/dist-types/vendors/ads-and-pixels/microsoft-uet.d.ts +2 -105
- package/dist-types/vendors/ads-and-pixels/openai-pixel.d.ts +2 -211
- package/dist-types/vendors/ads-and-pixels/pinterest-tag.d.ts +2 -295
- package/dist-types/vendors/ads-and-pixels/reddit-pixel.d.ts +2 -210
- package/dist-types/vendors/ads-and-pixels/snapchat-pixel.d.ts +2 -171
- package/dist-types/vendors/ads-and-pixels/tiktok-pixel.d.ts +2 -106
- package/dist-types/vendors/ads-and-pixels/x-pixel.d.ts +2 -183
- package/dist-types/vendors/analytics/adobe-analytics.d.ts +2 -75
- package/dist-types/vendors/analytics/ahrefs-analytics.d.ts +2 -62
- package/dist-types/vendors/analytics/amplitude.d.ts +2 -234
- package/dist-types/vendors/analytics/clearbit.d.ts +2 -60
- package/dist-types/vendors/analytics/cloudflare-web-analytics.d.ts +2 -67
- package/dist-types/vendors/analytics/databuddy.d.ts +2 -147
- package/dist-types/vendors/analytics/fathom-analytics.d.ts +2 -90
- package/dist-types/vendors/analytics/google-tag.d.ts +2 -95
- package/dist-types/vendors/analytics/heap.d.ts +2 -316
- package/dist-types/vendors/analytics/hightouch.d.ts +2 -285
- package/dist-types/vendors/analytics/hotjar.d.ts +2 -73
- package/dist-types/vendors/analytics/logrocket.d.ts +2 -101
- package/dist-types/vendors/analytics/matomo-analytics.d.ts +2 -41
- package/dist-types/vendors/analytics/microsoft-clarity.d.ts +2 -97
- package/dist-types/vendors/analytics/mixpanel-analytics.d.ts +2 -113
- package/dist-types/vendors/analytics/one-dollar-stats.d.ts +2 -39
- package/dist-types/vendors/analytics/pirsch.d.ts +2 -96
- package/dist-types/vendors/analytics/plausible-analytics.d.ts +2 -122
- package/dist-types/vendors/analytics/posthog.d.ts +2 -175
- package/dist-types/vendors/analytics/promptwatch.d.ts +2 -36
- package/dist-types/vendors/analytics/rudderstack.d.ts +2 -330
- package/dist-types/vendors/analytics/rybbit-analytics.d.ts +2 -82
- package/dist-types/vendors/analytics/segment.d.ts +2 -164
- package/dist-types/vendors/analytics/umami-analytics.d.ts +2 -93
- package/dist-types/vendors/analytics/vercel-analytics.d.ts +2 -66
- package/dist-types/vendors/email-and-sms/klaviyo.d.ts +2 -0
- package/dist-types/vendors/functional/crisp.d.ts +2 -78
- package/dist-types/vendors/functional/front-chat.d.ts +2 -62
- package/dist-types/vendors/functional/intercom.d.ts +2 -135
- package/dist-types/vendors/tag-managers/cloudflare-zaraz.d.ts +2 -39
- package/dist-types/vendors/tag-managers/google-tag-manager.d.ts +2 -96
- package/dist-types/vercel-analytics.d.ts +2 -0
- package/dist-types/x-pixel.d.ts +2 -0
- package/docs/README.md +129 -63
- package/docs/assets/v3/bottom-bar.png +0 -0
- package/docs/assets/v3/brand-card.png +0 -0
- package/docs/assets/v3/brand-preferences.png +0 -0
- package/docs/assets/v3/choice-wall.png +0 -0
- package/docs/assets/v3/headless-bar-html.png +0 -0
- package/docs/assets/v3/headless-bar-mobile.png +0 -0
- package/docs/assets/v3/headless-bar.png +0 -0
- package/docs/assets/v3/slim-bar.png +0 -0
- package/docs/concepts/choose-your-setup.md +87 -0
- package/docs/concepts/consent-categories.md +84 -0
- package/docs/{guides → concepts}/consent-state.md +71 -101
- package/docs/{guides → concepts}/data-fetching.md +31 -27
- package/docs/concepts/how-consent-works.md +123 -0
- package/docs/concepts/policies.md +71 -0
- package/docs/customization/class-names.md +202 -0
- package/docs/customization/dark-mode.md +157 -0
- package/docs/customization/motion.md +119 -0
- package/docs/customization/overview.md +67 -34
- package/docs/customization/recipes.md +839 -49
- package/docs/customization/slots.md +216 -35
- package/docs/customization/stylesheets.md +147 -0
- package/docs/customization/tailwind.md +842 -0
- package/docs/customization/tokens.md +163 -96
- package/docs/customization/translations.md +61 -3
- package/docs/frameworks/astro/embeds.md +160 -0
- package/docs/frameworks/astro/network-blocker.md +86 -0
- package/docs/frameworks/astro/scripts.md +146 -0
- package/docs/frameworks/html/embeds.md +142 -0
- package/docs/frameworks/html/network-blocker.md +105 -0
- package/docs/frameworks/html/scripts.md +164 -0
- package/docs/frameworks/javascript/scripts.md +119 -0
- package/docs/frameworks/next/embeds.md +90 -0
- package/docs/frameworks/next/network-blocker.md +153 -0
- package/docs/frameworks/next/scripts.md +196 -0
- package/docs/frameworks/nuxt/embeds.md +81 -0
- package/docs/frameworks/nuxt/network-blocker.md +97 -0
- package/docs/frameworks/nuxt/scripts.md +89 -0
- package/docs/frameworks/react/embeds.md +89 -0
- package/docs/frameworks/react/network-blocker.md +140 -0
- package/docs/frameworks/react/scripts.md +115 -0
- package/docs/frameworks/svelte/embeds.md +96 -0
- package/docs/frameworks/svelte/network-blocker.md +141 -0
- package/docs/frameworks/svelte/scripts.md +137 -0
- package/docs/frameworks/sveltekit/embeds.md +103 -0
- package/docs/frameworks/sveltekit/network-blocker.md +149 -0
- package/docs/frameworks/sveltekit/scripts.md +141 -0
- package/docs/frameworks/tanstack-start/embeds.md +96 -0
- package/docs/frameworks/tanstack-start/network-blocker.md +145 -0
- package/docs/frameworks/tanstack-start/scripts.md +103 -0
- package/docs/frameworks/vue/embeds.md +84 -0
- package/docs/frameworks/vue/network-blocker.md +99 -0
- package/docs/frameworks/vue/scripts.md +93 -0
- package/docs/guides/banner-experiments.md +654 -0
- package/docs/guides/troubleshooting.md +120 -47
- package/docs/guides/verify-consent.md +81 -49
- package/docs/integrations/adobe-analytics.md +167 -159
- package/docs/integrations/ahrefs-analytics.md +152 -154
- package/docs/integrations/amplitude.md +162 -156
- package/docs/integrations/building-integrations.md +136 -37
- package/docs/integrations/clearbit.md +154 -154
- package/docs/integrations/cloudflare-web-analytics.md +156 -156
- package/docs/integrations/cloudflare-zaraz.md +209 -261
- package/docs/integrations/crisp.md +164 -158
- package/docs/integrations/databuddy.md +157 -173
- package/docs/integrations/fathom-analytics.md +158 -156
- package/docs/integrations/front-chat.md +167 -167
- package/docs/integrations/google-maps.md +118 -83
- package/docs/integrations/google-tag-manager.md +178 -163
- package/docs/integrations/google-tag.md +163 -160
- package/docs/integrations/heap.md +163 -155
- package/docs/integrations/hightouch.md +161 -157
- package/docs/integrations/hotjar.md +159 -155
- package/docs/integrations/intercom.md +183 -153
- package/docs/integrations/klaviyo.md +486 -0
- package/docs/integrations/linkedin-insights.md +174 -150
- package/docs/integrations/logrocket.md +160 -156
- package/docs/integrations/matomo-analytics.md +188 -178
- package/docs/integrations/meta-pixel.md +188 -150
- package/docs/integrations/microsoft-clarity.md +163 -155
- package/docs/integrations/microsoft-uet.md +148 -154
- package/docs/integrations/mixpanel-analytics.md +155 -160
- package/docs/integrations/one-dollar-stats.md +166 -165
- package/docs/integrations/openai-pixel.md +204 -301
- package/docs/integrations/overview.md +137 -80
- package/docs/integrations/pinterest-tag.md +191 -183
- package/docs/integrations/pirsch.md +169 -159
- package/docs/integrations/plausible-analytics.md +172 -158
- package/docs/integrations/posthog.md +226 -241
- package/docs/integrations/promptwatch.md +154 -154
- package/docs/integrations/reddit-pixel.md +185 -157
- package/docs/integrations/rudderstack.md +201 -186
- package/docs/integrations/rybbit-analytics.md +171 -160
- package/docs/integrations/segment.md +182 -154
- package/docs/integrations/snapchat-pixel.md +186 -156
- package/docs/integrations/tiktok-pixel.md +171 -150
- package/docs/integrations/umami-analytics.md +163 -158
- package/docs/integrations/vercel-analytics.md +166 -157
- package/docs/integrations/x-pixel.md +176 -150
- package/docs/integrations/youtube.md +121 -86
- package/docs/upgrade-v3.md +475 -467
- package/package.json +10 -257
- package/dist-types/__tests__/helpers.d.ts +0 -141
- package/docs/assets/v3/brand-bar.png +0 -0
- package/docs/assets/v3/mobile-card.png +0 -0
- package/docs/assets/v3/preferences.png +0 -0
- package/docs/frameworks/javascript/script-loader.md +0 -100
- package/docs/frameworks/next/script-loader.md +0 -216
- package/docs/frameworks/react/script-loader.md +0 -69
- package/docs/guides/deployment-modes.md +0 -75
- package/docs/guides/shared-consent-controls.md +0 -158
- package/docs/integrations/clear-on-revocation.md +0 -167
- package/docs/integrations/granular-consent.md +0 -210
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Load scripts with consent
|
|
3
|
-
description: Register vendor scripts in your existing Next.js ConsentRoot and
|
|
4
|
-
handle loading and revocation.
|
|
5
|
-
group: frameworks
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Keep one owner for vendor scripts
|
|
9
|
-
|
|
10
|
-
The [App Router](https://c15t.com/docs/frameworks/next/app-router) and
|
|
11
|
-
[Pages Router](https://c15t.com/docs/frameworks/next/pages-router) setups already register scripts
|
|
12
|
-
in a client wrapper. Keep that wrapper and add vendors to `lib/scripts.ts`.
|
|
13
|
-
If you are adding scripts to an existing c15t setup, install the helpers and
|
|
14
|
-
use the same registration pattern below.
|
|
15
|
-
|
|
16
|
-
| Package manager | Command |
|
|
17
|
-
| :-------------- | :-------------------------- |
|
|
18
|
-
| npm | `npm install @c15t/scripts` |
|
|
19
|
-
| pnpm | `pnpm add @c15t/scripts` |
|
|
20
|
-
| yarn | `yarn add @c15t/scripts` |
|
|
21
|
-
| bun | `bun add @c15t/scripts` |
|
|
22
|
-
|
|
23
|
-
Keep `c15t.config.ts` and the manifest route from your router setup. These shared
|
|
24
|
-
URLs connect initialization and consent submissions to the same backend.
|
|
25
|
-
|
|
26
|
-
## Register scripts in a client wrapper
|
|
27
|
-
|
|
28
|
-
The [runnable Next.js example](https://c15t.com/docs/examples) uses PostHog for measurement and
|
|
29
|
-
X Pixel for marketing. Set `NEXT_PUBLIC_POSTHOG_KEY` and
|
|
30
|
-
`NEXT_PUBLIC_X_PIXEL_ID` to your own project identifiers before building.
|
|
31
|
-
`NEXT_PUBLIC_POSTHOG_HOST` optionally selects your PostHog region's API host.
|
|
32
|
-
Omit a vendor's ID to leave that integration disabled, or replace its helper
|
|
33
|
-
with the [integration](../../integrations/overview.md) your application uses. Include the
|
|
34
|
-
measurement and marketing categories in your policy for these two vendors.
|
|
35
|
-
|
|
36
|
-
Create `lib/scripts.ts` with the example's script configuration:
|
|
37
|
-
|
|
38
|
-
```ts title="lib/scripts.ts"
|
|
39
|
-
import { posthog } from '@c15t/scripts/posthog';
|
|
40
|
-
import { xPixel } from '@c15t/scripts/x-pixel';
|
|
41
|
-
import type { Script } from 'c15t';
|
|
42
|
-
|
|
43
|
-
export const posthogConfigured = Boolean(process.env.NEXT_PUBLIC_POSTHOG_KEY);
|
|
44
|
-
export const xPixelConfigured = Boolean(process.env.NEXT_PUBLIC_X_PIXEL_ID);
|
|
45
|
-
|
|
46
|
-
export const scripts: Script[] = [];
|
|
47
|
-
|
|
48
|
-
if (process.env.NEXT_PUBLIC_POSTHOG_KEY) {
|
|
49
|
-
scripts.push(
|
|
50
|
-
posthog({
|
|
51
|
-
apiHost: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
52
|
-
id: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
|
53
|
-
initOptions: { cookieless_mode: 'never' },
|
|
54
|
-
loadMode: 'after-consent',
|
|
55
|
-
})
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (process.env.NEXT_PUBLIC_X_PIXEL_ID) {
|
|
60
|
-
scripts.push(xPixel({ pixelId: process.env.NEXT_PUBLIC_X_PIXEL_ID }));
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
PostHog waits for measurement consent here. `cookieless_mode: 'never'` disables
|
|
65
|
-
cookieless capture after rejection. X Pixel waits for marketing consent. Remove
|
|
66
|
-
any existing loader for these vendors, including `next/script` and tag-manager
|
|
67
|
-
entries, so each integration loads once.
|
|
68
|
-
|
|
69
|
-
Create this client wrapper. It keeps scripts and browser callbacks in the client
|
|
70
|
-
while the router supplies the visitor's resolved state through `state`:
|
|
71
|
-
|
|
72
|
-
```tsx title="components/consent.tsx"
|
|
73
|
-
'use client';
|
|
74
|
-
|
|
75
|
-
import type { ReactNode } from 'react';
|
|
76
|
-
import {
|
|
77
|
-
ConsentBanner,
|
|
78
|
-
ConsentDialog,
|
|
79
|
-
ConsentDialogLink,
|
|
80
|
-
ConsentRoot,
|
|
81
|
-
} from 'c15t/next';
|
|
82
|
-
import type { ConsentRootProps } from 'c15t/next';
|
|
83
|
-
import { consentConfig } from '../c15t.config';
|
|
84
|
-
import { scripts } from '../lib/scripts';
|
|
85
|
-
|
|
86
|
-
export function Consent({
|
|
87
|
-
children,
|
|
88
|
-
state,
|
|
89
|
-
}: {
|
|
90
|
-
children: ReactNode;
|
|
91
|
-
state: ConsentRootProps['state'];
|
|
92
|
-
}) {
|
|
93
|
-
return (
|
|
94
|
-
<ConsentRoot state={state} config={consentConfig} scripts={scripts}>
|
|
95
|
-
{children}
|
|
96
|
-
<ConsentBanner />
|
|
97
|
-
<ConsentDialog />
|
|
98
|
-
<footer>
|
|
99
|
-
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
100
|
-
</footer>
|
|
101
|
-
</ConsentRoot>
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
`ConsentRoot` already provides the consent runtime. Mount this wrapper once;
|
|
107
|
-
do not add a second provider. Keep your site's content and footer inside it.
|
|
108
|
-
|
|
109
|
-
## Pass prepared consent through your router
|
|
110
|
-
|
|
111
|
-
In the App Router, the root layout from the
|
|
112
|
-
[App Router guide](https://c15t.com/docs/frameworks/next/app-router) passes the pending
|
|
113
|
-
`resolveConsent` result to this wrapper. This partial example is that call;
|
|
114
|
-
keep the `html`, `body` and stylesheet from your existing layout:
|
|
115
|
-
|
|
116
|
-
```tsx
|
|
117
|
-
import { resolveConsent } from 'c15t/next/server';
|
|
118
|
-
import { consentConfig } from '../c15t.config';
|
|
119
|
-
import { Consent } from '../components/consent';
|
|
120
|
-
|
|
121
|
-
// Inside the existing synchronous root layout:
|
|
122
|
-
const state = resolveConsent({ config: consentConfig });
|
|
123
|
-
|
|
124
|
-
<Consent state={state}>{children}</Consent>
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
No script loads until the browser has applied the resolved policy and the
|
|
128
|
-
visitor's choice allows it. With the
|
|
129
|
-
[awaited layout](https://c15t.com/docs/frameworks/next/app-router#render-the-banner-in-the-server-html),
|
|
130
|
-
pass the awaited result from `ResolvedConsent` to the same wrapper instead.
|
|
131
|
-
|
|
132
|
-
Pages Router passes `state={pageProps.consentState ?? {}}` to this wrapper
|
|
133
|
-
in `_app.tsx`. Keep `getServerSideProps` and its `c15t/next/pages` helper.
|
|
134
|
-
The router guides contain complete layout and `_app.tsx` files.
|
|
135
|
-
|
|
136
|
-
For static export or browser-only initialization, pass `state={{}}` and keep
|
|
137
|
-
that setup's existing transport. Register scripts on its existing `ConsentRoot`;
|
|
138
|
-
do not introduce server prefetch or local routes just to add a vendor.
|
|
139
|
-
|
|
140
|
-
## Check each vendor's loading behavior
|
|
141
|
-
|
|
142
|
-
The example explicitly configures PostHog to load after consent and disables
|
|
143
|
-
cookieless capture. Those settings are deliberate; its default helper can load
|
|
144
|
-
before consent and use the SDK's consent controls. Read the
|
|
145
|
-
[PostHog guide](../../integrations/posthog.md) before changing them.
|
|
146
|
-
|
|
147
|
-
Ordinary scripts wait for their category's effective permission. Give each
|
|
148
|
-
script a stable unique `id` and remove any other loader for the same vendor.
|
|
149
|
-
Helpers with `alwaysLoad` may load an SDK before permission is granted; a
|
|
150
|
-
category field alone does not guarantee no requests. See the
|
|
151
|
-
[vendor guides](../../integrations/overview.md) for their exact contracts.
|
|
152
|
-
|
|
153
|
-
Removing a script element cannot undo executed JavaScript or requests already
|
|
154
|
-
sent. PostHog exposes capture controls; X Pixel has no consent-update API.
|
|
155
|
-
Stop future event calls after revocation and test a change from allowed to
|
|
156
|
-
denied, as well as initial denial.
|
|
157
|
-
|
|
158
|
-
## Verify the integration
|
|
159
|
-
|
|
160
|
-
With an opt-in policy and no saved choice, neither configured example vendor
|
|
161
|
-
should load. Allow measurement only: PostHog loads and X Pixel remains blocked.
|
|
162
|
-
Reject, reload, and reopen Privacy settings to confirm the choice persists.
|
|
163
|
-
|
|
164
|
-
Use the [runnable example](https://c15t.com/docs/examples) to inspect the same script definitions
|
|
165
|
-
with DevTools, or follow [verification](../../guides/verify-consent.md) in your app.
|
|
166
|
-
Use [custom integrations](../../integrations/building-integrations.md) for an
|
|
167
|
-
unlisted vendor. Google helpers have a separate
|
|
168
|
-
[Consent Mode contract](../../integrations/google-tag-manager.md).
|
|
169
|
-
|
|
170
|
-
## Granular consent
|
|
171
|
-
|
|
172
|
-
A visitor can grant marketing and still turn one vendor off. Declare the
|
|
173
|
-
vendors next to the scripts in `lib/scripts.ts`, with the `vendor` slug each
|
|
174
|
-
script already carries, and pass both to `ConsentRoot`:
|
|
175
|
-
|
|
176
|
-
```ts title="lib/scripts.ts"
|
|
177
|
-
import type { Vendor } from 'c15t';
|
|
178
|
-
|
|
179
|
-
export const vendors: Vendor[] = [
|
|
180
|
-
{
|
|
181
|
-
id: 'x-pixel',
|
|
182
|
-
name: 'X Pixel',
|
|
183
|
-
category: 'marketing',
|
|
184
|
-
privacyPolicyUrl: 'https://x.com/privacy',
|
|
185
|
-
},
|
|
186
|
-
];
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
```tsx title="components/consent.tsx"
|
|
190
|
-
import { scripts, vendors } from '../lib/scripts';
|
|
191
|
-
|
|
192
|
-
<ConsentRoot state={state} config={consentConfig} scripts={scripts} vendors={vendors}>
|
|
193
|
-
{children}
|
|
194
|
-
</ConsentRoot>
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
The preference center lists each vendor under its category with a switch.
|
|
198
|
-
Integrations from `@c15t/scripts` set `vendor` to their manifest slug, so
|
|
199
|
-
`xPixel()` needs no extra wiring; give a hand-written script the same slug
|
|
200
|
-
in its `vendor` field. A backend manifest can declare vendors too. See
|
|
201
|
-
[granular consent](../../integrations/granular-consent.md) for storage,
|
|
202
|
-
bulk actions and the hooks a custom control uses.
|
|
203
|
-
|
|
204
|
-
## Clear stored tracking data
|
|
205
|
-
|
|
206
|
-
Script gating does not remove cookies or Web Storage entries that a script
|
|
207
|
-
already wrote. Add `clearOnRevocation` to your `ConsentRoot` or provider
|
|
208
|
-
options to remove declared data when its category is denied. See
|
|
209
|
-
[clear on revocation](../../integrations/clear-on-revocation.md) for configuration
|
|
210
|
-
and browser limits.
|
|
211
|
-
|
|
212
|
-
## Shared lifecycle controls
|
|
213
|
-
|
|
214
|
-
See [shared consent controls](../../guides/shared-consent-controls.md) for external CMPs,
|
|
215
|
-
preference delegation, withdrawal reloads, and application events. These controls
|
|
216
|
-
use the same core runtime across frameworks.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Load scripts with consent
|
|
3
|
-
description: Register vendor scripts once and let effective permissions control loading.
|
|
4
|
-
group: frameworks
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Register scripts on the provider
|
|
8
|
-
|
|
9
|
-
Install `@c15t/scripts` for vendor helpers. This React-compatible client component
|
|
10
|
-
uses Inth as the backend. Set the URL to the endpoint supplied by your Inth
|
|
11
|
-
project and keep the component mounted around your application.
|
|
12
|
-
|
|
13
|
-
```tsx title="components/consent.tsx"
|
|
14
|
-
'use client';
|
|
15
|
-
|
|
16
|
-
import type { ReactNode } from 'react';
|
|
17
|
-
import { ConsentProvider, ConsentBanner, ConsentDialog, ConsentDialogLink, hosted } from 'c15t/react';
|
|
18
|
-
import { metaPixel } from '@c15t/scripts/meta-pixel';
|
|
19
|
-
|
|
20
|
-
const mode = hosted({ url: 'https://your-project.inth.app' });
|
|
21
|
-
const scripts = [metaPixel({ pixelId: '123456789012345' })];
|
|
22
|
-
|
|
23
|
-
export function Consent({ children }: { children: ReactNode }) {
|
|
24
|
-
return (
|
|
25
|
-
<ConsentProvider options={{ mode, scripts }}>
|
|
26
|
-
{children}
|
|
27
|
-
<ConsentBanner />
|
|
28
|
-
<ConsentDialog />
|
|
29
|
-
<ConsentDialogLink>Privacy settings</ConsentDialogLink>
|
|
30
|
-
</ConsentProvider>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Import your adapter's stylesheet globally, as in the framework quickstart. For
|
|
36
|
-
an existing server-resolved `ConsentRoot`, keep that root and pass
|
|
37
|
-
`scripts` as a top-level prop instead of mounting a second provider.
|
|
38
|
-
|
|
39
|
-
## Understand loading and revocation
|
|
40
|
-
|
|
41
|
-
Ordinary scripts wait for their category's effective permission. Give each
|
|
42
|
-
script a stable unique `id` and remove any other loader for the same vendor.
|
|
43
|
-
Some helpers use `alwaysLoad` to load the SDK and signal consent through its own
|
|
44
|
-
API. Read the vendor guide; a category field alone does not guarantee no
|
|
45
|
-
requests.
|
|
46
|
-
|
|
47
|
-
Removing a script element cannot undo JavaScript that already executed or
|
|
48
|
-
requests already sent. Use the vendor's supported consent and cleanup behavior,
|
|
49
|
-
and stop future event calls after revocation. Test both initial denial and a
|
|
50
|
-
change from allowed to denied.
|
|
51
|
-
|
|
52
|
-
Use [custom integrations](../../integrations/building-integrations.md) for an
|
|
53
|
-
unlisted vendor and [verification](../../guides/verify-consent.md) for the network
|
|
54
|
-
checks. Google helpers have a separate
|
|
55
|
-
[Consent Mode contract](../../integrations/google-tag-manager.md).
|
|
56
|
-
|
|
57
|
-
## Clear stored tracking data
|
|
58
|
-
|
|
59
|
-
Script gating does not remove cookies or Web Storage entries that a script
|
|
60
|
-
already wrote. Add `clearOnRevocation` to `ConsentProvider.options` to remove
|
|
61
|
-
declared data when its category is denied. See
|
|
62
|
-
[clear on revocation](../../integrations/clear-on-revocation.md) for configuration
|
|
63
|
-
and browser limits.
|
|
64
|
-
|
|
65
|
-
## Shared lifecycle controls
|
|
66
|
-
|
|
67
|
-
See [shared consent controls](../../guides/shared-consent-controls.md) for external CMPs,
|
|
68
|
-
preference delegation, withdrawal reloads, and application events. These controls
|
|
69
|
-
use the same core runtime across frameworks.
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Choose a deployment mode
|
|
3
|
-
description: Choose who runs your consent backend, then select manifest, init or
|
|
4
|
-
offline resolution for your deployment.
|
|
5
|
-
group: guides
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Use Inth for managed policy and records
|
|
9
|
-
|
|
10
|
-
Start with [Inth](https://inth.com) unless you need to operate the consent
|
|
11
|
-
service yourself or deliberately need only local browser records. Configure
|
|
12
|
-
policy rules and trusted origins in the project, then use its exact backend
|
|
13
|
-
endpoint in your framework setup.
|
|
14
|
-
|
|
15
|
-
| Backend ownership | Policy source | Record storage | Use when |
|
|
16
|
-
| ------------------------- | ------------------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------------------- |
|
|
17
|
-
| Inth hosted service | Centrally managed policy through a manifest or `/init` | Browser records plus backend submissions | You want managed policy and consent records |
|
|
18
|
-
| Self-hosted c15t | Your backend's manifest or `/init` | Browser records plus your database | You need to operate the service and its infrastructure |
|
|
19
|
-
| Browser-only offline mode | Bundled `policyRules` | Browser persistence | Local development and tests. Not recommended for production environments. |
|
|
20
|
-
|
|
21
|
-
Hosted and self-hosted c15t use the same transport protocol. Switching who runs
|
|
22
|
-
the backend does not require switching from manifests to `/init`.
|
|
23
|
-
|
|
24
|
-
## Choose data fetching separately
|
|
25
|
-
|
|
26
|
-
For Next.js deployments with a runtime server, use the
|
|
27
|
-
[manifest setup](https://c15t.com/docs/frameworks/next/data-fetching). It reuses public policy data
|
|
28
|
-
in your application while consent writes still go to Inth. Regular backend
|
|
29
|
-
`/init` is available when you want backend-owned request resolution or a simpler
|
|
30
|
-
browser setup. See [data fetching and transports](./data-fetching.md) for
|
|
31
|
-
the comparison, including custom transports and offline mode.
|
|
32
|
-
|
|
33
|
-
Manifest resolution removes the per-visitor `/init` request, and with it the
|
|
34
|
-
backend's only count of visitors. The server adapters replace it with a session
|
|
35
|
-
report: after each resolution, on a server-rendered page or the same-origin
|
|
36
|
-
init route, the host posts a small report to the backend's `POST /sessions`,
|
|
37
|
-
server-to-server and detached from the response. The browser makes no request
|
|
38
|
-
and the report stores no identity; the visitor's IP and user agent travel as
|
|
39
|
-
forwarded headers under the backend's usual IP handling. Each report is one
|
|
40
|
-
resolution; a page view can produce a `render` and a `route` report, and the
|
|
41
|
-
consuming side groups them into sessions by address and user agent within a
|
|
42
|
-
window. Static output resolves in the browser and sends none. Set `reportSessions: false` on an adapter to turn
|
|
43
|
-
it off.
|
|
44
|
-
|
|
45
|
-
## Match initialization to your application output
|
|
46
|
-
|
|
47
|
-
| Application output | Initial state | Required setup |
|
|
48
|
-
| ------------------ | ------------------------- | ----------------------------------------------------------- |
|
|
49
|
-
| Request SSR | Prepared for this visitor | Adapter request helper and matching client configuration |
|
|
50
|
-
| Static HTML or SPA | Resolved in the browser | Reachable external URLs or deliberately bundled local rules |
|
|
51
|
-
|
|
52
|
-
Request SSR can include the visitor's prompt in the initial HTML. Pass the
|
|
53
|
-
prepared records and policy resolution through to hydration. Do not convert
|
|
54
|
-
effective permissions into new stored choices.
|
|
55
|
-
|
|
56
|
-
Static HTML is shared across visitors. It cannot contain a choice resolved from
|
|
57
|
-
each visitor's cookies or geography at build time. A static site can still use
|
|
58
|
-
Inth through browser requests. A same-origin `/api/c15t` URL only works if a
|
|
59
|
-
service actually serves it; a Next.js static export does not run API routes.
|
|
60
|
-
|
|
61
|
-
A manifest contains reusable public policy data. A resolved init response and
|
|
62
|
-
personalized consent HTML belong to a request. Do not give them the same shared
|
|
63
|
-
cache treatment.
|
|
64
|
-
|
|
65
|
-
## Handle initialization and storage failures
|
|
66
|
-
|
|
67
|
-
While no policy resolves, optional permissions stay denied and the stock
|
|
68
|
-
consent UI stays hidden. No banner can mean pending or failed initialization.
|
|
69
|
-
It does not mean permission to load analytics. Observe errors before changing
|
|
70
|
-
presentation, and do not silently switch to offline policy after a hosted
|
|
71
|
-
request fails.
|
|
72
|
-
|
|
73
|
-
Browser storage can also be unavailable. A working in-memory interaction does
|
|
74
|
-
not prove the choice survives reload. Use
|
|
75
|
-
[verification](./verify-consent.md) to test the actual deployment.
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Share consent controls across frameworks
|
|
3
|
-
description: Use the same c15t script lifecycle, external consent source, and
|
|
4
|
-
event controls in every framework.
|
|
5
|
-
group: guides
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Choose one consent authority
|
|
9
|
-
|
|
10
|
-
c15t owns script loading, consent gates, lifecycle callbacks, and optional cleanup
|
|
11
|
-
through its framework-independent core. React, Vue, Svelte, Astro, and the browser
|
|
12
|
-
client connect to that core. Next.js and TanStack Start use the React provider;
|
|
13
|
-
Nuxt uses Vue; SvelteKit uses Svelte. None requires Astro for these controls.
|
|
14
|
-
|
|
15
|
-
With c15t as the consent authority, keep your framework's hosted, self-hosted, or
|
|
16
|
-
offline setup. Offline mode keeps choices in the browser; a hosted backend can
|
|
17
|
-
store records. The script SDK and event dispatcher work with either mode.
|
|
18
|
-
|
|
19
|
-
To keep another CMP, provide a `consentSource`. It owns the banner, preferences,
|
|
20
|
-
records, expiration, privacy signals, and category mapping. c15t follows its
|
|
21
|
-
current permissions without creating a second choice record. Optional categories
|
|
22
|
-
start denied, including during SSR. An unavailable source or a failed read denies
|
|
23
|
-
them again. Initialize the CMP independently, or register its loader as an
|
|
24
|
-
explicitly early-loading script so it does not wait for its own consent.
|
|
25
|
-
|
|
26
|
-
The source contract is exported from `@c15t/core/runtime`:
|
|
27
|
-
|
|
28
|
-
```ts title="src/consent-source.ts — adapter skeleton"
|
|
29
|
-
import type { ExternalConsentSource } from 'c15t/runtime';
|
|
30
|
-
import { provider } from './existing-cmp';
|
|
31
|
-
|
|
32
|
-
export const consentSource: ExternalConsentSource = {
|
|
33
|
-
getPermissions: () => provider.getCategoryPermissions(),
|
|
34
|
-
subscribe: (notify) => provider.subscribe(notify),
|
|
35
|
-
openPreferences: () => provider.openPreferences(),
|
|
36
|
-
};
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
`provider` is your application's adapter for the existing CMP, not a c15t export.
|
|
40
|
-
Map its categories to c15t's `measurement`, `marketing`, `functionality`, and
|
|
41
|
-
`experience` booleans. Missing categories are denied; `necessary` stays true.
|
|
42
|
-
Return `null` until the CMP is ready. `subscribe` must notify on initialization,
|
|
43
|
-
changes, withdrawal, and expiration, and return a function that removes listeners.
|
|
44
|
-
Keep browser access inside these functions so importing the adapter during SSR is safe.
|
|
45
|
-
|
|
46
|
-
If `subscribe` throws, c15t reports the failure through `callbacks.onError` and
|
|
47
|
-
continues startup with optional categories denied. The failed connection ignores
|
|
48
|
-
later notifications and does not forward preference requests. Recreate the owner
|
|
49
|
-
after the CMP is available to connect again.
|
|
50
|
-
|
|
51
|
-
## Pass the controls to your framework
|
|
52
|
-
|
|
53
|
-
The `consentSource` option is available at these registration points. Register your SDK configurations through the same owner's
|
|
54
|
-
`scripts` option. Do not create an additional runtime beside an existing provider.
|
|
55
|
-
|
|
56
|
-
| Framework | Registration point |
|
|
57
|
-
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
58
|
-
| React | `ConsentProvider options={{ mode, consentSource, scripts }}` |
|
|
59
|
-
| Next.js / TanStack Start | `ConsentRoot options={{ consentSource }}` with `scripts` as a top-level prop; `ConsentProvider` also accepts the React options |
|
|
60
|
-
| Vue | `app.use(c15tVue, { consentSource, scripts })` |
|
|
61
|
-
| Nuxt | `app.config.ts` → `c15t: { consentSource, scripts }` |
|
|
62
|
-
| Svelte / SvelteKit | `ConsentManagerProvider` options or corresponding top-level props |
|
|
63
|
-
| Astro | `clientOptions.consentSource` |
|
|
64
|
-
| Browser client | `createConsentClient({ consentSource, scripts })` |
|
|
65
|
-
| Headless JavaScript / Solid | `createConsentRuntime({ mode, consentSource, scripts })` |
|
|
66
|
-
|
|
67
|
-
For example, a React client boundary can use the source directly:
|
|
68
|
-
|
|
69
|
-
```tsx title="src/Consent.tsx"
|
|
70
|
-
'use client';
|
|
71
|
-
|
|
72
|
-
import type { ReactNode } from 'react';
|
|
73
|
-
import { ConsentProvider, offline, useSetActiveUI } from 'c15t/react';
|
|
74
|
-
import { googleTagManager } from '@c15t/scripts/google-tag-manager';
|
|
75
|
-
import { consentSource } from './consent-source';
|
|
76
|
-
|
|
77
|
-
const mode = offline();
|
|
78
|
-
const scripts = [googleTagManager({ id: 'GTM-EXAMPLE' })];
|
|
79
|
-
|
|
80
|
-
function Preferences() {
|
|
81
|
-
const setActiveUI = useSetActiveUI();
|
|
82
|
-
return <button type="button" onClick={() => setActiveUI('dialog')}>Privacy settings</button>;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function Consent({ children }: { children: ReactNode }) {
|
|
86
|
-
return (
|
|
87
|
-
<ConsentProvider options={{ mode, consentSource, scripts }}>
|
|
88
|
-
{children}
|
|
89
|
-
<Preferences />
|
|
90
|
-
</ConsentProvider>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Replace the container ID. `mode` remains required by the provider API, but an
|
|
96
|
-
external source bypasses c15t backend initialization and persistence. Omit c15t's
|
|
97
|
-
banner and dialog. Preference links, hooks, and `kernel.set.activeUI('dialog')`
|
|
98
|
-
delegate to the source. Preference-opening failures reach `callbacks.onError`;
|
|
99
|
-
`kernel.commands.save()` rejects instead of recording a second choice.
|
|
100
|
-
|
|
101
|
-
In Next.js, construct the source in the client boundary; do not pass functions
|
|
102
|
-
from a Server Component. Existing `ConsentRoot` state can stay serializable, but
|
|
103
|
-
c15t records do not establish external permissions. A client-owned
|
|
104
|
-
`ConsentProvider` avoids a redundant server consent fetch for external-only setups.
|
|
105
|
-
For Nuxt, use `app.config.ts` for the functions, not serialized public runtime
|
|
106
|
-
configuration; the module skips its consent fetch and record hydration when a
|
|
107
|
-
source is configured. Browser access remains deferred until mount.
|
|
108
|
-
|
|
109
|
-
Solid currently ships UI primitives, not a lifecycle provider. Create the core
|
|
110
|
-
runtime once, call `start()` from `onMount`, and `dispose()` from `onCleanup`.
|
|
111
|
-
Other frameworks' providers perform that lifecycle automatically. A provider given
|
|
112
|
-
an existing `runtime` borrows it: configure controls on the runtime owner, which
|
|
113
|
-
also owns starting and disposing it.
|
|
114
|
-
|
|
115
|
-
## Handle withdrawal and application events
|
|
116
|
-
|
|
117
|
-
When the source withdraws an optional category that was granted, c15t reloads
|
|
118
|
-
the page, as it does when a visitor revokes consent in c15t's own UI. Removing a
|
|
119
|
-
script element cannot stop JavaScript that already ran, so the reload starts a
|
|
120
|
-
page with only permitted code. The reload runs in the next task, after
|
|
121
|
-
synchronous consent callbacks and `onBeforeConsentRevocationReload`. Disposing
|
|
122
|
-
the owner cancels a pending reload.
|
|
123
|
-
|
|
124
|
-
c15t cannot tell a visitor's withdrawal from expiry or a reset in the CMP, so
|
|
125
|
-
any notification that turns off a granted category reloads. The CMP owns
|
|
126
|
-
persistence: store the new decision before notifying c15t, or the reloaded page
|
|
127
|
-
reads the old one. Set `reloadOnConsentRevoked: false` to handle withdrawal
|
|
128
|
-
yourself. c15t still updates gates and calls script consent callbacks.
|
|
129
|
-
|
|
130
|
-
`createEventDispatcher` from `@c15t/scripts/events` also has no framework dependency:
|
|
131
|
-
|
|
132
|
-
```ts title="src/events.ts — attach to an existing runtime"
|
|
133
|
-
import { createEventDispatcher } from '@c15t/scripts/events';
|
|
134
|
-
|
|
135
|
-
const events = createEventDispatcher({
|
|
136
|
-
scripts,
|
|
137
|
-
getSnapshot: () => runtime.kernel.getSnapshot(),
|
|
138
|
-
});
|
|
139
|
-
events.track('docs_search', { resultCount: 4 });
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Here `scripts` is the same configuration registered with the existing `runtime`.
|
|
143
|
-
For a provider-owned kernel, use that kernel's live `getSnapshot` instead. The
|
|
144
|
-
dispatcher sends only to configured integrations with supported event APIs when
|
|
145
|
-
measurement and the script's own consent condition allow it. It discards denied
|
|
146
|
-
events, isolates vendor failures, and deduplicates explicitly configured SPA
|
|
147
|
-
pageviews. It does not subscribe to a framework router: notify it from your
|
|
148
|
-
router's navigation hook. Use vendor-specific helpers for APIs outside the shared
|
|
149
|
-
event contract.
|
|
150
|
-
|
|
151
|
-
## Verify the integration
|
|
152
|
-
|
|
153
|
-
Test an undecided visitor, an existing grant, withdrawal, expiry, and a source
|
|
154
|
-
that cannot be read. Check that only permitted scripts execute, the preference
|
|
155
|
-
control opens the existing CMP, c15t does not render another banner or persist
|
|
156
|
-
another receipt, and unmounting removes the source listeners. Test your actual
|
|
157
|
-
CMP category mapping and tag-manager container; shared gates do not validate
|
|
158
|
-
those configurations or establish compliance by themselves.
|