@c15t/scripts 3.0.0-alpha.1 → 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.
Files changed (300) hide show
  1. package/AGENTS.md +129 -59
  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 -137
  13. package/dist/engine/compile.js +2 -89
  14. package/dist/engine/runtime.js +2 -448
  15. package/dist/events.js +2 -0
  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 -392
  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 -0
  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 -66
  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 -0
  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 -56
  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 -0
  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 -59
  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 -0
  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 -458
  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 -0
  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 -93
  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 -0
  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 -158
  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 -0
  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 -94
  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 -59
  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/concepts/consent-state.md +357 -0
  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 -33
  207. package/docs/customization/recipes.md +839 -47
  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 +166 -36
  212. package/docs/customization/translations.md +61 -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 +146 -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 +119 -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 +137 -0
  232. package/docs/frameworks/sveltekit/embeds.md +103 -0
  233. package/docs/frameworks/sveltekit/network-blocker.md +149 -0
  234. package/docs/frameworks/sveltekit/scripts.md +141 -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 +168 -160
  245. package/docs/integrations/ahrefs-analytics.md +153 -155
  246. package/docs/integrations/amplitude.md +163 -157
  247. package/docs/integrations/building-integrations.md +136 -37
  248. package/docs/integrations/clearbit.md +155 -155
  249. package/docs/integrations/cloudflare-web-analytics.md +157 -157
  250. package/docs/integrations/cloudflare-zaraz.md +210 -262
  251. package/docs/integrations/crisp.md +165 -159
  252. package/docs/integrations/databuddy.md +158 -174
  253. package/docs/integrations/fathom-analytics.md +159 -157
  254. package/docs/integrations/front-chat.md +322 -0
  255. package/docs/integrations/google-maps.md +119 -84
  256. package/docs/integrations/google-tag-manager.md +179 -164
  257. package/docs/integrations/google-tag.md +164 -161
  258. package/docs/integrations/heap.md +164 -156
  259. package/docs/integrations/hightouch.md +162 -158
  260. package/docs/integrations/hotjar.md +160 -156
  261. package/docs/integrations/intercom.md +184 -154
  262. package/docs/integrations/klaviyo.md +486 -0
  263. package/docs/integrations/linkedin-insights.md +175 -151
  264. package/docs/integrations/logrocket.md +161 -157
  265. package/docs/integrations/matomo-analytics.md +189 -179
  266. package/docs/integrations/meta-pixel.md +189 -151
  267. package/docs/integrations/microsoft-clarity.md +164 -156
  268. package/docs/integrations/microsoft-uet.md +149 -155
  269. package/docs/integrations/mixpanel-analytics.md +156 -161
  270. package/docs/integrations/one-dollar-stats.md +306 -0
  271. package/docs/integrations/openai-pixel.md +205 -302
  272. package/docs/integrations/overview.md +143 -83
  273. package/docs/integrations/pinterest-tag.md +329 -0
  274. package/docs/integrations/pirsch.md +170 -160
  275. package/docs/integrations/plausible-analytics.md +173 -159
  276. package/docs/integrations/posthog.md +227 -242
  277. package/docs/integrations/promptwatch.md +155 -155
  278. package/docs/integrations/reddit-pixel.md +186 -158
  279. package/docs/integrations/rudderstack.md +202 -187
  280. package/docs/integrations/rybbit-analytics.md +172 -161
  281. package/docs/integrations/segment.md +183 -155
  282. package/docs/integrations/snapchat-pixel.md +187 -157
  283. package/docs/integrations/tiktok-pixel.md +172 -151
  284. package/docs/integrations/umami-analytics.md +164 -159
  285. package/docs/integrations/vercel-analytics.md +167 -158
  286. package/docs/integrations/x-pixel.md +177 -151
  287. package/docs/integrations/youtube.md +122 -87
  288. package/docs/upgrade-v3.md +490 -354
  289. package/package.json +12 -236
  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 -94
  295. package/docs/frameworks/next/script-loader.md +0 -210
  296. package/docs/frameworks/react/script-loader.md +0 -63
  297. package/docs/guides/consent-state.md +0 -60
  298. package/docs/guides/deployment-modes.md +0 -75
  299. package/docs/integrations/clear-on-revocation.md +0 -167
  300. package/docs/integrations/granular-consent.md +0 -208
@@ -1,210 +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
- App Router awaits the prefetch in the `ResolvedConsent` Server Component from
112
- the [App Router guide](https://c15t.com/docs/frameworks/next/app-router) and renders the
113
- wrapper inside it. This partial example is that component; keep the
114
- `Suspense` boundary, `html`, `body` and stylesheet from your existing layout:
115
-
116
- ```tsx
117
- import type { ReactNode } from 'react';
118
- import { resolveConsent } from 'c15t/next/server';
119
- import { consentConfig } from '../c15t.config';
120
- import { Consent } from '../components/consent';
121
-
122
- async function ResolvedConsent({ children }: { children: ReactNode }) {
123
- const state = await resolveConsent({ config: consentConfig });
124
- return <Consent state={state}>{children}</Consent>;
125
- }
126
- ```
127
-
128
- To stream the page shell before consent resolves instead, pass the unawaited
129
- promise from a synchronous layout as described in
130
- [stream the page while consent resolves](https://c15t.com/docs/frameworks/next/app-router#stream-the-page-while-consent-resolves).
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.
@@ -1,63 +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.
@@ -1,60 +0,0 @@
1
- ---
2
- title: Understand consent state
3
- description: Distinguish policy resolution, effective permissions, explicit
4
- choices, notices and privacy signals.
5
- group: guides
6
- ---
7
-
8
- ## Use effective permissions to gate features
9
-
10
- `effectivePermissions` answers whether a category is allowed now. It combines
11
- the resolved policy, stored choices and privacy signals. Under an opt-out rule,
12
- permission can be true before the visitor acts. It is not evidence of a recorded
13
- grant.
14
-
15
- | Task | State or API |
16
- | ------------------------------------------- | ---------------------------------------------------- |
17
- | Load a script or render an optional feature | `effectivePermissions`, React `useConsent(category)` |
18
- | Inspect what the visitor confirmed | `explicitChoice` |
19
- | Decide whether to show a prompt | `promptRequirement` |
20
- | Explain regional behavior | `policyRule` |
21
- | Diagnose initialization | `resolution` |
22
-
23
- ## Record only explicit visitor actions
24
-
25
- ```ts
26
- // Run in the corresponding click or form-submit handler.
27
- await kernel.commands.save('all');
28
- await kernel.commands.save('none');
29
- await kernel.commands.save({ marketing: false });
30
- ```
31
-
32
- These are three separate examples: accept, reject and a partial save. A partial
33
- save confirms only the supplied categories and keeps the other categories'
34
- confirmation times. Do not call all three in one handler.
35
-
36
- `onChoiceRecorded` reports an explicit choice. `onPermissionsChanged` reports
37
- changes in effective permissions, including changes caused by expiry or privacy
38
- signals. Hydration must not be counted as another visitor choice.
39
-
40
- ## Treat notices and privacy signals separately
41
-
42
- `commands.dismissNotice()` acknowledges the current notice. It does not grant
43
- categories or overwrite existing denials. Global Privacy Control, or GPC, is a
44
- browser privacy signal. Its configured restrictions can change permissions
45
- without creating an explicit choice.
46
-
47
- A rule with `prompt: 'none'` can still require a persistent preferences entry
48
- point. Check the policy's rights instead of hiding preferences merely because
49
- the banner is absent. An unresolved rule is another distinct state; optional
50
- permissions stay denied until resolution succeeds.
51
-
52
- ## Preserve records during hydration
53
-
54
- Server helpers return records with policy information and evaluation time.
55
- Forward that configuration intact. Copying an allowed category into a receipt
56
- would invent a grant and lose its original confirmation time.
57
-
58
- Valid v2 records can be read without a startup rewrite. The next explicit action
59
- writes the v3 format. See [migration](../upgrade-v3.md) for expiry, partial saves,
60
- custom transports and backend contract changes.
@@ -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,167 +0,0 @@
1
- ---
2
- title: Clear on revocation
3
- description: Remove configured first-party cookies and Web Storage keys when
4
- their consent category is denied.
5
- group: integrations
6
- ---
7
-
8
- ## Configure cleanup
9
-
10
- Add `clearOnRevocation` to your provider or runtime options. Declare only the
11
- data owned by each optional category:
12
-
13
- ```ts
14
- import { hosted, type ClearOnRevocationConfig } from 'c15t';
15
- import { createConsentRuntime } from 'c15t/runtime';
16
-
17
- const clearOnRevocation = {
18
- measurement: {
19
- cookies: ['_ga', '_ga_*'],
20
- localStorage: ['analytics:*'],
21
- },
22
- marketing: {
23
- cookies: ['_fbp'],
24
- sessionStorage: ['campaign-id'],
25
- },
26
- } satisfies ClearOnRevocationConfig;
27
-
28
- const runtime = createConsentRuntime({
29
- mode: hosted({ url: '/api/c15t' }),
30
- clearOnRevocation,
31
- });
32
-
33
- // Start in the browser after mount. The endpoint must serve your c15t backend.
34
- runtime.start();
35
-
36
- // Call runtime.dispose() when the app no longer needs consent management.
37
- ```
38
-
39
- For React, pass the same configuration through `ConsentProvider.options`:
40
-
41
- ```tsx
42
- import type { ReactNode } from 'react';
43
- import { ConsentProvider, hosted } from 'c15t/react';
44
-
45
- const mode = hosted({ url: '/api/c15t' });
46
-
47
- export function Consent({ children }: { children: ReactNode }) {
48
- return (
49
- <ConsentProvider
50
- options={{
51
- mode,
52
- clearOnRevocation: {
53
- measurement: { cookies: ['_ga', '_ga_*'] },
54
- },
55
- }}
56
- >
57
- {children}
58
- </ConsentProvider>
59
- );
60
- }
61
- ```
62
-
63
- The same option is available in Next.js and TanStack Start `ConsentRoot` props, Vue and
64
- Nuxt configuration, Svelte providers, and Astro integration options. Solid and
65
- other headless integrations can use `createConsentRuntime` as shown above.
66
- Every adapter uses the same cleanup module.
67
-
68
- Omitting `clearOnRevocation` leaves cleanup disabled. The provider option is
69
- initial-only. Remount the provider to replace its cleanup configuration. For
70
- a shared runtime, configure the runtime owner rather than a borrowing provider.
71
-
72
- ## Matching names and cookie scopes
73
-
74
- Use an exact string or a nonempty prefix followed by `*`. `_ga_*` matches
75
- `_ga_ABC123`; it does not match `_ga`. Regular expressions, wildcards in other
76
- positions, and a bare `*` are unsupported. Web Storage keys may contain spaces,
77
- Unicode, and punctuation. Cookie names use their raw spelling, without URL
78
- decoding.
79
-
80
- Cookies can share a name while having different domains or paths. Cleanup
81
- tries the current host and its parent domains, and the current path and its
82
- ancestors. To target a specific scope, use an object:
83
-
84
- ```ts
85
- const clearOnRevocation = {
86
- measurement: {
87
- cookies: [
88
- { name: 'analytics-id', domain: 'example.com', path: '/' },
89
- { name: 'checkout-metrics', domain: '', path: '/checkout' },
90
- { name: 'partitioned-metrics', partitioned: true },
91
- ],
92
- },
93
- };
94
- ```
95
-
96
- An empty `domain` means host-only. Explicit domains and paths replace the
97
- automatic attempts for that field. Exact names can be deleted at a configured
98
- path even when the current page cannot read that cookie. Prefix matching can
99
- only discover cookie names visible to the current page, so use an exact name
100
- for a cookie on another path.
101
-
102
- Partitioned cookies require `partitioned: true`; ordinary targets remove
103
- unpartitioned cookies. Cookie deletion preserves the browser's `__Secure-`
104
- and `__Host-` prefix requirements. c15t protects its own consent, notice,
105
- privacy, pending-save, and IAB consent records in cookies and localStorage,
106
- including configured custom storage keys, even if your patterns match them.
107
- c15t does not store consent in sessionStorage, so targeted entries there are
108
- removed even when their names match consent storage keys.
109
-
110
- ## When cleanup runs
111
-
112
- The runtime attaches cleanup after persistence and the script loader. Cleanup
113
- waits while the policy is pending. On the first settled snapshot, it removes
114
- configured data for every denied category. This includes a new opt-in visitor
115
- who has not made a choice and a returning visitor whose permission expired.
116
-
117
- After that first pass, cleanup runs when a category changes from allowed to
118
- denied. Saving a refusal, expiry, a policy change, Global Privacy Control,
119
- or synchronized records can cause that transition. Under an opt-out policy,
120
- an expired grant that remains effectively allowed does not trigger deletion.
121
- The `necessary` category cannot be configured for cleanup.
122
-
123
- Cleanup keeps waiting if a failed initial request leaves the policy pending.
124
- If a previously settled policy falls back to denial after an initialization
125
- failure, cleanup removes its configured data. A later successful retry cannot
126
- restore deleted data.
127
-
128
- Runtime construction, server rendering, draft checkbox edits, opening the
129
- dialog, and disposal do not clear data. Cleanup does not poll storage or repeat
130
- on unrelated UI updates.
131
-
132
- ## Use an existing kernel
133
-
134
- For a manually assembled integration, attach the module in the browser after
135
- persistence hydration and script-loader setup:
136
-
137
- ```ts
138
- import { createClearOnRevocation } from 'c15t/modules/clear-on-revocation';
139
-
140
- const cleanup = createClearOnRevocation({
141
- kernel,
142
- config: { measurement: { cookies: ['_ga', '_ga_*'] } },
143
- storageConfig,
144
- });
145
-
146
- // Stop observing consent when this integration is torn down.
147
- cleanup.dispose();
148
- ```
149
-
150
- Here `kernel` is your existing consent kernel. Pass the same `storageConfig`
151
- used by persistence so cleanup protects custom record keys. Attaching the
152
- module can immediately clear denied categories if the policy is already
153
- settled. Do not also attach it when your provider or runtime owns cleanup.
154
-
155
- ## Browser limits
156
-
157
- Cleanup can remove JavaScript-accessible first-party cookies and keys in the
158
- current origin's `localStorage` and `sessionStorage`. It cannot remove
159
- `HttpOnly` cookies or another origin's data. Keep `HttpOnly` protections and
160
- use your server to expire cookies that require server access. Cookie deletion
161
- must match the cookie's scope. See the
162
- [browser cookie documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies).
163
-
164
- Browser restrictions can prevent reads or deletions. Cleanup failures do not
165
- block consent updates. A running SDK may write data again after a sweep, so
166
- keep script gating and the integration's consent-change or teardown behavior
167
- configured. Deleting a script element cannot undo JavaScript it already ran.