@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,91 +1,80 @@
1
1
  ---
2
2
  title: Cloudflare Zaraz
3
- description: Synchronize c15t permissions with Zaraz purposes while Cloudflare
4
- manages your tools.
3
+ description: Sync c15t permissions to Cloudflare Zaraz purposes with the c15t
4
+ cloudflareZaraz bridge, which runs on every page without loading a script, and
5
+ check the tools it controls.
6
+ icon: cloudflare-web-analytics
5
7
  group: integrations
6
8
  ---
7
9
 
8
- ## Configure Zaraz before registering the bridge
9
-
10
- This helper connects c15t to an existing Zaraz installation. It does not insert a
11
- script, configure Cloudflare tools, or turn a standalone SDK into a server-side
12
- integration. Configure each tool in Zaraz and remove its previous standalone
13
- loader, including any duplicate `@c15t/scripts` helper.
14
-
15
- In the Zaraz dashboard:
16
-
17
- 1. Enable Consent Management and create purposes for the categories you use.
18
- 2. Assign a purpose to every tool requiring permission. Zaraz tools without a
19
- purpose bypass consent checks.
20
- 3. Disable automatic display of the Zaraz consent modal. c15t owns the UI.
21
- 4. Disable **Automatic Pageview Tracking**. Disable automatic SPA pageviews too
22
- if your application will emit them itself.
23
- 5. Copy the purpose IDs into the mapping below. Every active purpose returned by `zaraz.consent.getAll()` and omitted
24
- from the mapping is denied by this bridge. Register one bridge per application.
25
-
26
- Zaraz keeps a separate consent cookie. Its automatic pageview can run before
27
- c15t resolves the current permissions, using a grant from a previous visit.
28
- Disabling that pageview and emitting it from `onReady` prevents this particular
29
- startup race. Do not send other events before synchronization, and audit any
30
- custom triggers that run independently. DOM-ready, timer or click triggers can
31
- run with stale permissions before the bridge mounts. The bridge cannot undo
32
- requests sent before it starts.
33
-
34
- Cloudflare documents [purpose assignment](https://developers.cloudflare.com/zaraz/consent-management/)
35
- and [automatic pageview settings](https://developers.cloudflare.com/zaraz/reference/settings/).
36
-
37
- ## Register the consent bridge
38
-
39
- | Package manager | Command |
40
- | :-------------- | :-------------------------- |
41
- | npm | `npm install @c15t/scripts` |
42
- | pnpm | `pnpm add @c15t/scripts` |
43
- | yarn | `yarn add @c15t/scripts` |
44
- | bun | `bun add @c15t/scripts` |
10
+ ## Configure Cloudflare Zaraz
11
+
12
+ `cloudflareZaraz` connects c15t to an existing Zaraz installation. It inserts
13
+ no script and configures no tools. Zaraz loads the tools; c15t decides which
14
+ purposes they may use. In the Zaraz dashboard:
15
+
16
+ 1. Enable Consent Management and create purposes for the c15t categories you
17
+ use.
18
+ 2. Assign a purpose to every tool that needs permission. Zaraz runs a tool
19
+ without a purpose regardless of consent.
20
+ 3. Turn off automatic display of the Zaraz consent modal. c15t owns the UI.
21
+ 4. Turn off **Automatic Pageview Tracking**, and automatic SPA pageviews too if
22
+ your app sends them itself.
23
+ 5. Copy the purpose IDs, not the purpose names, into the mapping below.
24
+
25
+ Zaraz keeps its own consent cookie. An automatic pageview can run with a grant
26
+ from a previous visit before c15t applies the current permissions. With
27
+ automatic pageviews off, send the first pageview from `onReady`, which runs
28
+ after the first synchronization. DOM-ready, timer and click triggers you add in
29
+ Zaraz can still run before the bridge starts; audit them. Cloudflare documents
30
+ [purpose assignment](https://developers.cloudflare.com/zaraz/consent-management/)
31
+ and [pageview settings](https://developers.cloudflare.com/zaraz/reference/settings/).
32
+
33
+ | Package manager | Command |
34
+ | :-------------- | :------------------------------------- |
35
+ | npm | `npm install @c15t/integrations@alpha` |
36
+ | pnpm | `pnpm add @c15t/integrations@alpha` |
37
+ | yarn | `yarn add @c15t/integrations@alpha` |
38
+ | bun | `bun add @c15t/integrations@alpha` |
45
39
 
46
40
  ```ts title="src/consent-scripts.ts"
47
- import { cloudflareZaraz } from '@c15t/scripts/cloudflare-zaraz';
41
+ import { cloudflareZaraz } from '@c15t/integrations/cloudflare-zaraz';
48
42
 
49
43
  // Zaraz provides this global after its loader runs.
50
44
  declare const zaraz: { track: (event: string) => void };
51
45
 
52
46
  export const scripts = [
53
- cloudflareZaraz({
54
- purposes: {
55
- measurement: ['your-measurement-purpose-id'],
56
- marketing: ['your-marketing-purpose-id'],
57
- },
58
- onReady: () => {
59
- zaraz.track('Pageview');
60
- },
61
- }),
47
+ cloudflareZaraz({
48
+ purposes: {
49
+ measurement: ['your-measurement-purpose-id'],
50
+ marketing: ['your-marketing-purpose-id'],
51
+ },
52
+ onReady: () => {
53
+ zaraz.track('Pageview');
54
+ },
55
+ }),
62
56
  ];
63
57
  ```
64
58
 
65
- Use actual IDs from your dashboard, not the purpose names. A category may map to
66
- several purposes, but a purpose cannot appear more than once. Empty mappings,
67
- blank IDs and duplicate IDs throw during construction. Zaraz only returns purposes attached to enabled tools from `getAll()`. IDs absent
68
- from that result cannot receive a grant; compare the mapping with
69
- `zaraz.consent.getAll()` when troubleshooting.
70
-
71
- Include the mapped categories in your c15t policy. The bridge reads effective
72
- permissions, including policy restrictions, rather than treating every allowed
73
- category as a recorded visitor choice.
74
-
75
- For the shared registration examples below, keep Zaraz's own loader and its
76
- configured dashboard tools. Remove duplicate standalone vendor loaders only.
77
- For this integration, c15t owns permission synchronization and Zaraz owns tool
78
- loading.
59
+ Register one bridge per app. Keep Zaraz's own loader and its dashboard tools
60
+ when you follow the registration steps below; remove only standalone loaders
61
+ for tools that Zaraz already runs, including a separate `@c15t/integrations` helper
62
+ for the same tool. If Zaraz auto-injection is off, load
63
+ [Zaraz manually](https://developers.cloudflare.com/zaraz/advanced/load-zaraz-manually/)
64
+ once.
79
65
 
80
66
  ## Register the scripts
81
67
 
82
68
  Complete your [framework quickstart](https://c15t.com/docs/frameworks) first. Keep its Inth
83
69
  endpoint, policy, styles and consent UI. Remove the vendor's original script,
84
- SDK initializer or tag-manager entry so c15t owns loading once.
70
+ SDK initializer or tag-manager entry, so the vendor loads only through c15t.
85
71
 
86
- The `scripts` export in `src/consent-scripts.ts` is a configuration, not an
87
- initializer. Add it to your existing consent owner using the registration point
88
- below. These are partial edits to that owner, not additional providers.
72
+ The vendor pages put the helper in `src/consent-scripts.ts`. If your framework
73
+ quickstart already created a scripts file, such as `lib/scripts.ts` in the
74
+ Next.js guide, add the helper to that array instead of creating a second file.
75
+ The `scripts` export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
76
+ point for your framework below. These are edits to that provider, not a second
77
+ provider.
89
78
 
90
79
  **Next.js**
91
80
 
@@ -106,158 +95,106 @@ router guide. Its manifest, init and save URLs stay in effect. Add
106
95
  </ConsentRoot>
107
96
  ```
108
97
 
109
- For a Pages Router or static-export setup using `ConsentProvider`, add
110
- `scripts` to its existing `options` instead. Keep the router-specific setup
111
- from [Next.js script loading](../frameworks/next/script-loader.md).
98
+ App Router, Pages Router and static export all use this `ConsentRoot` in
99
+ the `'use client'` wrapper `components/consent.tsx`. Keep `scripts` there,
100
+ because a Server Component cannot pass script callbacks to it. See
101
+ [Next.js scripts and embeds](../frameworks/next/scripts.md).
112
102
 
113
103
  **TanStack Start**
114
104
 
115
- In your existing root route component, import the scripts alongside
116
- `ConsentRoot`. Keep the server loader from the [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart).
105
+ Import the configuration into your root route and pass it to the existing
106
+ `ConsentRoot` as a top-level prop. Keep the loader, `backendURL` and
107
+ `initRoute` from the [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart):
117
108
 
118
- ```tsx
119
- import { Outlet } from '@tanstack/react-router';
120
- import { ConsentRoot } from 'c15t/tanstack-start';
109
+ ```tsx title="src/routes/__root.tsx"
121
110
  import { scripts } from '../consent-scripts';
122
111
 
123
- function Root() {
124
- const state = Route.useLoaderData();
125
- return (
126
- <ConsentRoot state={state} backendURL={backendURL} initRoute={false} scripts={scripts}>
127
- <Outlet />
128
- {/* Keep your consent banner, dialog and preferences link here. */}
129
- </ConsentRoot>
130
- );
131
- }
112
+ <ConsentRoot
113
+ state={consent}
114
+ backendURL={backendURL}
115
+ initRoute={false}
116
+ scripts={scripts}
117
+ >
132
118
  ```
133
119
 
134
- This edits the existing route. `Route` and `backendURL` come from its setup;
135
- keep the document shell and head components if they are part of your root.
136
- `initRoute={false}` keeps the quickstart's direct-backend initialization.
137
- If your app mounts a consent server route, retain its existing `initRoute`
138
- instead. Do not return script callbacks from a server function or route loader.
120
+ Import vendor helpers in the root route module, not in a server function.
121
+ A server function's return value must be serializable, and script
122
+ configurations carry callbacks. See
123
+ [TanStack Start scripts](../frameworks/tanstack-start/scripts.md).
139
124
 
140
125
  **React**
141
126
 
142
- Import the scripts into your existing provider component:
127
+ Add the configuration to the existing `ConsentProvider` options, next to
128
+ `mode`:
143
129
 
144
- ```ts
145
- import { ConsentProvider } from 'c15t/react';
130
+ ```tsx title="src/consent.tsx"
146
131
  import { scripts } from './consent-scripts';
147
- ```
148
132
 
149
- Keep the existing options and add `scripts`:
150
-
151
- ```tsx
152
- <ConsentProvider options={{ ...consentOptions, scripts }}>
153
- {children}
154
- </ConsentProvider>
133
+ <ConsentProvider options={{ mode, scripts }}>
155
134
  ```
156
135
 
157
- Here `consentOptions` is your existing configuration, including
158
- `mode: hosted({ url: backendURL })`. Keep the banner, dialog and preferences
159
- link inside the provider. See [React script loading](../frameworks/react/script-loader.md).
136
+ `mode` is the `hosted({ url: 'https://your-project.inth.app' })` value
137
+ from the [React quickstart](https://c15t.com/docs/frameworks/react/quickstart). Keep the banner,
138
+ dialog and preferences link inside the provider. See
139
+ [React scripts and embeds](../frameworks/react/scripts.md).
160
140
 
161
141
  **Nuxt**
162
142
 
163
- Attach one loader from the root `app.vue`, after the Nuxt module has
164
- started its browser runtime. This keeps vendor callbacks in application code rather
165
- than serialized `nuxt.config.ts` runtime configuration.
143
+ Register the scripts under the `c15t` key in `app/app.config.ts`. Adjust the
144
+ relative import to where you created `consent-scripts.ts`:
166
145
 
167
- ```vue title="app/app.vue"
168
- <script setup lang="ts">
169
- import { onUnmounted } from 'vue';
170
- import { createScriptLoader } from 'c15t/modules/script-loader';
146
+ ```ts title="app/app.config.ts"
171
147
  import { scripts } from '../src/consent-scripts';
172
148
 
173
- const nuxtApp = useNuxtApp();
174
- const kernel = useConsentKernel();
175
- let loader: ReturnType<typeof createScriptLoader> | undefined;
176
-
177
- const removeMountedHook = nuxtApp.hook('app:mounted', () => {
178
- loader = createScriptLoader({ kernel, scripts });
179
- });
180
- onUnmounted(() => {
181
- removeMountedHook();
182
- loader?.dispose();
149
+ export default defineAppConfig({
150
+ c15t: { scripts },
183
151
  });
184
- </script>
185
-
186
- <template>
187
- <ConsentRoot />
188
- <NuxtPage />
189
- </template>
190
152
  ```
191
153
 
192
- Merge the setup code into your root and retain its footer and preferences
193
- link. `useConsentKernel` is auto-imported by the c15t Nuxt module. Adjust the
194
- relative script import if your `app.vue` is at the project root. This loader
195
- waits until the module has applied browser persistence and privacy signals,
196
- then reads the current snapshot and observes future changes. Do not also register these scripts
197
- in another loader. See the [Nuxt quickstart](https://c15t.com/docs/frameworks/nuxt/quickstart).
154
+ The Nuxt module merges this over its options in `nuxt.config.ts` and starts
155
+ one script loader in the browser after hydration, once it has applied the
156
+ visitor's stored choice and privacy signals. Keep `scripts` out of
157
+ `nuxt.config.ts`, which reaches the browser as JSON and drops the vendor
158
+ callbacks. Write the vendor IDs into `consent-scripts.ts`. See
159
+ [Nuxt scripts and embeds](../frameworks/nuxt/scripts.md).
198
160
 
199
161
  **Vue**
200
162
 
201
- Use the kernel already provided by the Vue plugin. Merge this setup into
202
- `App.vue`, whose lifetime covers the application:
163
+ Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
203
164
 
204
- ```vue title="src/App.vue"
205
- <script setup lang="ts">
206
- import { onMounted, onUnmounted } from 'vue';
207
- import { createScriptLoader } from 'c15t/modules/script-loader';
208
- import { useConsentKernel } from 'c15t/vue/vue-plugin';
209
- import ConsentRoot from 'c15t/vue/consent-root';
165
+ ```ts title="src/main.ts"
210
166
  import { scripts } from './consent-scripts';
211
167
 
212
- const kernel = useConsentKernel();
213
- let loader: ReturnType<typeof createScriptLoader> | undefined;
214
-
215
- onMounted(() => {
216
- loader = createScriptLoader({ kernel, scripts });
168
+ app.use(c15tVue, {
169
+ backendURL: 'https://your-project.inth.app',
170
+ scripts,
217
171
  });
218
- onUnmounted(() => loader?.dispose());
219
- </script>
220
-
221
- <template>
222
- <ConsentRoot />
223
- <main>Your application</main>
224
- </template>
225
172
  ```
226
173
 
227
- Keep your existing page content and preferences link. The plugin still owns
228
- the kernel and persistence; this component owns only the vendor loader.
229
- Do not register the same scripts in plugin configuration as well. See the
230
- [Vue quickstart](https://c15t.com/docs/frameworks/vue/quickstart).
174
+ Keep your existing backend URL and other options. The plugin starts one
175
+ script loader when the app mounts, after it has applied the visitor's stored
176
+ choice. Do not also call `createScriptLoader` from a component. See
177
+ [Vue scripts and embeds](../frameworks/vue/scripts.md).
231
178
 
232
179
  **Astro**
233
180
 
234
- Point the existing Astro integration at a client module. Keep its `mode`,
235
- `ui` and framework integration from the [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart).
236
- Import `fileURLToPath` in your Astro configuration:
237
-
238
- ```js title="astro.config.mjs"
239
- import { fileURLToPath } from 'node:url';
240
- ```
241
-
242
- Add this option to the existing `c15t({ ... })` call. Resolve the path from
243
- the configuration file because Astro injects the import into a virtual module:
244
-
245
- ```js
246
- clientEntrypoint: fileURLToPath(new URL('./src/c15t.client.ts', import.meta.url)),
247
- ```
181
+ Add the scripts to the client entrypoint from the
182
+ [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart), the module that the
183
+ integration's `clientEntrypoint` option names. Keep `mode`, `ui` and the
184
+ framework integration in `astro.config.mjs` as they are. If the module
185
+ already exports scripts, combine the two arrays.
248
186
 
249
- Export the scripts from that module:
250
-
251
- ```ts title="src/c15t.client.ts"
187
+ ```ts title="src/consent-client.ts"
252
188
  import type { C15tClientOptionsExtension } from 'c15t/astro';
253
189
  import { scripts } from './consent-scripts';
254
190
 
255
191
  export default { scripts } satisfies C15tClientOptionsExtension;
256
192
  ```
257
193
 
258
- The integration passes this extension to its shared browser runtime. Vendor
259
- helpers contain callbacks, so do not put them in the serialized `scripts`
260
- option in `astro.config.mjs`. Keep one runtime across consent islands and
194
+ Vendor helpers contain callbacks, and the integration options in
195
+ `astro.config.mjs` are serialized into the page, so do not put helpers in
196
+ the integration's `scripts` option. The integration passes the client
197
+ entrypoint to the one runtime every page shares, including across
261
198
  `ClientRouter` navigation.
262
199
 
263
200
  **Svelte**
@@ -270,9 +207,7 @@ pass them as a top-level prop:
270
207
  import { ConsentManagerProvider, hosted } from '@c15t/svelte';
271
208
  import { scripts } from './consent-scripts';
272
209
 
273
- const backendURL = import.meta.env.VITE_C15T_BACKEND_URL;
274
- if (!backendURL) throw new Error('Set VITE_C15T_BACKEND_URL');
275
- const mode = hosted({ url: backendURL });
210
+ const mode = hosted({ url: 'https://your-project.inth.app' });
276
211
  </script>
277
212
 
278
213
  <ConsentManagerProvider {mode} {scripts}>
@@ -294,7 +229,7 @@ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.
294
229
  import { scripts } from '../consent-scripts';
295
230
 
296
231
  let { children, data } = $props();
297
- const mode = hosted({ url: data.backendURL });
232
+ const mode = hosted({ url: 'https://your-project.inth.app' });
298
233
  </script>
299
234
 
300
235
  <ConsentManagerProvider {mode} {scripts} prefetch={data.prefetch}>
@@ -303,97 +238,110 @@ and its serializable prefetch data from the [SvelteKit quickstart](https://c15t.
303
238
  </ConsentManagerProvider>
304
239
  ```
305
240
 
306
- Import vendor helpers in the layout component, not in `+layout.server.ts`.
307
- For static hosting, keep your browser-only `mode` setup and omit request
308
- prefetch; the `scripts` prop stays the same. If you pass an externally owned
241
+ Import vendor helpers in the layout component, not in `+layout.server.ts`:
242
+ a server load cannot send functions to the browser. Prerendered, static and
243
+ SPA-mode pages use the same `scripts` prop. If you pass an externally owned
309
244
  `runtime` to the provider, register scripts when creating that runtime instead.
310
245
 
246
+ **HTML**
247
+
248
+ The helpers in `@c15t/integrations` are ES modules that need a bundler. On a
249
+ page that loads the c15t script tag, paste the vendor's own snippet instead
250
+ and keep it inert until its category is allowed:
251
+
252
+ ```html
253
+ <script type="text/plain" data-c15t-category="measurement">
254
+ // The vendor's snippet, unchanged
255
+ </script>
256
+ ```
257
+
258
+ Use the category this guide names for the vendor. c15t runs the snippet
259
+ once that category is allowed, and reloads the page when the visitor
260
+ withdraws it. Helper options on this page, such as `loadMode`, do not apply
261
+ to a pasted snippet. See [HTML scripts](../frameworks/html/scripts.md).
262
+
311
263
  **JavaScript**
312
264
 
313
- Attach the loader to your existing kernel before calling
314
- `kernel.commands.init()`:
265
+ Pass the scripts to `init()` from `@c15t/browser`, next to your backend
266
+ URL:
315
267
 
316
268
  ```ts
317
- import { createScriptLoader } from 'c15t/modules/script-loader';
269
+ import { init } from '@c15t/browser';
318
270
  import { scripts } from './consent-scripts';
319
271
 
320
- const loader = createScriptLoader({ kernel, scripts });
272
+ const consent = init({
273
+ backendURL: 'https://your-project.inth.app',
274
+ scripts,
275
+ });
321
276
  ```
322
277
 
323
- Call `loader.dispose()` when that application instance is destroyed.
324
- `kernel` is the hosted kernel from your quickstart. A provider-owned kernel
325
- already has a loader; do not attach a second one. See
326
- [JavaScript script loading](../frameworks/javascript/script-loader.md).
327
-
328
- ## Loading and updates
329
-
330
- The helper returns an `alwaysLoad`, `callbackOnly` configuration with category
331
- `necessary`. This lets consent synchronization run for every visitor. It does
332
- not make the downstream analytics or advertising tools necessary.
333
-
334
- Zaraz normally injects its own loader. If auto-injection is disabled, install
335
- [Zaraz manually](https://developers.cloudflare.com/zaraz/advanced/load-zaraz-manually/)
336
- once. The bridge supports either loading order: an already-ready API is updated
337
- immediately; otherwise it waits for `zarazConsentAPIReady` and applies the latest
338
- c15t permissions. No polling is used.
339
-
340
- On a change, the bridge calls `zaraz.consent.set()` before
341
- `zaraz.consent.sendQueuedEvents()`. It flushes Zaraz's queued pageviews only when
342
- a purpose changes from denied to allowed. Revocation updates purposes to false
343
- and does not flush events. Repeated identical permissions do not rewrite the
344
- Zaraz cookie. `onReady` runs once after the first successful synchronization,
345
- including when all optional purposes are denied. A pageview sent there remains
346
- subject to Zaraz's purpose checks.
347
-
348
- | Option | Default | Behavior |
349
- | ------------------ | -------- | ---------------------------------------------------------------------------- |
350
- | `purposes` | Required | Maps categories to Zaraz purpose IDs; unmapped purposes are denied |
351
- | `hideBuiltInModal` | `true` | Hides the currently visible modal; also disable auto-display in Cloudflare |
352
- | `sendQueuedEvents` | `true` | Replays Zaraz's queued pageviews after new grants |
353
- | `onReady` | Unset | Runs after initial permission synchronization |
354
- | `onError` | Unset | Receives synchronization errors so the application can report or handle them |
355
-
356
- If a Zaraz API call throws, `onReady` does not run until synchronization
357
- succeeds. Use `onError(error)` to report the failure and prevent application
358
- events from relying on permissions that were not applied. The bridge retries
359
- with the latest permissions on the next consent update or readiness event;
360
- it does not poll or schedule automatic retries. Readiness retries remain
361
- registered when `onError` is omitted and an error reaches the loader debug hook. A failed queued-event replay
362
- remains pending until synchronization succeeds while that purpose is still
363
- allowed. Revoking the purpose cancels its pending replay. Zaraz can partially
364
- process a queue before throwing, so retries cannot guarantee exactly-once delivery. Without `onError`, synchronous
365
- failures reach the script loader's debug events and readiness-event failures
366
- reach the browser's error handler. A failed revocation can leave the previous
367
- Zaraz grant in place.
368
-
369
- If the bridge starts before saved consent or policy resolution is available,
370
- it applies the kernel's current effective permissions and updates them when
371
- initialization completes. Pass restored state during setup when available.
372
- The bridge does not force a denial when the kernel already permits a purpose.
373
-
374
- Set `sendQueuedEvents: false` if your application deliberately discards
375
- pre-consent pageviews. Send subsequent route events only after readiness and
376
- avoid combining manual route events with Zaraz's automatic SPA pageviews.
377
-
378
- Removing or replacing the configuration, or disposing its loader, detaches the
379
- readiness listener. Disposal does not revoke consent, clear vendor storage, or
380
- stop a tool that has already initialized. Save the denied permissions before
381
- teardown when revocation is required. Zaraz controls subsequent tool execution;
382
- test vendor-specific behavior for scripts with their own ongoing activity.
383
-
384
- ## Verify the configured tools
385
-
386
- Use a test environment with isolated destinations. Check a first visit, a return
387
- visit with stale Zaraz grants, measurement-only acceptance, marketing-only
388
- acceptance, rejection, and revocation. Inspect both `zaraz.consent.getAll()` and
389
- actual tool activity. An updated consent object alone does not prove that a
390
- misconfigured tool stopped sending data.
391
-
392
- This integration maps c15t categories to Zaraz purposes. It does not translate
393
- IAB TCF vendor and purpose choices or replace Zaraz's separate TCF configuration.
278
+ Keep the backend URL from your quickstart. With
279
+ `createConsentRuntime` from `c15t/runtime`, pass `scripts` to it instead.
280
+ A kernel you create yourself needs a loader from
281
+ `c15t/modules/script-loader`. Attach one loader per kernel. See
282
+ [JavaScript scripts](../frameworks/javascript/scripts.md).
283
+
284
+ ## Options
285
+
286
+ | Option | Default | Behavior |
287
+ | ------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
288
+ | `purposes` | Required | Maps c15t categories to Zaraz purpose IDs. A category can list several IDs. An empty mapping, a blank ID, an ID with surrounding whitespace or an ID mapped twice throws. |
289
+ | `hideBuiltInModal` | `true` | Hides the Zaraz modal if it is visible. Also turn off auto-display in Zaraz. |
290
+ | `sendQueuedEvents` | `true` | Calls `zaraz.consent.sendQueuedEvents()` after a purpose changes from denied to allowed. Set `false` to discard pageviews Zaraz queued before consent. |
291
+ | `onReady` | None | Runs once after the first successful synchronization, even when every purpose is denied. |
292
+ | `onError` | None | Receives synchronization errors. |
293
+
294
+ ## Loading and revocation
295
+
296
+ `cloudflareZaraz` returns a callback-only script with the `necessary` category
297
+ and `alwaysLoad`, so the bridge runs for every visitor. That does not make the
298
+ tools behind it necessary. Control each tool through its Zaraz purpose.
299
+
300
+ The bridge's vendor slug is `cloudflare-zaraz`. Declare a vendor with that
301
+ `id` to give visitors a switch for Zaraz in the preference dialog. While a
302
+ visitor has it switched off, the bridge denies every purpose mapped to an
303
+ optional category, whatever the categories allow. See
304
+ [vendor consent for your framework](./overview.md#vendor-switches-and-cookie-cleanup).
305
+
306
+ When the Zaraz consent API is ready, the bridge reads `zaraz.consent.getAll()`
307
+ and sets each returned purpose to `true` only if its mapped category is
308
+ allowed in c15t's effective permissions, which include policy restrictions.
309
+ Purposes you did not map are set to `false`. If the API is not ready,
310
+ the bridge waits for the `zarazConsentAPIReady` event and applies the latest
311
+ permissions; it does not poll. On each consent change it calls
312
+ `zaraz.consent.set()` only when a value differs, then replays queued events
313
+ for newly allowed purposes. Revocation sets purposes to `false` and replays
314
+ nothing. Zaraz returns only purposes attached to enabled tools, so a mapped ID
315
+ missing from `getAll()` gets no grant.
316
+
317
+ If a Zaraz call throws, `onReady` waits and the bridge retries on the next
318
+ consent change or readiness event. Without `onError`, the error reaches the
319
+ script loader's debug events, or the browser's error handler for readiness
320
+ events. A failed revocation can leave the previous Zaraz grant in place, and a
321
+ retried replay can send a queued event twice. Disposing the loader detaches the
322
+ bridge but does not revoke purposes or stop tools that already ran. The bridge
323
+ maps categories to purposes only; it does not translate IAB TCF choices.
324
+
325
+ ## Verify Cloudflare Zaraz
326
+
327
+ Test with isolated destinations. `getAll()` shows what the bridge set, but only
328
+ a tool's own requests show whether it respected that.
329
+
330
+ 1. In a private window with an opt-in policy, load the page. The bridge adds
331
+ no script element. `zaraz.consent.getAll()` returns `false` for every
332
+ purpose, the Zaraz modal stays hidden, and no purpose-gated tool sends a
333
+ request.
334
+ 2. Click Reject, then reload. Every purpose is still `false`.
335
+ 3. Open Privacy settings and allow measurement. Without a reload, the
336
+ measurement purposes become `true`, the queued pageview replays and
337
+ measurement tools send requests. Marketing tools stay silent.
338
+ 4. Turn measurement off again and save. c15t reloads the page, and the new
339
+ page starts with every purpose `false`.
340
+ 5. In the console, call `zaraz.consent.set()` to grant a purpose that c15t
341
+ denies, then reload. The bridge sets it back to `false` before `onReady`
342
+ runs.
394
343
 
395
344
  [Cloudflare Web Analytics](./cloudflare-web-analytics.md) is a
396
- separate analytics product with its own loader. Zaraz manages multiple tools,
397
- which can have different consent requirements and execution costs. Moving a
398
- tool to Zaraz can reduce browser work, but this bridge alone does not establish
399
- a performance improvement for that tool.
345
+ separate product with its own helper. See the
346
+ [consent verification guide](../guides/verify-consent.md) for navigation and
347
+ hosting checks.