@c15t/scripts 3.0.0-alpha.2 → 3.0.0-alpha.4

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.
Files changed (300) hide show
  1. package/AGENTS.md +129 -63
  2. package/README.md +8 -29
  3. package/SKILL.md +33 -0
  4. package/dist/adobe-analytics.js +2 -0
  5. package/dist/ahrefs-analytics.js +2 -0
  6. package/dist/amplitude.js +2 -0
  7. package/dist/clearbit.js +2 -0
  8. package/dist/cloudflare-web-analytics.js +2 -0
  9. package/dist/cloudflare-zaraz.js +2 -0
  10. package/dist/crisp.js +2 -0
  11. package/dist/databuddy.js +2 -0
  12. package/dist/e2e-test-utils.js +2 -139
  13. package/dist/engine/compile.js +2 -89
  14. package/dist/engine/runtime.js +2 -448
  15. package/dist/events.js +2 -218
  16. package/dist/fathom-analytics.js +2 -0
  17. package/dist/front-chat.js +2 -0
  18. package/dist/google-tag-manager.js +2 -0
  19. package/dist/google-tag.js +2 -0
  20. package/dist/heap.js +2 -0
  21. package/dist/hightouch.js +2 -0
  22. package/dist/hotjar.js +2 -0
  23. package/dist/intercom.js +2 -0
  24. package/dist/klaviyo.js +2 -0
  25. package/dist/linkedin-insights.js +2 -0
  26. package/dist/logrocket.js +2 -0
  27. package/dist/matomo-analytics.js +2 -0
  28. package/dist/meta-pixel.js +2 -0
  29. package/dist/microsoft-clarity.js +2 -0
  30. package/dist/microsoft-uet.js +2 -0
  31. package/dist/mixpanel-analytics.js +2 -0
  32. package/dist/one-dollar-stats.js +2 -0
  33. package/dist/openai-pixel.js +2 -0
  34. package/dist/pinterest-tag.js +2 -0
  35. package/dist/pirsch.js +2 -0
  36. package/dist/plausible-analytics.js +2 -0
  37. package/dist/posthog.js +2 -0
  38. package/dist/promptwatch.js +2 -0
  39. package/dist/reddit-pixel.js +2 -0
  40. package/dist/registry.js +2 -422
  41. package/dist/resolve.js +2 -33
  42. package/dist/rudderstack.js +2 -0
  43. package/dist/rybbit-analytics.js +2 -0
  44. package/dist/segment.js +2 -0
  45. package/dist/snapchat-pixel.js +2 -0
  46. package/dist/tiktok-pixel.js +2 -0
  47. package/dist/types.js +2 -16
  48. package/dist/umami-analytics.js +2 -0
  49. package/dist/vendors/_shared/attributes.js +2 -14
  50. package/dist/vendors/_shared/google-consent.js +2 -27
  51. package/dist/vendors/_shared/install-builders.js +2 -21
  52. package/dist/vendors/_shared/required-id.js +2 -0
  53. package/dist/vendors/_shared/script-url.js +2 -28
  54. package/dist/vendors/ads-and-pixels/linkedin-insights.js +2 -48
  55. package/dist/vendors/ads-and-pixels/meta-pixel.js +2 -153
  56. package/dist/vendors/ads-and-pixels/microsoft-uet.js +2 -110
  57. package/dist/vendors/ads-and-pixels/openai-pixel.js +2 -88
  58. package/dist/vendors/ads-and-pixels/pinterest-tag.js +2 -123
  59. package/dist/vendors/ads-and-pixels/reddit-pixel.js +2 -107
  60. package/dist/vendors/ads-and-pixels/snapchat-pixel.js +2 -87
  61. package/dist/vendors/ads-and-pixels/tiktok-pixel.js +2 -89
  62. package/dist/vendors/ads-and-pixels/x-pixel.js +2 -48
  63. package/dist/vendors/analytics/adobe-analytics.js +2 -49
  64. package/dist/vendors/analytics/ahrefs-analytics.js +2 -27
  65. package/dist/vendors/analytics/amplitude.js +2 -134
  66. package/dist/vendors/analytics/clearbit.js +2 -28
  67. package/dist/vendors/analytics/cloudflare-web-analytics.js +2 -32
  68. package/dist/vendors/analytics/databuddy.js +2 -103
  69. package/dist/vendors/analytics/fathom-analytics.js +2 -35
  70. package/dist/vendors/analytics/google-tag.js +2 -78
  71. package/dist/vendors/analytics/heap.js +2 -134
  72. package/dist/vendors/analytics/hightouch.js +2 -109
  73. package/dist/vendors/analytics/hotjar.js +2 -44
  74. package/dist/vendors/analytics/logrocket.js +2 -58
  75. package/dist/vendors/analytics/matomo-analytics.js +2 -191
  76. package/dist/vendors/analytics/microsoft-clarity.js +2 -100
  77. package/dist/vendors/analytics/mixpanel-analytics.js +2 -93
  78. package/dist/vendors/analytics/one-dollar-stats.js +2 -30
  79. package/dist/vendors/analytics/pirsch.js +2 -67
  80. package/dist/vendors/analytics/plausible-analytics.js +2 -81
  81. package/dist/vendors/analytics/posthog.js +2 -200
  82. package/dist/vendors/analytics/promptwatch.js +2 -29
  83. package/dist/vendors/analytics/rudderstack.js +2 -183
  84. package/dist/vendors/analytics/rybbit-analytics.js +2 -63
  85. package/dist/vendors/analytics/segment.js +2 -65
  86. package/dist/vendors/analytics/umami-analytics.js +2 -39
  87. package/dist/vendors/analytics/vercel-analytics.js +2 -53
  88. package/dist/vendors/email-and-sms/klaviyo.js +2 -0
  89. package/dist/vendors/functional/crisp.js +2 -100
  90. package/dist/vendors/functional/front-chat.js +2 -64
  91. package/dist/vendors/functional/intercom.js +2 -45
  92. package/dist/vendors/tag-managers/cloudflare-zaraz.js +2 -98
  93. package/dist/vendors/tag-managers/google-tag-manager.js +2 -73
  94. package/dist/vercel-analytics.js +2 -0
  95. package/dist/x-pixel.js +2 -0
  96. package/dist-types/adobe-analytics.d.ts +2 -0
  97. package/dist-types/ahrefs-analytics.d.ts +2 -0
  98. package/dist-types/amplitude.d.ts +2 -0
  99. package/dist-types/clearbit.d.ts +2 -0
  100. package/dist-types/cloudflare-web-analytics.d.ts +2 -0
  101. package/dist-types/cloudflare-zaraz.d.ts +2 -0
  102. package/dist-types/crisp.d.ts +2 -0
  103. package/dist-types/databuddy.d.ts +2 -0
  104. package/dist-types/e2e-test-utils.d.ts +2 -0
  105. package/dist-types/engine/compile.d.ts +2 -3
  106. package/dist-types/engine/runtime.d.ts +2 -3
  107. package/dist-types/events.d.ts +2 -46
  108. package/dist-types/fathom-analytics.d.ts +2 -0
  109. package/dist-types/front-chat.d.ts +2 -0
  110. package/dist-types/google-tag-manager.d.ts +2 -0
  111. package/dist-types/google-tag.d.ts +2 -0
  112. package/dist-types/heap.d.ts +2 -0
  113. package/dist-types/hightouch.d.ts +2 -0
  114. package/dist-types/hotjar.d.ts +2 -0
  115. package/dist-types/intercom.d.ts +2 -0
  116. package/dist-types/klaviyo.d.ts +2 -0
  117. package/dist-types/linkedin-insights.d.ts +2 -0
  118. package/dist-types/logrocket.d.ts +2 -0
  119. package/dist-types/matomo-analytics.d.ts +2 -0
  120. package/dist-types/meta-pixel.d.ts +2 -0
  121. package/dist-types/microsoft-clarity.d.ts +2 -0
  122. package/dist-types/microsoft-uet.d.ts +2 -0
  123. package/dist-types/mixpanel-analytics.d.ts +2 -0
  124. package/dist-types/one-dollar-stats.d.ts +2 -0
  125. package/dist-types/openai-pixel.d.ts +2 -0
  126. package/dist-types/pinterest-tag.d.ts +2 -0
  127. package/dist-types/pirsch.d.ts +2 -0
  128. package/dist-types/plausible-analytics.d.ts +2 -0
  129. package/dist-types/posthog.d.ts +2 -0
  130. package/dist-types/promptwatch.d.ts +2 -0
  131. package/dist-types/reddit-pixel.d.ts +2 -0
  132. package/dist-types/registry.d.ts +2 -485
  133. package/dist-types/resolve.d.ts +2 -9
  134. package/dist-types/rudderstack.d.ts +2 -0
  135. package/dist-types/rybbit-analytics.d.ts +2 -0
  136. package/dist-types/segment.d.ts +2 -0
  137. package/dist-types/snapchat-pixel.d.ts +2 -0
  138. package/dist-types/tiktok-pixel.d.ts +2 -0
  139. package/dist-types/types.d.ts +2 -314
  140. package/dist-types/umami-analytics.d.ts +2 -0
  141. package/dist-types/vendors/_shared/attributes.d.ts +2 -35
  142. package/dist-types/vendors/_shared/google-consent.d.ts +2 -47
  143. package/dist-types/vendors/_shared/install-builders.d.ts +2 -30
  144. package/dist-types/vendors/_shared/required-id.d.ts +2 -0
  145. package/dist-types/vendors/_shared/script-url.d.ts +2 -75
  146. package/dist-types/vendors/ads-and-pixels/linkedin-insights.d.ts +2 -92
  147. package/dist-types/vendors/ads-and-pixels/meta-pixel.d.ts +2 -289
  148. package/dist-types/vendors/ads-and-pixels/microsoft-uet.d.ts +2 -105
  149. package/dist-types/vendors/ads-and-pixels/openai-pixel.d.ts +2 -211
  150. package/dist-types/vendors/ads-and-pixels/pinterest-tag.d.ts +2 -295
  151. package/dist-types/vendors/ads-and-pixels/reddit-pixel.d.ts +2 -210
  152. package/dist-types/vendors/ads-and-pixels/snapchat-pixel.d.ts +2 -171
  153. package/dist-types/vendors/ads-and-pixels/tiktok-pixel.d.ts +2 -106
  154. package/dist-types/vendors/ads-and-pixels/x-pixel.d.ts +2 -183
  155. package/dist-types/vendors/analytics/adobe-analytics.d.ts +2 -75
  156. package/dist-types/vendors/analytics/ahrefs-analytics.d.ts +2 -62
  157. package/dist-types/vendors/analytics/amplitude.d.ts +2 -234
  158. package/dist-types/vendors/analytics/clearbit.d.ts +2 -60
  159. package/dist-types/vendors/analytics/cloudflare-web-analytics.d.ts +2 -67
  160. package/dist-types/vendors/analytics/databuddy.d.ts +2 -147
  161. package/dist-types/vendors/analytics/fathom-analytics.d.ts +2 -90
  162. package/dist-types/vendors/analytics/google-tag.d.ts +2 -95
  163. package/dist-types/vendors/analytics/heap.d.ts +2 -316
  164. package/dist-types/vendors/analytics/hightouch.d.ts +2 -285
  165. package/dist-types/vendors/analytics/hotjar.d.ts +2 -73
  166. package/dist-types/vendors/analytics/logrocket.d.ts +2 -101
  167. package/dist-types/vendors/analytics/matomo-analytics.d.ts +2 -41
  168. package/dist-types/vendors/analytics/microsoft-clarity.d.ts +2 -97
  169. package/dist-types/vendors/analytics/mixpanel-analytics.d.ts +2 -113
  170. package/dist-types/vendors/analytics/one-dollar-stats.d.ts +2 -39
  171. package/dist-types/vendors/analytics/pirsch.d.ts +2 -96
  172. package/dist-types/vendors/analytics/plausible-analytics.d.ts +2 -122
  173. package/dist-types/vendors/analytics/posthog.d.ts +2 -175
  174. package/dist-types/vendors/analytics/promptwatch.d.ts +2 -36
  175. package/dist-types/vendors/analytics/rudderstack.d.ts +2 -330
  176. package/dist-types/vendors/analytics/rybbit-analytics.d.ts +2 -82
  177. package/dist-types/vendors/analytics/segment.d.ts +2 -164
  178. package/dist-types/vendors/analytics/umami-analytics.d.ts +2 -93
  179. package/dist-types/vendors/analytics/vercel-analytics.d.ts +2 -66
  180. package/dist-types/vendors/email-and-sms/klaviyo.d.ts +2 -0
  181. package/dist-types/vendors/functional/crisp.d.ts +2 -78
  182. package/dist-types/vendors/functional/front-chat.d.ts +2 -62
  183. package/dist-types/vendors/functional/intercom.d.ts +2 -135
  184. package/dist-types/vendors/tag-managers/cloudflare-zaraz.d.ts +2 -39
  185. package/dist-types/vendors/tag-managers/google-tag-manager.d.ts +2 -96
  186. package/dist-types/vercel-analytics.d.ts +2 -0
  187. package/dist-types/x-pixel.d.ts +2 -0
  188. package/docs/README.md +129 -63
  189. package/docs/assets/v3/bottom-bar.png +0 -0
  190. package/docs/assets/v3/brand-card.png +0 -0
  191. package/docs/assets/v3/brand-preferences.png +0 -0
  192. package/docs/assets/v3/choice-wall.png +0 -0
  193. package/docs/assets/v3/headless-bar-html.png +0 -0
  194. package/docs/assets/v3/headless-bar-mobile.png +0 -0
  195. package/docs/assets/v3/headless-bar.png +0 -0
  196. package/docs/assets/v3/slim-bar.png +0 -0
  197. package/docs/concepts/choose-your-setup.md +87 -0
  198. package/docs/concepts/consent-categories.md +84 -0
  199. package/docs/{guides → concepts}/consent-state.md +89 -105
  200. package/docs/{guides → concepts}/data-fetching.md +31 -27
  201. package/docs/concepts/how-consent-works.md +123 -0
  202. package/docs/concepts/policies.md +71 -0
  203. package/docs/customization/class-names.md +202 -0
  204. package/docs/customization/dark-mode.md +157 -0
  205. package/docs/customization/motion.md +119 -0
  206. package/docs/customization/overview.md +67 -34
  207. package/docs/customization/recipes.md +839 -49
  208. package/docs/customization/slots.md +216 -35
  209. package/docs/customization/stylesheets.md +147 -0
  210. package/docs/customization/tailwind.md +842 -0
  211. package/docs/customization/tokens.md +163 -96
  212. package/docs/customization/translations.md +60 -3
  213. package/docs/frameworks/astro/embeds.md +160 -0
  214. package/docs/frameworks/astro/network-blocker.md +86 -0
  215. package/docs/frameworks/astro/scripts.md +155 -0
  216. package/docs/frameworks/html/embeds.md +142 -0
  217. package/docs/frameworks/html/network-blocker.md +105 -0
  218. package/docs/frameworks/html/scripts.md +164 -0
  219. package/docs/frameworks/javascript/scripts.md +137 -0
  220. package/docs/frameworks/next/embeds.md +90 -0
  221. package/docs/frameworks/next/network-blocker.md +153 -0
  222. package/docs/frameworks/next/scripts.md +196 -0
  223. package/docs/frameworks/nuxt/embeds.md +81 -0
  224. package/docs/frameworks/nuxt/network-blocker.md +97 -0
  225. package/docs/frameworks/nuxt/scripts.md +89 -0
  226. package/docs/frameworks/react/embeds.md +89 -0
  227. package/docs/frameworks/react/network-blocker.md +140 -0
  228. package/docs/frameworks/react/scripts.md +115 -0
  229. package/docs/frameworks/svelte/embeds.md +96 -0
  230. package/docs/frameworks/svelte/network-blocker.md +141 -0
  231. package/docs/frameworks/svelte/scripts.md +144 -0
  232. package/docs/frameworks/sveltekit/embeds.md +103 -0
  233. package/docs/frameworks/sveltekit/network-blocker.md +159 -0
  234. package/docs/frameworks/sveltekit/scripts.md +172 -0
  235. package/docs/frameworks/tanstack-start/embeds.md +96 -0
  236. package/docs/frameworks/tanstack-start/network-blocker.md +145 -0
  237. package/docs/frameworks/tanstack-start/scripts.md +103 -0
  238. package/docs/frameworks/vue/embeds.md +84 -0
  239. package/docs/frameworks/vue/network-blocker.md +99 -0
  240. package/docs/frameworks/vue/scripts.md +93 -0
  241. package/docs/guides/banner-experiments.md +654 -0
  242. package/docs/guides/troubleshooting.md +120 -47
  243. package/docs/guides/verify-consent.md +81 -49
  244. package/docs/integrations/adobe-analytics.md +167 -159
  245. package/docs/integrations/ahrefs-analytics.md +152 -154
  246. package/docs/integrations/amplitude.md +162 -156
  247. package/docs/integrations/building-integrations.md +136 -37
  248. package/docs/integrations/clearbit.md +154 -154
  249. package/docs/integrations/cloudflare-web-analytics.md +156 -156
  250. package/docs/integrations/cloudflare-zaraz.md +209 -261
  251. package/docs/integrations/crisp.md +164 -158
  252. package/docs/integrations/databuddy.md +157 -173
  253. package/docs/integrations/fathom-analytics.md +158 -156
  254. package/docs/integrations/front-chat.md +167 -167
  255. package/docs/integrations/google-maps.md +118 -83
  256. package/docs/integrations/google-tag-manager.md +178 -163
  257. package/docs/integrations/google-tag.md +163 -160
  258. package/docs/integrations/heap.md +163 -155
  259. package/docs/integrations/hightouch.md +161 -157
  260. package/docs/integrations/hotjar.md +159 -155
  261. package/docs/integrations/intercom.md +183 -153
  262. package/docs/integrations/klaviyo.md +486 -0
  263. package/docs/integrations/linkedin-insights.md +174 -150
  264. package/docs/integrations/logrocket.md +160 -156
  265. package/docs/integrations/matomo-analytics.md +188 -178
  266. package/docs/integrations/meta-pixel.md +188 -150
  267. package/docs/integrations/microsoft-clarity.md +163 -155
  268. package/docs/integrations/microsoft-uet.md +148 -154
  269. package/docs/integrations/mixpanel-analytics.md +155 -160
  270. package/docs/integrations/one-dollar-stats.md +166 -165
  271. package/docs/integrations/openai-pixel.md +204 -301
  272. package/docs/integrations/overview.md +137 -80
  273. package/docs/integrations/pinterest-tag.md +191 -183
  274. package/docs/integrations/pirsch.md +169 -159
  275. package/docs/integrations/plausible-analytics.md +172 -158
  276. package/docs/integrations/posthog.md +313 -240
  277. package/docs/integrations/promptwatch.md +154 -154
  278. package/docs/integrations/reddit-pixel.md +185 -157
  279. package/docs/integrations/rudderstack.md +201 -186
  280. package/docs/integrations/rybbit-analytics.md +171 -160
  281. package/docs/integrations/segment.md +182 -154
  282. package/docs/integrations/snapchat-pixel.md +186 -156
  283. package/docs/integrations/tiktok-pixel.md +171 -150
  284. package/docs/integrations/umami-analytics.md +163 -158
  285. package/docs/integrations/vercel-analytics.md +166 -157
  286. package/docs/integrations/x-pixel.md +176 -150
  287. package/docs/integrations/youtube.md +121 -86
  288. package/docs/upgrade-v3.md +496 -467
  289. package/package.json +10 -257
  290. package/dist-types/__tests__/helpers.d.ts +0 -141
  291. package/docs/assets/v3/brand-bar.png +0 -0
  292. package/docs/assets/v3/mobile-card.png +0 -0
  293. package/docs/assets/v3/preferences.png +0 -0
  294. package/docs/frameworks/javascript/script-loader.md +0 -100
  295. package/docs/frameworks/next/script-loader.md +0 -216
  296. package/docs/frameworks/react/script-loader.md +0 -69
  297. package/docs/guides/deployment-modes.md +0 -75
  298. package/docs/guides/shared-consent-controls.md +0 -158
  299. package/docs/integrations/clear-on-revocation.md +0 -167
  300. 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.