@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,31 +1,31 @@
1
1
  ---
2
- title: Overview
2
+ title: Integrations
3
3
  description: Find all c15t integrations for analytics, tag managers,
4
- advertising, chat and embedded content.
4
+ advertising, email and SMS, chat and embedded content.
5
5
  group: integrations
6
6
  ---
7
7
 
8
8
  ## Choose an integration
9
9
 
10
- Use the vendor helper from `@c15t/scripts` with your existing c15t provider or
11
- script loader. Every helper returns a script configuration; importing one does
12
- not install the vendor. Start with your [framework quickstart](https://c15t.com/docs/frameworks)
13
- to connect Inth and render consent UI, then follow the vendor guide.
10
+ Each vendor helper in `@c15t/integrations` returns a script configuration that you
11
+ register with your c15t provider. Importing a helper installs nothing on its
12
+ own. Set up consent with your [framework quickstart](https://c15t.com/docs/frameworks) first,
13
+ then follow the vendor guide.
14
14
 
15
- | Package manager | Command |
16
- | :-------------- | :-------------------------- |
17
- | npm | `npm install @c15t/scripts` |
18
- | pnpm | `pnpm add @c15t/scripts` |
19
- | yarn | `yarn add @c15t/scripts` |
20
- | bun | `bun add @c15t/scripts` |
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` |
21
21
 
22
- `@c15t/scripts` is a separate add-on. Keep the main `c15t` package for imports
23
- such as `c15t/react` and `c15t/next`.
22
+ `@c15t/integrations` is a separate package. Keep importing c15t itself from `c15t`,
23
+ for example `c15t/react` or `c15t/next`.
24
24
 
25
- Browse integrations by service type below. The tables distinguish helpers that
26
- wait for permission from helpers
27
- that load immediately and send consent signals. Read the vendor's revocation
28
- behavior before choosing either approach.
25
+ The Loading behavior column shows when each helper requests the vendor. Most
26
+ wait for the category to be allowed. A few load on every page and pass the
27
+ permission to the vendor's own consent API, so the browser contacts the vendor
28
+ before a choice.
29
29
 
30
30
  ## Embeds
31
31
 
@@ -36,77 +36,137 @@ behavior before choosing either approach.
36
36
 
37
37
  Both guides include all nine framework examples. React and Svelte use `ConsentGate`;
38
38
  Vue conditionally renders the iframe, and Astro and JavaScript use the existing
39
- kernel to control its DOM lifecycle. Embeds do not require `@c15t/scripts`.
39
+ kernel to control its DOM lifecycle. Embeds do not require `@c15t/integrations`.
40
40
 
41
41
  ## Tag managers
42
42
 
43
- | Integration | Helper | Category | Loading behavior |
44
- | --------------------------------------------- | ------------------ | ----------- | ------------------------------------------------ |
45
- | [Cloudflare Zaraz](./cloudflare-zaraz.md) | `cloudflareZaraz` | `necessary` | Synchronizes purposes; Zaraz owns tool execution |
46
- | [Google Tag Manager](./google-tag-manager.md) | `googleTagManager` | `necessary` | Always loads; signals Google consent |
43
+ | Integration | Helper | Category | Loading behavior |
44
+ | --------------------------------------------- | ------------------ | ----------- | ------------------------------------------------- |
45
+ | [Cloudflare Zaraz](./cloudflare-zaraz.md) | `cloudflareZaraz` | `necessary` | Always runs; syncs purposes, Zaraz runs the tools |
46
+ | [Google Tag Manager](./google-tag-manager.md) | `googleTagManager` | `necessary` | Always loads; signals Google consent |
47
47
 
48
48
  ## Analytics
49
49
 
50
- | Integration | Helper | Category | Loading behavior |
51
- | --------------------------------------------------------- | ------------------------ | -------------------------- | -------------------------------------------------------- |
52
- | [Google Tag](./google-tag.md) | `gtag` | `measurement or marketing` | Always loads; signals Google consent |
53
- | [Ahrefs Analytics](./ahrefs-analytics.md) | `ahrefsAnalytics` | `measurement` | Waits for effective permission |
54
- | [Adobe Analytics](./adobe-analytics.md) | `adobeAnalytics` | `measurement` | Waits for effective permission |
55
- | [Amplitude](./amplitude.md) | `amplitude` | `measurement` | Waits for effective permission |
56
- | [Cloudflare Web Analytics](./cloudflare-web-analytics.md) | `cloudflareWebAnalytics` | `measurement` | Waits for effective permission |
57
- | [Clearbit](./clearbit.md) | `clearbit` | `marketing` | Waits for effective permission |
58
- | [Microsoft Clarity](./microsoft-clarity.md) | `clarity` | `measurement` | Gated initially; retains SDK and signals storage consent |
59
- | [Databuddy](./databuddy.md) | `databuddy` | `measurement` | Always loads; switches SDK configuration |
60
- | [Fathom Analytics](./fathom-analytics.md) | `fathomAnalytics` | `measurement` | Waits for effective permission |
61
- | [Heap](./heap.md) | `heap` | `measurement` | Waits for effective permission |
62
- | [Matomo Analytics](./matomo-analytics.md) | `matomoAnalytics` | `measurement` | Gated by default; optional consent mode |
63
- | [Mixpanel](./mixpanel-analytics.md) | `mixpanelAnalytics` | `measurement` | Always loads; calls opt-in and opt-out APIs |
64
- | [Hotjar](./hotjar.md) | `hotjar` | `measurement` | Waits for effective permission |
65
- | [Hightouch](./hightouch.md) | `hightouch` | `measurement` | Waits for effective permission |
66
- | [LogRocket](./logrocket.md) | `logRocket` | `measurement` | Waits for effective permission |
67
- | [Plausible Analytics](./plausible-analytics.md) | `plausibleAnalytics` | `measurement` | Waits for effective permission |
68
- | [PostHog](./posthog.md) | `posthog` | `measurement` | Configurable; default always loads |
69
- | [Promptwatch](./promptwatch.md) | `promptwatch` | `measurement` | Waits for effective permission |
70
- | [Pirsch](./pirsch.md) | `pirsch` | `measurement` | Waits for effective permission |
71
- | [RudderStack](./rudderstack.md) | `rudderstack` | `measurement` | Gated by default; optional destination consent mode |
72
- | [Segment](./segment.md) | `segment` | `measurement` | Waits for effective permission |
73
- | [Rybbit Analytics](./rybbit-analytics.md) | `rybbitAnalytics` | `measurement` | Waits for effective permission |
74
- | [Umami Analytics](./umami-analytics.md) | `umamiAnalytics` | `measurement` | Waits for effective permission |
75
- | [Vercel Analytics](./vercel-analytics.md) | `vercelAnalytics` | `measurement` | Waits for effective permission |
76
-
77
- ## Functionality
78
-
79
- | Integration | Helper | Category | Loading behavior |
80
- | ------------------------- | ---------- | --------------- | ------------------------------ |
81
- | [Crisp](./crisp.md) | `crisp` | `functionality` | Waits for effective permission |
82
- | [Intercom](./intercom.md) | `intercom` | `functionality` | Waits for effective permission |
50
+ | Integration | Helper | Category | Loading behavior |
51
+ | --------------------------------------------------------- | ------------------------ | ---------------------------- | ---------------------------------------------------------------------------- |
52
+ | [Google Tag](./google-tag.md) | `gtag` | `measurement` or `marketing` | Always loads; signals Google consent |
53
+ | [Ahrefs Analytics](./ahrefs-analytics.md) | `ahrefsAnalytics` | `measurement` | Waits for effective permission |
54
+ | [Adobe Analytics](./adobe-analytics.md) | `adobeAnalytics` | `measurement` | Waits for effective permission |
55
+ | [Amplitude](./amplitude.md) | `amplitude` | `measurement` | Waits for effective permission; opts the SDK out on revocation |
56
+ | [Cloudflare Web Analytics](./cloudflare-web-analytics.md) | `cloudflareWebAnalytics` | `measurement` | Waits for effective permission |
57
+ | [Clearbit](./clearbit.md) | `clearbit` | `marketing` | Waits for effective permission |
58
+ | [Microsoft Clarity](./microsoft-clarity.md) | `clarity` | `measurement` | Gated initially; keeps the SDK and signals storage consent |
59
+ | [Databuddy](./databuddy.md) | `databuddy` | `measurement` | Always loads; switches the SDK's disabled flag |
60
+ | [Fathom Analytics](./fathom-analytics.md) | `fathomAnalytics` | `measurement` | Waits for effective permission |
61
+ | [Heap](./heap.md) | `heap` | `measurement` | Waits for effective permission |
62
+ | [Matomo Analytics](./matomo-analytics.md) | `matomoAnalytics` | `measurement` | Gated by default; optional consent mode |
63
+ | [Mixpanel](./mixpanel-analytics.md) | `mixpanelAnalytics` | `measurement` | Always loads; calls opt-in and opt-out APIs |
64
+ | [OneDollarStats](./one-dollar-stats.md) | `oneDollarStats` | `measurement` | Waits for effective permission |
65
+ | [Hotjar](./hotjar.md) | `hotjar` | `measurement` | Waits for effective permission |
66
+ | [Hightouch](./hightouch.md) | `hightouch` | `measurement` | Waits for effective permission |
67
+ | [LogRocket](./logrocket.md) | `logRocket` | `measurement` | Waits for effective permission |
68
+ | [Plausible Analytics](./plausible-analytics.md) | `plausibleAnalytics` | `measurement` | Waits for effective permission |
69
+ | [PostHog](./posthog.md) | `posthog` | `measurement` | Configurable; defaults to always loading and calling opt-in and opt-out APIs |
70
+ | [Promptwatch](./promptwatch.md) | `promptwatch` | `measurement` | Waits for effective permission |
71
+ | [Pirsch](./pirsch.md) | `pirsch` | `measurement` | Waits for effective permission |
72
+ | [RudderStack](./rudderstack.md) | `rudderstack` | `measurement` | Gated by default; optional destination consent mode |
73
+ | [Segment](./segment.md) | `segment` | `measurement` | Waits for effective permission |
74
+ | [Rybbit Analytics](./rybbit-analytics.md) | `rybbitAnalytics` | `measurement` | Waits for effective permission |
75
+ | [Umami Analytics](./umami-analytics.md) | `umamiAnalytics` | `measurement` | Waits for effective permission |
76
+ | [Vercel Analytics](./vercel-analytics.md) | `vercelAnalytics` | `measurement` | Waits for effective permission |
77
+
78
+ ## Chat and support
79
+
80
+ | Integration | Helper | Category | Loading behavior |
81
+ | ----------------------------- | ----------- | --------------- | ------------------------------ |
82
+ | [Crisp](./crisp.md) | `crisp` | `functionality` | Waits for effective permission |
83
+ | [Front Chat](./front-chat.md) | `frontChat` | `functionality` | Waits for effective permission |
84
+ | [Intercom](./intercom.md) | `intercom` | `functionality` | Waits for effective permission |
85
+
86
+ ## Email and SMS
87
+
88
+ | Integration | Helper | Category | Loading behavior |
89
+ | ----------------------- | --------- | ----------------------------- | ---------------------------------------------------------- |
90
+ | [Klaviyo](./klaviyo.md) | `klaviyo` | `marketing` and `measurement` | Waits for both; optional forms-only mode needs `marketing` |
83
91
 
84
92
  ## Ads and pixels
85
93
 
86
- | Integration | Helper | Category | Loading behavior |
87
- | ---------------------------------------------- | ------------------ | ----------- | ------------------------------------------------- |
88
- | [Meta Pixel](./meta-pixel.md) | `metaPixel` | `marketing` | Waits for effective permission |
89
- | [OpenAI Pixel](./openai-pixel.md) | `openaiPixel` | `marketing` | Gated initially; retains SDK and signals consent |
90
- | [Reddit Pixel](./reddit-pixel.md) | `redditPixel` | `marketing` | Gated initially; retains SDK and switches cookies |
91
- | [TikTok Pixel](./tiktok-pixel.md) | `tiktokPixel` | `marketing` | Gated initially; retains SDK and signals consent |
92
- | [LinkedIn Insight Tag](./linkedin-insights.md) | `linkedinInsights` | `marketing` | Waits for effective permission |
93
- | [Microsoft UET](./microsoft-uet.md) | `microsoftUet` | `marketing` | Always loads; signals ad storage consent |
94
- | [Snapchat Pixel](./snapchat-pixel.md) | `snapchatPixel` | `marketing` | Waits for effective permission |
95
- | [X Pixel](./x-pixel.md) | `xPixel` | `marketing` | Waits for effective permission |
96
-
97
- ## Keep one owner per vendor
98
-
99
- Remove direct snippets, tracking images, framework plugins and duplicate
100
- SDK initializers before adding a helper. A vendor loaded outside c15t is not
101
- controlled by the configuration here. Tag managers and data pipelines can load
102
- other destinations, which need their own consent settings.
103
-
104
- Initial loading and later event calls are separate. Some helpers keep an SDK
105
- loaded to send consent updates. Others remove their script element without a
106
- vendor stop callback. Neither approach can reverse code or requests that already
107
- ran. Guard application events and verify automatic tracking after revocation.
108
-
109
- Use [custom integrations](./building-integrations.md) for a service
110
- without a helper, or an SDK your application already owns. Follow
111
- [consent verification](../guides/verify-consent.md) for fresh sessions, rejection,
112
- acceptance, revocation and navigation.
94
+ | Integration | Helper | Category | Loading behavior |
95
+ | ---------------------------------------------- | ------------------ | ----------- | ---------------------------------------------------------------- |
96
+ | [Meta Pixel](./meta-pixel.md) | `metaPixel` | `marketing` | Gated initially; keeps the SDK and signals consent |
97
+ | [OpenAI Pixel](./openai-pixel.md) | `openaiPixel` | `marketing` | Gated initially; keeps the SDK and signals consent |
98
+ | [Pinterest Tag](./pinterest-tag.md) | `pinterestTag` | `marketing` | Gated initially; keeps the tag and signals consent |
99
+ | [Reddit Pixel](./reddit-pixel.md) | `redditPixel` | `marketing` | Gated initially; keeps the pixel and toggles first-party cookies |
100
+ | [TikTok Pixel](./tiktok-pixel.md) | `tiktokPixel` | `marketing` | Gated initially; keeps the SDK and signals consent |
101
+ | [LinkedIn Insight Tag](./linkedin-insights.md) | `linkedinInsights` | `marketing` | Waits for effective permission |
102
+ | [Microsoft UET](./microsoft-uet.md) | `microsoftUet` | `marketing` | Always loads; signals ad storage consent |
103
+ | [Snapchat Pixel](./snapchat-pixel.md) | `snapchatPixel` | `marketing` | Waits for effective permission |
104
+ | [X Pixel](./x-pixel.md) | `xPixel` | `marketing` | Waits for effective permission |
105
+
106
+ ## Load each vendor once
107
+
108
+ Remove the vendor's own snippet, tracking image, framework plugin or tag
109
+ manager entry before adding its helper. c15t cannot gate a copy it did not
110
+ load. Tag managers and data pipelines such as Segment can load further
111
+ destinations, which need consent settings of their own.
112
+
113
+ When a visitor turns off a category they had allowed, c15t reloads the page so
114
+ that code which already ran stops. Each vendor guide lists what its helper does
115
+ on revocation and how to check it.
116
+
117
+ ## Vendor switches and cookie cleanup
118
+
119
+ Every helper sets a `vendor` slug, so once you declare that vendor a visitor
120
+ can allow its category and still switch the vendor off. Gating also leaves
121
+ behind the cookies a vendor already wrote; `clearOnRevocation` deletes them
122
+ when their category is denied. Each framework documents both in its Scripts
123
+ and embeds group:
124
+
125
+ | Framework | Vendor consent | Clear on revocation |
126
+ | -------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
127
+ | Next.js | [Vendor consent](https://c15t.com/docs/frameworks/next/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/next/clear-on-revocation) |
128
+ | TanStack Start | [Vendor consent](https://c15t.com/docs/frameworks/tanstack-start/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/tanstack-start/clear-on-revocation) |
129
+ | React | [Vendor consent](https://c15t.com/docs/frameworks/react/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/react/clear-on-revocation) |
130
+ | Nuxt | [Vendor consent](https://c15t.com/docs/frameworks/nuxt/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/nuxt/clear-on-revocation) |
131
+ | Vue | [Vendor consent](https://c15t.com/docs/frameworks/vue/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/vue/clear-on-revocation) |
132
+ | Astro | [Vendor consent](https://c15t.com/docs/frameworks/astro/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/astro/clear-on-revocation) |
133
+ | Svelte | [Vendor consent](https://c15t.com/docs/frameworks/svelte/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/svelte/clear-on-revocation) |
134
+ | SvelteKit | [Vendor consent](https://c15t.com/docs/frameworks/sveltekit/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/sveltekit/clear-on-revocation) |
135
+ | HTML | [Vendor consent](https://c15t.com/docs/frameworks/html/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/html/clear-on-revocation) |
136
+ | JavaScript | [Vendor consent](https://c15t.com/docs/frameworks/javascript/vendor-consent) | [Clear on revocation](https://c15t.com/docs/frameworks/javascript/clear-on-revocation) |
137
+
138
+ ## Send events only to allowed integrations
139
+
140
+ `createEventDispatcher` from `@c15t/integrations/events` sends one named event to
141
+ every registered integration that has an event API and is allowed right now.
142
+ It drops events while measurement is denied, and one vendor's error does not
143
+ stop delivery to the others:
144
+
145
+ ```ts
146
+ import { createEventDispatcher } from '@c15t/integrations/events';
147
+
148
+ const events = createEventDispatcher({
149
+ scripts,
150
+ getSnapshot: () => runtime.kernel.getSnapshot(),
151
+ pageviews: ['segment'],
152
+ });
153
+
154
+ events.track('docs_search', { resultCount: 4 });
155
+ events.pageview(location.pathname);
156
+ ```
157
+
158
+ Pass the same `scripts` you registered and a function that returns the live
159
+ consent snapshot. `track` supports Google Tag Manager, Google Tag, PostHog,
160
+ Mixpanel, Segment, Hightouch, Heap, Amplitude, LogRocket, Adobe Analytics,
161
+ Databuddy, Plausible, Fathom, Pirsch, Microsoft Clarity, Hotjar, Vercel
162
+ Analytics, OneDollarStats, Umami, Rybbit, RudderStack and Matomo.
163
+ `pageview` sends single-page-app page views only to the integrations named in
164
+ `pageviews`: PostHog, Segment or Hightouch. Call it from your router's
165
+ navigation hook. The first call records the path without sending, and repeated
166
+ paths or hash-only changes are skipped.
167
+
168
+ ## Add a vendor without a helper
169
+
170
+ Use [custom integrations](./building-integrations.md) for a
171
+ vendor without a helper, or an SDK your app already loads. Test every
172
+ integration with the [consent verification guide](../guides/verify-consent.md).
@@ -0,0 +1,329 @@
1
+ ---
2
+ title: Pinterest Tag
3
+ description: Load the Pinterest Tag only after marketing consent with the c15t
4
+ pinterestTag helper, guard pintrk event calls, and check it in DevTools.
5
+ icon: pinterest
6
+ group: integrations
7
+ ---
8
+
9
+ ## Configure the Pinterest Tag
10
+
11
+ Copy the numeric tag ID from Pinterest Ads Manager. Remove Pinterest's base
12
+ code and its `<noscript>` image. The helper does not emit that image, because
13
+ it fires without JavaScript and c15t cannot gate it.
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` |
21
+
22
+ ```ts title="src/consent-scripts.ts"
23
+ import { pinterestTag } from '@c15t/integrations/pinterest-tag';
24
+
25
+ export const scripts = [pinterestTag({ tagId: '2613654212508' })];
26
+ ```
27
+
28
+ ## Register the scripts
29
+
30
+ Complete your [framework quickstart](https://c15t.com/docs/frameworks) first. Keep its Inth
31
+ endpoint, policy, styles and consent UI. Remove the vendor's original script,
32
+ SDK initializer or tag-manager entry, so the vendor loads only through c15t.
33
+
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.
40
+
41
+ **Next.js**
42
+
43
+ Import the configuration into the client boundary from your router guide:
44
+
45
+ ```ts
46
+ import { ConsentRoot } from 'c15t/next';
47
+ import { scripts } from './consent-scripts';
48
+ ```
49
+
50
+ Keep the server-resolved `state` and shared `consentConfig` from your
51
+ router guide. Its manifest, init and save URLs stay in effect. Add
52
+ `scripts` as a top-level prop on the existing root:
53
+
54
+ ```tsx
55
+ <ConsentRoot state={state} config={consentConfig} scripts={scripts}>
56
+ {children}
57
+ </ConsentRoot>
58
+ ```
59
+
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).
64
+
65
+ **TanStack Start**
66
+
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):
70
+
71
+ ```tsx title="src/routes/__root.tsx"
72
+ import { scripts } from '../consent-scripts';
73
+
74
+ <ConsentRoot
75
+ state={consent}
76
+ backendURL={backendURL}
77
+ initRoute={false}
78
+ scripts={scripts}
79
+ >
80
+ ```
81
+
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).
86
+
87
+ **React**
88
+
89
+ Add the configuration to the existing `ConsentProvider` options, next to
90
+ `mode`:
91
+
92
+ ```tsx title="src/consent.tsx"
93
+ import { scripts } from './consent-scripts';
94
+
95
+ <ConsentProvider options={{ mode, scripts }}>
96
+ ```
97
+
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).
102
+
103
+ **Nuxt**
104
+
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`:
107
+
108
+ ```ts title="app/app.config.ts"
109
+ import { scripts } from '../src/consent-scripts';
110
+
111
+ export default defineAppConfig({
112
+ c15t: { scripts },
113
+ });
114
+ ```
115
+
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).
122
+
123
+ **Vue**
124
+
125
+ Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
126
+
127
+ ```ts title="src/main.ts"
128
+ import { scripts } from './consent-scripts';
129
+
130
+ app.use(c15tVue, {
131
+ backendURL: 'https://your-project.inth.app',
132
+ scripts,
133
+ });
134
+ ```
135
+
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).
140
+
141
+ **Astro**
142
+
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.
148
+
149
+ ```ts title="src/consent-client.ts"
150
+ import type { C15tClientOptionsExtension } from 'c15t/astro';
151
+ import { scripts } from './consent-scripts';
152
+
153
+ export default { scripts } satisfies C15tClientOptionsExtension;
154
+ ```
155
+
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
160
+ `ClientRouter` navigation.
161
+
162
+ **Svelte**
163
+
164
+ Import the scripts in the component that owns your existing provider and
165
+ pass them as a top-level prop:
166
+
167
+ ```svelte title="src/App.svelte"
168
+ <script lang="ts">
169
+ import { ConsentManagerProvider, hosted } from '@c15t/svelte';
170
+ import { scripts } from './consent-scripts';
171
+
172
+ const mode = hosted({ url: 'https://your-project.inth.app' });
173
+ </script>
174
+
175
+ <ConsentManagerProvider {mode} {scripts}>
176
+ <!-- Keep your application, consent UI and preferences link here. -->
177
+ </ConsentManagerProvider>
178
+ ```
179
+
180
+ Retain the styles and consent UI from the [Svelte quickstart](https://c15t.com/docs/frameworks/svelte/quickstart).
181
+ The provider owns the loader and disposes it on unmount.
182
+
183
+ **SvelteKit**
184
+
185
+ Add the scripts to the existing root layout provider. Keep the server load
186
+ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.com/docs/frameworks/sveltekit/quickstart).
187
+
188
+ ```svelte title="src/routes/+layout.svelte"
189
+ <script lang="ts">
190
+ import { ConsentManagerProvider, hosted } from '@c15t/svelte';
191
+ import { scripts } from '../consent-scripts';
192
+
193
+ let { children, data } = $props();
194
+ const mode = hosted({ url: 'https://your-project.inth.app' });
195
+ </script>
196
+
197
+ <ConsentManagerProvider {mode} {scripts} prefetch={data.prefetch}>
198
+ {@render children()}
199
+ <!-- Keep your consent UI and preferences link here. -->
200
+ </ConsentManagerProvider>
201
+ ```
202
+
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
206
+ `runtime` to the provider, register scripts when creating that runtime instead.
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
+
225
+ **JavaScript**
226
+
227
+ Pass the scripts to `init()` from `@c15t/browser`, next to your backend
228
+ URL:
229
+
230
+ ```ts
231
+ import { init } from '@c15t/browser';
232
+ import { scripts } from './consent-scripts';
233
+
234
+ const consent = init({
235
+ backendURL: 'https://your-project.inth.app',
236
+ scripts,
237
+ });
238
+ ```
239
+
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
+ | `tagId` | Required | Tag ID passed to `pintrk('load', ...)`. The helper trims it. Empty or whitespace-only values throw. |
251
+ | `loadOptions` | None | Object passed as the third argument to `pintrk('load', ...)`, such as `em` or `external_id` for enhanced match. Pass user data only when your app has the permission it needs. |
252
+ | `trackPageVisit` | `true` | Queues `pintrk('page')` after `load`. Set `false` to send page visits yourself. |
253
+ | `scriptUrl` | `https://s.pinimg.com/ct/core.js` | Loader URL override. A blank value falls back to the default. |
254
+
255
+ ## Loading and revocation
256
+
257
+ `pinterestTag` uses the `marketing` category. Before marketing is allowed, c15t
258
+ defines no `pintrk` function and loads nothing from Pinterest. When marketing
259
+ becomes allowed, the helper queues `load`, `pintrk('setconsent', true)` and
260
+ the page visit, then loads `core.js`.
261
+
262
+ On revocation the helper keeps the tag and calls
263
+ `pintrk('setconsent', false)`, which Pinterest documents as stopping events
264
+ and clearing its first-party storage. If the visitor allows marketing again
265
+ before the page reloads, the helper calls `pintrk('setconsent', true)`.
266
+
267
+ ## Guard your own pintrk calls
268
+
269
+ The helper sends the page visit. Events your code sends, such as `checkout` or
270
+ `lead`, need their own check. After revocation `window.pintrk` still exists, so
271
+ its presence does not mean marketing is allowed. Check the permission first,
272
+ then that the tag has loaded:
273
+
274
+ ```ts title="src/track-checkout.ts"
275
+ export function trackCheckout(marketingAllowed: boolean, orderId: string) {
276
+ if (!marketingAllowed || typeof window.pintrk !== 'function') return;
277
+ window.pintrk('track', 'checkout', {
278
+ currency: 'USD',
279
+ event_id: orderId,
280
+ order_id: orderId,
281
+ value: 99.99,
282
+ line_items: [{ product_id: '1414', product_quantity: 1 }],
283
+ });
284
+ }
285
+ ```
286
+
287
+ Pass the current marketing permission from your framework, for example
288
+ `useConsent('marketing')` in React. Put product details in `line_items`, and
289
+ set `event_id` to deduplicate against the Conversions API. Pinterest reports
290
+ conversions only for its 20 event types. It keeps other event names for
291
+ audience targeting.
292
+
293
+ `@c15t/integrations/pinterest-tag` also exports `pinterestTagEvent`, a typed wrapper
294
+ around `pintrk('track', ...)`. It does nothing until `pintrk` exists and does
295
+ not check permission, so apply the same guard before calling it. Its optional
296
+ third argument receives Pinterest's `(didInit, error)` result.
297
+
298
+ ## Verify the Pinterest Tag
299
+
300
+ After you allow marketing, `core.js` loads from `s.pinimg.com` and Pinterest
301
+ Tag Helper shows the page visit. Trigger one guarded event and check that Tag
302
+ Helper records it. Then revoke marketing. Until the page reloads, calling
303
+ `trackCheckout` sends nothing.
304
+
305
+ Test in a private window with an opt-in policy. Open DevTools Network, disable
306
+ the cache and filter by the vendor's domain:
307
+
308
+ 1. Load the page. No request goes to the vendor before you choose.
309
+ 2. Click Reject, then reload. There is still no vendor request.
310
+ 3. Open Privacy settings and allow the helper's category. The vendor script
311
+ loads without a page reload.
312
+ 4. Turn the category off again and save. c15t reloads the page, and the new
313
+ page makes no vendor request.
314
+
315
+ c15t reloads on revocation because removing a script element does not stop
316
+ code that already ran. The vendor's listeners, timers and queued events stay
317
+ alive until the page unloads. If you set `reloadOnConsentRevoked: false`, stop
318
+ the vendor yourself. Register a callback-only script whose `onConsentChange`
319
+ calls the vendor's opt-out API, as shown in
320
+ [custom integrations](./building-integrations.md), and check the
321
+ permission before each of your own event calls. The reload does not delete
322
+ cookies the vendor already set; see
323
+ [clear on revocation for your framework](./overview.md#vendor-switches-and-cookie-cleanup).
324
+
325
+ The helper sets `vendor` to its script ID, so once you declare that vendor a
326
+ visitor can turn it off inside an allowed category. See
327
+ [vendor consent for your framework](./overview.md#vendor-switches-and-cookie-cleanup). The
328
+ [consent verification guide](../guides/verify-consent.md) covers navigation,
329
+ expiry and hosting checks.