@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.
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 +71 -101
  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 +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 +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 +226 -241
  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 +475 -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,40 +1,42 @@
1
1
  ---
2
2
  title: Google Tag
3
- description: Configure gtag with c15t Consent Mode signals and understand its
4
- loading behavior.
3
+ description: Load gtag.js for Google Analytics or Google Ads with c15t Consent
4
+ Mode v2 signals, and verify the consent commands in DevTools.
5
+ icon: google-analytics
5
6
  group: integrations
6
7
  ---
7
8
 
8
- ## Register gtag
9
+ ## Configure the Google tag
9
10
 
10
- | Package manager | Command |
11
- | :-------------- | :-------------------------- |
12
- | npm | `npm install @c15t/scripts` |
13
- | pnpm | `pnpm add @c15t/scripts` |
14
- | yarn | `yarn add @c15t/scripts` |
15
- | bun | `bun add @c15t/scripts` |
11
+ Copy the tag ID, for example `G-XXXXXXXXXX` for Google Analytics or
12
+ `AW-XXXXXXXXX` for Google Ads. Remove any `gtag.js` snippet already in your
13
+ HTML and any tag-manager entry that loads the same tag.
14
+
15
+ | Package manager | Command |
16
+ | :-------------- | :------------------------------------- |
17
+ | npm | `npm install @c15t/integrations@alpha` |
18
+ | pnpm | `pnpm add @c15t/integrations@alpha` |
19
+ | yarn | `yarn add @c15t/integrations@alpha` |
20
+ | bun | `bun add @c15t/integrations@alpha` |
16
21
 
17
22
  ```ts title="src/consent-scripts.ts"
18
- import { gtag } from '@c15t/scripts/google-tag';
23
+ import { gtag } from '@c15t/integrations/google-tag';
19
24
 
20
25
  export const scripts = [gtag({ id: 'G-XXXXXXXXXX', category: 'measurement' })];
21
26
  ```
22
27
 
23
- Use your Google tag ID and pass `scripts` to the existing provider options.
24
- Choose `marketing` for a configuration whose purpose is advertising. The
25
- category describes the integration but does not override `alwaysLoad`.
26
- Remove a separately installed `gtag.js` snippet or a duplicate tag-manager
27
- configuration before testing.
28
-
29
28
  ## Register the scripts
30
29
 
31
30
  Complete your [framework quickstart](https://c15t.com/docs/frameworks) first. Keep its Inth
32
31
  endpoint, policy, styles and consent UI. Remove the vendor's original script,
33
- SDK initializer or tag-manager entry so c15t owns loading once.
32
+ SDK initializer or tag-manager entry, so the vendor loads only through c15t.
34
33
 
35
- The `scripts` export in `src/consent-scripts.ts` is a configuration, not an
36
- initializer. Add it to your existing consent owner using the registration point
37
- below. These are partial edits to that owner, not additional providers.
34
+ The vendor pages put the helper in `src/consent-scripts.ts`. If your framework
35
+ quickstart already created a scripts file, such as `lib/scripts.ts` in the
36
+ Next.js guide, add the helper to that array instead of creating a second file.
37
+ The `scripts` export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
38
+ point for your framework below. These are edits to that provider, not a second
39
+ provider.
38
40
 
39
41
  **Next.js**
40
42
 
@@ -55,158 +57,106 @@ router guide. Its manifest, init and save URLs stay in effect. Add
55
57
  </ConsentRoot>
56
58
  ```
57
59
 
58
- For a Pages Router or static-export setup using `ConsentProvider`, add
59
- `scripts` to its existing `options` instead. Keep the router-specific setup
60
- from [Next.js script loading](../frameworks/next/script-loader.md).
60
+ App Router, Pages Router and static export all use this `ConsentRoot` in
61
+ the `'use client'` wrapper `components/consent.tsx`. Keep `scripts` there,
62
+ because a Server Component cannot pass script callbacks to it. See
63
+ [Next.js scripts and embeds](../frameworks/next/scripts.md).
61
64
 
62
65
  **TanStack Start**
63
66
 
64
- In your existing root route component, import the scripts alongside
65
- `ConsentRoot`. Keep the server loader from the [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart).
67
+ Import the configuration into your root route and pass it to the existing
68
+ `ConsentRoot` as a top-level prop. Keep the loader, `backendURL` and
69
+ `initRoute` from the [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart):
66
70
 
67
- ```tsx
68
- import { Outlet } from '@tanstack/react-router';
69
- import { ConsentRoot } from 'c15t/tanstack-start';
71
+ ```tsx title="src/routes/__root.tsx"
70
72
  import { scripts } from '../consent-scripts';
71
73
 
72
- function Root() {
73
- const state = Route.useLoaderData();
74
- return (
75
- <ConsentRoot state={state} backendURL={backendURL} initRoute={false} scripts={scripts}>
76
- <Outlet />
77
- {/* Keep your consent banner, dialog and preferences link here. */}
78
- </ConsentRoot>
79
- );
80
- }
74
+ <ConsentRoot
75
+ state={consent}
76
+ backendURL={backendURL}
77
+ initRoute={false}
78
+ scripts={scripts}
79
+ >
81
80
  ```
82
81
 
83
- This edits the existing route. `Route` and `backendURL` come from its setup;
84
- keep the document shell and head components if they are part of your root.
85
- `initRoute={false}` keeps the quickstart's direct-backend initialization.
86
- If your app mounts a consent server route, retain its existing `initRoute`
87
- instead. Do not return script callbacks from a server function or route loader.
82
+ Import vendor helpers in the root route module, not in a server function.
83
+ A server function's return value must be serializable, and script
84
+ configurations carry callbacks. See
85
+ [TanStack Start scripts](../frameworks/tanstack-start/scripts.md).
88
86
 
89
87
  **React**
90
88
 
91
- Import the scripts into your existing provider component:
89
+ Add the configuration to the existing `ConsentProvider` options, next to
90
+ `mode`:
92
91
 
93
- ```ts
94
- import { ConsentProvider } from 'c15t/react';
92
+ ```tsx title="src/consent.tsx"
95
93
  import { scripts } from './consent-scripts';
96
- ```
97
94
 
98
- Keep the existing options and add `scripts`:
99
-
100
- ```tsx
101
- <ConsentProvider options={{ ...consentOptions, scripts }}>
102
- {children}
103
- </ConsentProvider>
95
+ <ConsentProvider options={{ mode, scripts }}>
104
96
  ```
105
97
 
106
- Here `consentOptions` is your existing configuration, including
107
- `mode: hosted({ url: backendURL })`. Keep the banner, dialog and preferences
108
- link inside the provider. See [React script loading](../frameworks/react/script-loader.md).
98
+ `mode` is the `hosted({ url: 'https://your-project.inth.app' })` value
99
+ from the [React quickstart](https://c15t.com/docs/frameworks/react/quickstart). Keep the banner,
100
+ dialog and preferences link inside the provider. See
101
+ [React scripts and embeds](../frameworks/react/scripts.md).
109
102
 
110
103
  **Nuxt**
111
104
 
112
- Attach one loader from the root `app.vue`, after the Nuxt module has
113
- started its browser runtime. This keeps vendor callbacks in application code rather
114
- than serialized `nuxt.config.ts` runtime configuration.
105
+ Register the scripts under the `c15t` key in `app/app.config.ts`. Adjust the
106
+ relative import to where you created `consent-scripts.ts`:
115
107
 
116
- ```vue title="app/app.vue"
117
- <script setup lang="ts">
118
- import { onUnmounted } from 'vue';
119
- import { createScriptLoader } from 'c15t/modules/script-loader';
108
+ ```ts title="app/app.config.ts"
120
109
  import { scripts } from '../src/consent-scripts';
121
110
 
122
- const nuxtApp = useNuxtApp();
123
- const kernel = useConsentKernel();
124
- let loader: ReturnType<typeof createScriptLoader> | undefined;
125
-
126
- const removeMountedHook = nuxtApp.hook('app:mounted', () => {
127
- loader = createScriptLoader({ kernel, scripts });
111
+ export default defineAppConfig({
112
+ c15t: { scripts },
128
113
  });
129
- onUnmounted(() => {
130
- removeMountedHook();
131
- loader?.dispose();
132
- });
133
- </script>
134
-
135
- <template>
136
- <ConsentRoot />
137
- <NuxtPage />
138
- </template>
139
114
  ```
140
115
 
141
- Merge the setup code into your root and retain its footer and preferences
142
- link. `useConsentKernel` is auto-imported by the c15t Nuxt module. Adjust the
143
- relative script import if your `app.vue` is at the project root. This loader
144
- waits until the module has applied browser persistence and privacy signals,
145
- then reads the current snapshot and observes future changes. Do not also register these scripts
146
- in another loader. See the [Nuxt quickstart](https://c15t.com/docs/frameworks/nuxt/quickstart).
116
+ The Nuxt module merges this over its options in `nuxt.config.ts` and starts
117
+ one script loader in the browser after hydration, once it has applied the
118
+ visitor's stored choice and privacy signals. Keep `scripts` out of
119
+ `nuxt.config.ts`, which reaches the browser as JSON and drops the vendor
120
+ callbacks. Write the vendor IDs into `consent-scripts.ts`. See
121
+ [Nuxt scripts and embeds](../frameworks/nuxt/scripts.md).
147
122
 
148
123
  **Vue**
149
124
 
150
- Use the kernel already provided by the Vue plugin. Merge this setup into
151
- `App.vue`, whose lifetime covers the application:
125
+ Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
152
126
 
153
- ```vue title="src/App.vue"
154
- <script setup lang="ts">
155
- import { onMounted, onUnmounted } from 'vue';
156
- import { createScriptLoader } from 'c15t/modules/script-loader';
157
- import { useConsentKernel } from 'c15t/vue/vue-plugin';
158
- import ConsentRoot from 'c15t/vue/consent-root';
127
+ ```ts title="src/main.ts"
159
128
  import { scripts } from './consent-scripts';
160
129
 
161
- const kernel = useConsentKernel();
162
- let loader: ReturnType<typeof createScriptLoader> | undefined;
163
-
164
- onMounted(() => {
165
- loader = createScriptLoader({ kernel, scripts });
130
+ app.use(c15tVue, {
131
+ backendURL: 'https://your-project.inth.app',
132
+ scripts,
166
133
  });
167
- onUnmounted(() => loader?.dispose());
168
- </script>
169
-
170
- <template>
171
- <ConsentRoot />
172
- <main>Your application</main>
173
- </template>
174
134
  ```
175
135
 
176
- Keep your existing page content and preferences link. The plugin still owns
177
- the kernel and persistence; this component owns only the vendor loader.
178
- Do not register the same scripts in plugin configuration as well. See the
179
- [Vue quickstart](https://c15t.com/docs/frameworks/vue/quickstart).
136
+ Keep your existing backend URL and other options. The plugin starts one
137
+ script loader when the app mounts, after it has applied the visitor's stored
138
+ choice. Do not also call `createScriptLoader` from a component. See
139
+ [Vue scripts and embeds](../frameworks/vue/scripts.md).
180
140
 
181
141
  **Astro**
182
142
 
183
- Point the existing Astro integration at a client module. Keep its `mode`,
184
- `ui` and framework integration from the [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart).
185
- Import `fileURLToPath` in your Astro configuration:
186
-
187
- ```js title="astro.config.mjs"
188
- import { fileURLToPath } from 'node:url';
189
- ```
190
-
191
- Add this option to the existing `c15t({ ... })` call. Resolve the path from
192
- the configuration file because Astro injects the import into a virtual module:
193
-
194
- ```js
195
- clientEntrypoint: fileURLToPath(new URL('./src/c15t.client.ts', import.meta.url)),
196
- ```
143
+ Add the scripts to the client entrypoint from the
144
+ [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart), the module that the
145
+ integration's `clientEntrypoint` option names. Keep `mode`, `ui` and the
146
+ framework integration in `astro.config.mjs` as they are. If the module
147
+ already exports scripts, combine the two arrays.
197
148
 
198
- Export the scripts from that module:
199
-
200
- ```ts title="src/c15t.client.ts"
149
+ ```ts title="src/consent-client.ts"
201
150
  import type { C15tClientOptionsExtension } from 'c15t/astro';
202
151
  import { scripts } from './consent-scripts';
203
152
 
204
153
  export default { scripts } satisfies C15tClientOptionsExtension;
205
154
  ```
206
155
 
207
- The integration passes this extension to its shared browser runtime. Vendor
208
- helpers contain callbacks, so do not put them in the serialized `scripts`
209
- option in `astro.config.mjs`. Keep one runtime across consent islands and
156
+ Vendor helpers contain callbacks, and the integration options in
157
+ `astro.config.mjs` are serialized into the page, so do not put helpers in
158
+ the integration's `scripts` option. The integration passes the client
159
+ entrypoint to the one runtime every page shares, including across
210
160
  `ClientRouter` navigation.
211
161
 
212
162
  **Svelte**
@@ -219,9 +169,7 @@ pass them as a top-level prop:
219
169
  import { ConsentManagerProvider, hosted } from '@c15t/svelte';
220
170
  import { scripts } from './consent-scripts';
221
171
 
222
- const backendURL = import.meta.env.VITE_C15T_BACKEND_URL;
223
- if (!backendURL) throw new Error('Set VITE_C15T_BACKEND_URL');
224
- const mode = hosted({ url: backendURL });
172
+ const mode = hosted({ url: 'https://your-project.inth.app' });
225
173
  </script>
226
174
 
227
175
  <ConsentManagerProvider {mode} {scripts}>
@@ -243,7 +191,7 @@ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.
243
191
  import { scripts } from '../consent-scripts';
244
192
 
245
193
  let { children, data } = $props();
246
- const mode = hosted({ url: data.backendURL });
194
+ const mode = hosted({ url: 'https://your-project.inth.app' });
247
195
  </script>
248
196
 
249
197
  <ConsentManagerProvider {mode} {scripts} prefetch={data.prefetch}>
@@ -252,37 +200,75 @@ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.
252
200
  </ConsentManagerProvider>
253
201
  ```
254
202
 
255
- Import vendor helpers in the layout component, not in `+layout.server.ts`.
256
- For static hosting, keep your browser-only `mode` setup and omit request
257
- prefetch; the `scripts` prop stays the same. If you pass an externally owned
203
+ Import vendor helpers in the layout component, not in `+layout.server.ts`:
204
+ a server load cannot send functions to the browser. Prerendered, static and
205
+ SPA-mode pages use the same `scripts` prop. If you pass an externally owned
258
206
  `runtime` to the provider, register scripts when creating that runtime instead.
259
207
 
208
+ **HTML**
209
+
210
+ The helpers in `@c15t/integrations` are ES modules that need a bundler. On a
211
+ page that loads the c15t script tag, paste the vendor's own snippet instead
212
+ and keep it inert until its category is allowed:
213
+
214
+ ```html
215
+ <script type="text/plain" data-c15t-category="measurement">
216
+ // The vendor's snippet, unchanged
217
+ </script>
218
+ ```
219
+
220
+ Use the category this guide names for the vendor. c15t runs the snippet
221
+ once that category is allowed, and reloads the page when the visitor
222
+ withdraws it. Helper options on this page, such as `loadMode`, do not apply
223
+ to a pasted snippet. See [HTML scripts](../frameworks/html/scripts.md).
224
+
260
225
  **JavaScript**
261
226
 
262
- Attach the loader to your existing kernel before calling
263
- `kernel.commands.init()`:
227
+ Pass the scripts to `init()` from `@c15t/browser`, next to your backend
228
+ URL:
264
229
 
265
230
  ```ts
266
- import { createScriptLoader } from 'c15t/modules/script-loader';
231
+ import { init } from '@c15t/browser';
267
232
  import { scripts } from './consent-scripts';
268
233
 
269
- const loader = createScriptLoader({ kernel, scripts });
234
+ const consent = init({
235
+ backendURL: 'https://your-project.inth.app',
236
+ scripts,
237
+ });
270
238
  ```
271
239
 
272
- Call `loader.dispose()` when that application instance is destroyed.
273
- `kernel` is the hosted kernel from your quickstart. A provider-owned kernel
274
- already has a loader; do not attach a second one. See
275
- [JavaScript script loading](../frameworks/javascript/script-loader.md).
240
+ Keep the backend URL from your quickstart. With
241
+ `createConsentRuntime` from `c15t/runtime`, pass `scripts` to it instead.
242
+ A kernel you create yourself needs a loader from
243
+ `c15t/modules/script-loader`. Attach one loader per kernel. See
244
+ [JavaScript scripts](../frameworks/javascript/scripts.md).
245
+
246
+ ## Options
247
+
248
+ | Option | Default | Behavior |
249
+ | ---------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
250
+ | `id` | Required | Tag ID passed to `gtag('config', ...)` and the loader URL. The helper trims it. Empty or whitespace-only values throw. |
251
+ | `category` | Required | `measurement` for Analytics, `marketing` for Ads and Floodlight. It sets the script's permission, which callbacks receive, but does not delay loading. |
252
+ | `config` | None | Parameters passed as the third argument to `gtag('config', id, config)`. |
253
+ | `consentMapping` | The table below | Replaces the category-to-Google mapping. |
276
254
 
277
- ## Consent Mode is not a zero-request gate
255
+ The deprecated `script` option overrides fields of the returned script. Use the
256
+ options above instead.
278
257
 
279
- This helper sets `alwaysLoad: true`. It prepares the Google queue, sends consent
280
- defaults and updates, and loads Google's script even before a visitor makes a
281
- choice. That is different from preventing any request to Google until consent.
282
- Google describes the distinction in its
258
+ ## Google loads before a choice
259
+
260
+ The `googleTagManager` and `gtag` helpers set `alwaysLoad: true`. Before the
261
+ visitor chooses, the helper creates the `dataLayer` queue, sends
262
+ `gtag('consent', 'default', ...)` with the current permissions and loads
263
+ Google's script. After each permission change it sends
264
+ `gtag('consent', 'update', ...)`. Google's tags then adjust what they store and
265
+ send; see Google's
283
266
  [Consent Mode overview](https://developers.google.com/tag-platform/security/concepts/consent-mode).
284
267
 
285
- The default mapping is:
268
+ So the browser does contact Google before consent. If your policy requires no
269
+ Google request until the visitor allows it, do not use these helpers unchanged.
270
+
271
+ ## How categories map to Google consent types
286
272
 
287
273
  | c15t category | Google consent types |
288
274
  | --------------- | -------------------------------------------------- |
@@ -292,14 +278,31 @@ The default mapping is:
292
278
  | `marketing` | `ad_storage`, `ad_user_data`, `ad_personalization` |
293
279
  | `experience` | `personalization_storage` |
294
280
 
295
- `consentMapping` replaces the mapping when supplied. Keep the full set of
296
- signals your integration needs. Test both default and update commands and the
297
- actual tag behavior. Do not infer a saved grant from an allowed default under an
298
- opt-out policy.
299
-
300
- ## Test event delivery
301
-
302
- Confirm the initial consent command precedes configuration and event commands.
303
- Then reject, grant and revoke permission and inspect updates. Test page-view
304
- behavior during client navigation so a separate routing integration does not
305
- send duplicate events or bypass your chosen consent behavior.
281
+ Each Google type is `granted` when its category is allowed and `denied`
282
+ otherwise. If a visitor turns off the helper's vendor, every optional type is
283
+ sent as `denied`. The `consentMapping` option replaces the whole table, so
284
+ include every category you still want signalled.
285
+
286
+ Under an opt-out policy, the default command can grant types before the
287
+ visitor has chosen anything. That is a permission, not a recorded choice.
288
+
289
+ ## Verify the Google tag
290
+
291
+ These checks are for the `gtag` helper, which loads before a choice on
292
+ purpose. On a plain HTML page with the script tag, you gate Google's snippet
293
+ instead and it loads only after consent; see
294
+ [HTML scripts](../frameworks/html/scripts.md#google-consent-mode-and-tag-managers).
295
+
296
+ 1. In a private window with an opt-in policy, load the page. `gtag/js` loads.
297
+ In Google Tag Assistant, the `consent` `default` command comes before
298
+ `config`, with `analytics_storage` and `ad_storage` set to `denied`.
299
+ 2. Open Privacy settings and allow the tag's category. Tag Assistant shows an
300
+ `update` command that grants the mapped types.
301
+ 3. Turn the category off again and save. c15t reloads the page, and the new
302
+ page starts with those types denied.
303
+ 4. With client-side navigation, check that each route change sends one page
304
+ view. A separate router integration that also sends `page_view` doubles
305
+ the count.
306
+
307
+ See the [consent verification guide](../guides/verify-consent.md) for hosting
308
+ checks.