@c15t/react 3.1.0-canary.0 → 3.2.0-canary.0

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 (129) hide show
  1. package/AGENTS.md +11 -4
  2. package/README.md +4 -4
  3. package/dist/component-hooks/use-consent-gate.js +2 -0
  4. package/dist/component-hooks/use-consent-labels.js +2 -0
  5. package/dist/component-hooks/use-consent-text-direction.js +2 -0
  6. package/dist/component-hooks/use-vendors-listed-under.js +2 -0
  7. package/dist/components/consent-gate/atoms.js +1 -1
  8. package/dist/components/consent-gate/consent-gate.js +1 -1
  9. package/dist/components/iab-prompt/atoms/root.js +1 -1
  10. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  11. package/dist/components/preferences/atoms/button.js +1 -1
  12. package/dist/components/preferences/atoms/vendor-list.js +1 -1
  13. package/dist/components/prompt/atoms/root.js +1 -1
  14. package/dist/components/prompt/components.js +1 -1
  15. package/dist/components/prompt/policy-actions.js +1 -1
  16. package/dist/components/prompt/prompt.js +1 -1
  17. package/dist/components/prompt/surface-context.js +1 -1
  18. package/dist/components/prompt/use-banner-copy.js +1 -1
  19. package/dist/components/shared/streamed-surface.js +1 -1
  20. package/dist/event-dispatcher.js +2 -0
  21. package/dist/headless.js +1 -1
  22. package/dist/index-parts/event-dispatcher.js +1 -0
  23. package/dist/index-parts/offline.js +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/modes.js +1 -1
  26. package/dist/provider.js +1 -1
  27. package/dist/transports/offline.js +1 -1
  28. package/dist/version.js +1 -1
  29. package/dist-types/component-hooks/use-consent-gate.d.ts +102 -0
  30. package/dist-types/component-hooks/use-consent-labels.d.ts +32 -0
  31. package/dist-types/component-hooks/use-consent-text-direction.d.ts +22 -0
  32. package/dist-types/component-hooks/use-vendors-listed-under.d.ts +30 -0
  33. package/dist-types/components/prompt/atoms/root.d.ts +3 -3
  34. package/dist-types/components/prompt/prompt.d.ts +4 -3
  35. package/dist-types/components/prompt/surface-context.d.ts +1 -14
  36. package/dist-types/components/prompt/use-banner-copy.d.ts +8 -3
  37. package/dist-types/components/shared/streamed-surface.d.ts +47 -10
  38. package/dist-types/context.d.ts +3 -1
  39. package/dist-types/event-dispatcher.d.ts +24 -0
  40. package/dist-types/headless.d.ts +10 -1
  41. package/dist-types/hooks/use-iab-policy-guard.d.ts +17 -1
  42. package/dist-types/hooks/use-scroll-lock.d.ts +16 -2
  43. package/dist-types/index-parts/event-dispatcher.d.ts +7 -0
  44. package/dist-types/index-parts/offline.d.ts +1 -1
  45. package/dist-types/index.d.ts +2 -0
  46. package/dist-types/modes.d.ts +1 -1
  47. package/dist-types/module-hooks/script-loader.d.ts +9 -0
  48. package/dist-types/provider.d.ts +3 -3
  49. package/dist-types/transports/offline.d.ts +2 -2
  50. package/dist-types/version.d.ts +1 -1
  51. package/docs/README.md +11 -4
  52. package/docs/concepts/choose-your-setup.md +9 -9
  53. package/docs/concepts/consent-state.md +93 -9
  54. package/docs/concepts/data-fetching.md +30 -23
  55. package/docs/concepts/modes.md +85 -35
  56. package/docs/customization/recipes.md +4 -4
  57. package/docs/customization/stylesheets.md +3 -3
  58. package/docs/customization/tailwind.md +17 -34
  59. package/docs/customization/translations.md +18 -12
  60. package/docs/frameworks/react/clear-on-revocation.md +3 -2
  61. package/docs/frameworks/react/components/consent-banner.md +3 -3
  62. package/docs/frameworks/react/components/consent-provider.md +29 -29
  63. package/docs/frameworks/react/gpp.md +1 -1
  64. package/docs/frameworks/react/headless.md +146 -19
  65. package/docs/frameworks/react/iab.md +8 -1
  66. package/docs/frameworks/react/quickstart.md +1 -1
  67. package/docs/frameworks/react/rendering.md +1 -1
  68. package/docs/frameworks/react/scripts.md +44 -0
  69. package/docs/frameworks/react/translations.md +9 -9
  70. package/docs/frameworks/react/troubleshooting.md +1 -1
  71. package/docs/frameworks/react/upgrade-v3.md +39 -32
  72. package/docs/frameworks/react/vendor-consent.md +5 -0
  73. package/docs/guides/banner-experiments.md +3 -3
  74. package/docs/guides/troubleshooting.md +3 -2
  75. package/docs/integrations/adobe-analytics.md +2 -2
  76. package/docs/integrations/ahrefs-analytics.md +2 -2
  77. package/docs/integrations/amplitude.md +2 -2
  78. package/docs/integrations/clay.md +305 -0
  79. package/docs/integrations/clearbit.md +2 -2
  80. package/docs/integrations/cloudflare-web-analytics.md +2 -2
  81. package/docs/integrations/cloudflare-zaraz.md +2 -2
  82. package/docs/integrations/crisp.md +2 -2
  83. package/docs/integrations/databuddy.md +2 -2
  84. package/docs/integrations/fathom-analytics.md +2 -2
  85. package/docs/integrations/front-chat.md +2 -2
  86. package/docs/integrations/google-maps.md +2 -2
  87. package/docs/integrations/google-tag-manager.md +59 -2
  88. package/docs/integrations/google-tag.md +2 -2
  89. package/docs/integrations/heap.md +2 -2
  90. package/docs/integrations/hightouch.md +2 -2
  91. package/docs/integrations/hotjar.md +40 -26
  92. package/docs/integrations/intercom.md +2 -2
  93. package/docs/integrations/klaviyo.md +2 -2
  94. package/docs/integrations/linkedin-insights.md +2 -2
  95. package/docs/integrations/logrocket.md +2 -2
  96. package/docs/integrations/matomo-analytics.md +2 -2
  97. package/docs/integrations/meta-pixel.md +2 -2
  98. package/docs/integrations/microsoft-clarity.md +2 -2
  99. package/docs/integrations/microsoft-uet.md +2 -2
  100. package/docs/integrations/mixpanel-analytics.md +2 -2
  101. package/docs/integrations/one-dollar-stats.md +2 -2
  102. package/docs/integrations/openai-pixel.md +2 -2
  103. package/docs/integrations/other-ads-and-pixels.md +94 -0
  104. package/docs/integrations/other-analytics.md +108 -0
  105. package/docs/integrations/other-chat-and-support.md +112 -0
  106. package/docs/integrations/other-email-and-sms.md +156 -0
  107. package/docs/integrations/other-experience.md +222 -0
  108. package/docs/integrations/overview.md +102 -45
  109. package/docs/integrations/pinterest-tag.md +2 -2
  110. package/docs/integrations/pirsch.md +2 -2
  111. package/docs/integrations/plausible-analytics.md +2 -2
  112. package/docs/integrations/posthog.md +10 -2
  113. package/docs/integrations/promptwatch.md +2 -2
  114. package/docs/integrations/reddit-pixel.md +2 -2
  115. package/docs/integrations/rudderstack.md +2 -2
  116. package/docs/integrations/rybbit-analytics.md +2 -2
  117. package/docs/integrations/segment.md +2 -2
  118. package/docs/integrations/sentry.md +2 -2
  119. package/docs/integrations/shopify.md +323 -0
  120. package/docs/integrations/snapchat-pixel.md +2 -2
  121. package/docs/integrations/tiktok-pixel.md +2 -2
  122. package/docs/integrations/umami-analytics.md +2 -2
  123. package/docs/integrations/vercel-analytics.md +2 -2
  124. package/docs/integrations/vercel-speed-insights.md +7 -2
  125. package/docs/integrations/x-pixel.md +2 -2
  126. package/docs/integrations/youtube.md +2 -2
  127. package/package.json +12 -29
  128. package/dist/components/prompt/resolve-banner-primary-actions.js +0 -1
  129. package/dist-types/components/prompt/resolve-banner-primary-actions.d.ts +0 -14
@@ -10,16 +10,22 @@ icon: hotjar
10
10
  group: integrations
11
11
  ---
12
12
 
13
- The c15t `hotjar` helper keeps Hotjar off the page until `measurement` has
14
- consent. Until then, c15t does not define `window._hjSettings` or `window.hj`.
15
- The helper sends no consent signal to Hotjar. If the visitor withdraws consent,
16
- c15t removes the loader script element. By default, c15t also reloads the page.
17
- The reload stops Hotjar.
13
+ Hotjar records what visitors do on your pages, so it should load only when
14
+ consent allows analytics. The c15t `hotjar` helper waits until the
15
+ `measurement` category is allowed before it adds the Hotjar loader. Until then,
16
+ c15t doesn't define `window._hjSettings` or `window.hj`, and it loads nothing
17
+ from Hotjar. Under an opt-in policy, that wait lasts until the visitor allows
18
+ analytics.
19
+
20
+ Withdrawal needs more care. c15t sends Hotjar no consent signal, so it can't
21
+ tell a running recording to stop. By default it reloads the page instead, and
22
+ the reload ends the recording.
18
23
 
19
24
  ## Configure Hotjar
20
25
 
21
- Copy the site ID from your Hotjar tracking code, where it is the `hjid` value.
22
- Remove the original tracking code.
26
+ Find your site ID in the Hotjar tracking code. It's the `hjid` value. Then
27
+ delete the tracking code from your app. c15t doesn't control that snippet, so
28
+ if it stays, Hotjar loads and records even after the visitor rejects analytics.
23
29
 
24
30
  | Package manager | Command |
25
31
  | :-------------- | :------------------------------- |
@@ -165,7 +171,7 @@ pass them as a top-level prop:
165
171
 
166
172
  ```svelte title="src/App.svelte"
167
173
  <script lang="ts">
168
- import { ConsentProvider, manifest } from '@c15t/svelte';
174
+ import { ConsentProvider, manifest } from 'c15t/svelte';
169
175
  import { scripts } from './consent-scripts';
170
176
  </script>
171
177
 
@@ -184,7 +190,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
184
190
 
185
191
  ```svelte title="src/routes/+layout.svelte"
186
192
  <script lang="ts">
187
- import { ConsentRoot } from '@c15t/svelte';
193
+ import { ConsentRoot } from 'c15t/svelte';
188
194
  import { scripts } from '../consent-scripts';
189
195
 
190
196
  let { children, data } = $props();
@@ -240,30 +246,38 @@ A kernel you create yourself needs a loader from
240
246
 
241
247
  ## Options
242
248
 
243
- | Option | Default | Behavior |
244
- | ----------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
245
- | `siteId` | Required | Site ID as a number or string. Set as `window._hjSettings.hjid` and used in the default loader URL. Missing, empty and `0` values log an error and the script does not load. |
246
- | `version` | `6` | Script version, set as `window._hjSettings.hjsv` and the `sv` query parameter of the default loader URL. |
247
- | `scriptUrl` | `https://static.hotjar.com/c/hotjar-<siteId>.js?sv=<version>` | Loader URL override. |
249
+ | Option | Default | Behavior |
250
+ | ----------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
251
+ | `siteId` | Required | Site ID as a number or string. Set as `window._hjSettings.hjid` and used in the default loader URL. If it's missing, empty or `0`, c15t logs an error and never loads Hotjar. |
252
+ | `version` | `6` | Script version, set as `window._hjSettings.hjsv` and the `sv` query parameter of the default loader URL. |
253
+ | `scriptUrl` | `https://static.hotjar.com/c/hotjar-<siteId>.js?sv=<version>` | Loader URL override. |
248
254
 
249
255
  ## Loading and revocation
250
256
 
251
- `hotjar` uses the `measurement` category. When measurement becomes allowed,
252
- the helper sets `window._hjSettings` and a queue-backed `window.hj` stub, each
253
- only when the global is undefined, then loads the Hotjar loader.
257
+ `hotjar` uses the `measurement` category. When `measurement` is allowed, the
258
+ helper sets `window._hjSettings` and a `window.hj` stub that queues calls, then
259
+ loads the Hotjar script. If your page already defines either global, the helper
260
+ leaves it alone.
254
261
 
255
- On revocation the helper removes the loader script element and calls no Hotjar
256
- API. A recording in progress continues until the page unloads, so c15t's
257
- default reload on revocation is what ends it.
262
+ When the visitor withdraws, the helper removes the script element. Hotjar is
263
+ already running by then, so removing the element doesn't stop it. The default
264
+ page reload does. If you set `reloadOnConsentRevoked: false`, Hotjar keeps
265
+ recording until the visitor leaves the page.
258
266
 
259
267
  ## Verify Hotjar
260
268
 
261
- Filter DevTools Network by `hotjar`. After you allow measurement, the
262
- `hotjar-<siteId>.js` request loads from `static.hotjar.com`, and
263
- `window._hjSettings.hjid` holds your site ID. Review a recording of a real
264
- screen in your app to check that Hotjar masks the fields you expect.
265
- `window.hj` still exists after revocation, so check measurement permission
266
- before your own `hj` calls.
269
+ Filter the DevTools Network panel by `hotjar`. After you allow measurement,
270
+ the loader appears and `window._hjSettings.hjid` holds your site ID. If it
271
+ holds a different ID, other code on the page set `_hjSettings` before c15t, and
272
+ the helper left it alone. Find and remove that code. By default
273
+ the loader is `hotjar-<siteId>.js` from `static.hotjar.com`. If you set
274
+ `scriptUrl`, look for that URL instead.
275
+
276
+ Then watch one recording of a real screen in your app. Hotjar decides what to
277
+ mask, not c15t, so check that it hides the fields you expect.
278
+
279
+ `window.hj` stays defined after withdrawal. If your own code calls `hj()`,
280
+ check the measurement permission first.
267
281
 
268
282
  Test in a private window with an opt-in policy. Open DevTools Network, disable
269
283
  the cache and filter by the vendor's domain:
@@ -165,7 +165,7 @@ pass them as a top-level prop:
165
165
 
166
166
  ```svelte title="src/App.svelte"
167
167
  <script lang="ts">
168
- import { ConsentProvider, manifest } from '@c15t/svelte';
168
+ import { ConsentProvider, manifest } from 'c15t/svelte';
169
169
  import { scripts } from './consent-scripts';
170
170
  </script>
171
171
 
@@ -184,7 +184,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
184
184
 
185
185
  ```svelte title="src/routes/+layout.svelte"
186
186
  <script lang="ts">
187
- import { ConsentRoot } from '@c15t/svelte';
187
+ import { ConsentRoot } from 'c15t/svelte';
188
188
  import { scripts } from '../consent-scripts';
189
189
 
190
190
  let { children, data } = $props();
@@ -175,7 +175,7 @@ pass them as a top-level prop:
175
175
 
176
176
  ```svelte title="src/App.svelte"
177
177
  <script lang="ts">
178
- import { ConsentProvider, manifest } from '@c15t/svelte';
178
+ import { ConsentProvider, manifest } from 'c15t/svelte';
179
179
  import { scripts } from './consent-scripts';
180
180
  </script>
181
181
 
@@ -194,7 +194,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
194
194
 
195
195
  ```svelte title="src/routes/+layout.svelte"
196
196
  <script lang="ts">
197
- import { ConsentRoot } from '@c15t/svelte';
197
+ import { ConsentRoot } from 'c15t/svelte';
198
198
  import { scripts } from '../consent-scripts';
199
199
 
200
200
  let { children, data } = $props();
@@ -166,7 +166,7 @@ pass them as a top-level prop:
166
166
 
167
167
  ```svelte title="src/App.svelte"
168
168
  <script lang="ts">
169
- import { ConsentProvider, manifest } from '@c15t/svelte';
169
+ import { ConsentProvider, manifest } from 'c15t/svelte';
170
170
  import { scripts } from './consent-scripts';
171
171
  </script>
172
172
 
@@ -185,7 +185,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
185
185
 
186
186
  ```svelte title="src/routes/+layout.svelte"
187
187
  <script lang="ts">
188
- import { ConsentRoot } from '@c15t/svelte';
188
+ import { ConsentRoot } from 'c15t/svelte';
189
189
  import { scripts } from '../consent-scripts';
190
190
 
191
191
  let { children, data } = $props();
@@ -164,7 +164,7 @@ pass them as a top-level prop:
164
164
 
165
165
  ```svelte title="src/App.svelte"
166
166
  <script lang="ts">
167
- import { ConsentProvider, manifest } from '@c15t/svelte';
167
+ import { ConsentProvider, manifest } from 'c15t/svelte';
168
168
  import { scripts } from './consent-scripts';
169
169
  </script>
170
170
 
@@ -183,7 +183,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
183
183
 
184
184
  ```svelte title="src/routes/+layout.svelte"
185
185
  <script lang="ts">
186
- import { ConsentRoot } from '@c15t/svelte';
186
+ import { ConsentRoot } from 'c15t/svelte';
187
187
  import { scripts } from '../consent-scripts';
188
188
 
189
189
  let { children, data } = $props();
@@ -170,7 +170,7 @@ pass them as a top-level prop:
170
170
 
171
171
  ```svelte title="src/App.svelte"
172
172
  <script lang="ts">
173
- import { ConsentProvider, manifest } from '@c15t/svelte';
173
+ import { ConsentProvider, manifest } from 'c15t/svelte';
174
174
  import { scripts } from './consent-scripts';
175
175
  </script>
176
176
 
@@ -189,7 +189,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
189
189
 
190
190
  ```svelte title="src/routes/+layout.svelte"
191
191
  <script lang="ts">
192
- import { ConsentRoot } from '@c15t/svelte';
192
+ import { ConsentRoot } from 'c15t/svelte';
193
193
  import { scripts } from '../consent-scripts';
194
194
 
195
195
  let { children, data } = $props();
@@ -166,7 +166,7 @@ pass them as a top-level prop:
166
166
 
167
167
  ```svelte title="src/App.svelte"
168
168
  <script lang="ts">
169
- import { ConsentProvider, manifest } from '@c15t/svelte';
169
+ import { ConsentProvider, manifest } from 'c15t/svelte';
170
170
  import { scripts } from './consent-scripts';
171
171
  </script>
172
172
 
@@ -185,7 +185,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
185
185
 
186
186
  ```svelte title="src/routes/+layout.svelte"
187
187
  <script lang="ts">
188
- import { ConsentRoot } from '@c15t/svelte';
188
+ import { ConsentRoot } from 'c15t/svelte';
189
189
  import { scripts } from '../consent-scripts';
190
190
 
191
191
  let { children, data } = $props();
@@ -166,7 +166,7 @@ pass them as a top-level prop:
166
166
 
167
167
  ```svelte title="src/App.svelte"
168
168
  <script lang="ts">
169
- import { ConsentProvider, manifest } from '@c15t/svelte';
169
+ import { ConsentProvider, manifest } from 'c15t/svelte';
170
170
  import { scripts } from './consent-scripts';
171
171
  </script>
172
172
 
@@ -185,7 +185,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
185
185
 
186
186
  ```svelte title="src/routes/+layout.svelte"
187
187
  <script lang="ts">
188
- import { ConsentRoot } from '@c15t/svelte';
188
+ import { ConsentRoot } from 'c15t/svelte';
189
189
  import { scripts } from '../consent-scripts';
190
190
 
191
191
  let { children, data } = $props();
@@ -168,7 +168,7 @@ pass them as a top-level prop:
168
168
 
169
169
  ```svelte title="src/App.svelte"
170
170
  <script lang="ts">
171
- import { ConsentProvider, manifest } from '@c15t/svelte';
171
+ import { ConsentProvider, manifest } from 'c15t/svelte';
172
172
  import { scripts } from './consent-scripts';
173
173
  </script>
174
174
 
@@ -187,7 +187,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
187
187
 
188
188
  ```svelte title="src/routes/+layout.svelte"
189
189
  <script lang="ts">
190
- import { ConsentRoot } from '@c15t/svelte';
190
+ import { ConsentRoot } from 'c15t/svelte';
191
191
  import { scripts } from '../consent-scripts';
192
192
 
193
193
  let { children, data } = $props();
@@ -177,7 +177,7 @@ pass them as a top-level prop:
177
177
 
178
178
  ```svelte title="src/App.svelte"
179
179
  <script lang="ts">
180
- import { ConsentProvider, manifest } from '@c15t/svelte';
180
+ import { ConsentProvider, manifest } from 'c15t/svelte';
181
181
  import { scripts } from './consent-scripts';
182
182
  </script>
183
183
 
@@ -196,7 +196,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
196
196
 
197
197
  ```svelte title="src/routes/+layout.svelte"
198
198
  <script lang="ts">
199
- import { ConsentRoot } from '@c15t/svelte';
199
+ import { ConsentRoot } from 'c15t/svelte';
200
200
  import { scripts } from '../consent-scripts';
201
201
 
202
202
  let { children, data } = $props();
@@ -164,7 +164,7 @@ pass them as a top-level prop:
164
164
 
165
165
  ```svelte title="src/App.svelte"
166
166
  <script lang="ts">
167
- import { ConsentProvider, manifest } from '@c15t/svelte';
167
+ import { ConsentProvider, manifest } from 'c15t/svelte';
168
168
  import { scripts } from './consent-scripts';
169
169
  </script>
170
170
 
@@ -183,7 +183,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
183
183
 
184
184
  ```svelte title="src/routes/+layout.svelte"
185
185
  <script lang="ts">
186
- import { ConsentRoot } from '@c15t/svelte';
186
+ import { ConsentRoot } from 'c15t/svelte';
187
187
  import { scripts } from '../consent-scripts';
188
188
 
189
189
  let { children, data } = $props();
@@ -169,7 +169,7 @@ pass them as a top-level prop:
169
169
 
170
170
  ```svelte title="src/App.svelte"
171
171
  <script lang="ts">
172
- import { ConsentProvider, manifest } from '@c15t/svelte';
172
+ import { ConsentProvider, manifest } from 'c15t/svelte';
173
173
  import { scripts } from './consent-scripts';
174
174
  </script>
175
175
 
@@ -188,7 +188,7 @@ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs
188
188
 
189
189
  ```svelte title="src/routes/+layout.svelte"
190
190
  <script lang="ts">
191
- import { ConsentRoot } from '@c15t/svelte';
191
+ import { ConsentRoot } from 'c15t/svelte';
192
192
  import { scripts } from '../consent-scripts';
193
193
 
194
194
  let { children, data } = $props();
@@ -0,0 +1,94 @@
1
+ ---
2
+ title: Other ads and pixels
3
+ description: Consent-gated helpers for ad platforms and conversion pixels that
4
+ don't need a full guide.
5
+ icon: radar
6
+ group: integrations
7
+ ---
8
+
9
+ Each helper below loads its vendor only after the visitor allows the listed consent category. For setup, see [Integrations overview](./overview.md).
10
+
11
+ ## AdRoll
12
+
13
+ AdRoll retargets site visitors with ads and measures conversions. The helper sends the first `pageView` for you. Waits for `marketing` consent.
14
+
15
+ ```ts title="src/consent-scripts.ts"
16
+ import { adrollPixel } from '@c15t/integrations/adroll';
17
+
18
+ export const scripts = [
19
+ adrollPixel({ advertiserId: 'ADVERTISER_ID', pixelId: 'PIXEL_ID' }),
20
+ ];
21
+ ```
22
+
23
+ | Option | Type | Required | Description |
24
+ | -------------- | -------- | -------- | ----------------------------------------------------------------------------- |
25
+ | `advertiserId` | `string` | Yes | Advertiser ID from Analytics > Insights > Website > View Pixel. |
26
+ | `pixelId` | `string` | Yes | Pixel ID from the same snippet. |
27
+ | `scriptUrl` | `string` | No | Loader URL. Defaults to `https://s.adroll.com/j/<advertiserId>/roundtrip.js`. |
28
+
29
+ **When consent is withdrawn:** AdRoll has no API to stop it, so the helper leaves it on the page. Keep c15t's default `reloadOnConsentRevoked` so the page reload removes it.
30
+
31
+ * In AdRoll, set Settings > Data Collection > Visitor Consent to **Use your existing Consent Banner**. Otherwise AdRoll can load its own banner.
32
+
33
+ ## LiveIntent
34
+
35
+ LiveIntent's LiveConnect tag identifies visitors for people-based ad targeting and measurement. Waits for `marketing` consent.
36
+
37
+ ```ts title="src/consent-scripts.ts"
38
+ import { liveIntentTag } from '@c15t/integrations/liveintent';
39
+
40
+ export const scripts = [liveIntentTag({ tagId: 'YOUR_TAG_ID' })];
41
+ ```
42
+
43
+ | Option | Type | Required | Description |
44
+ | ----------- | ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
45
+ | `tagId` | `string` | Yes | Tag filename from your LiveConnect base tag, without `.min.js`. |
46
+ | `events` | `LiveIntentEvent[]` | No | Event objects queued once on the first grant, such as `{ event: 'conversion', name: 'purchase' }`. Use the fields from your account's event tags. |
47
+ | `scriptUrl` | `string` | No | Loader URL. Defaults to `https://b-code.liadm.com/<tagId>.min.js`. |
48
+
49
+ **When consent is withdrawn:** LiveConnect has no API to stop it, so the helper leaves it on the page. Keep c15t's default `reloadOnConsentRevoked` so the page reload removes it.
50
+
51
+ * Don't test with the public `a-00xx` tag from LiveIntent's examples. It's live production code, not a sandbox.
52
+ * Where GDPR applies, LiveIntent also reads the TCF string. LiveIntent's guide lists purposes 1 to 4, but the served bundle asks for more. Confirm your account's requirements with LiveIntent.
53
+
54
+ ## The Trade Desk
55
+
56
+ The Trade Desk Universal Pixel records conversions and builds ad audiences. Waits for `marketing` consent.
57
+
58
+ ```ts title="src/consent-scripts.ts"
59
+ import { theTradeDeskPixel } from '@c15t/integrations/the-trade-desk';
60
+
61
+ export const scripts = [
62
+ theTradeDeskPixel({ advertiserId: 'ADVERTISER_ID', pixelIds: ['PIXEL_ID'] }),
63
+ ];
64
+ ```
65
+
66
+ | Option | Type | Required | Description |
67
+ | ---------------------- | ---------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------- |
68
+ | `advertiserId` | `string` | Yes | Advertiser ID from your Universal Pixel snippet. |
69
+ | `pixelIds` | `string[]` | Yes | One or more Universal Pixel IDs. A blank entry skips the helper. |
70
+ | `enableCookieSyncing` | `boolean` | No | Set `false` to turn off cookie syncing. Unset uses the vendor default. |
71
+ | `dataProcessingOption` | `{ policies: string[]; region: string }` | No | Limited data use setting, such as `{ policies: ['LDU'], region: 'US-CO' }`. It doesn't replace consent. |
72
+ | `scriptUrl` | `string` | No | Loader URL. Defaults to `https://js.adsrvr.org/up_loader.3.0.0.js`. |
73
+
74
+ **When consent is withdrawn:** The Trade Desk has no API to stop its SDK, so the helper leaves it on the page. Keep c15t's default `reloadOnConsentRevoked` so the page reload removes it.
75
+
76
+ * Walmart DSP accounts use a different loader. Set `scriptUrl` to `https://azjs.adsrvr.org/thetradedesk-ads/up_loader.3.0.0.js`.
77
+ * `enableCookieSyncing: false` doesn't stop all cookies. The Trade Desk still sets its `TDID` cookie on `adsrvr.org`.
78
+
79
+ ## Vector
80
+
81
+ Vector identifies the people and companies visiting your site and builds advertising audiences from their activity. Waits for `marketing` consent.
82
+
83
+ ```ts title="src/consent-scripts.ts"
84
+ import { vector } from '@c15t/integrations/vector';
85
+
86
+ export const scripts = [vector({ pixelId: 'YOUR_PIXEL_ID' })];
87
+ ```
88
+
89
+ | Option | Type | Required | Description |
90
+ | ----------- | -------- | -------- | ------------------------------------------------------------- |
91
+ | `pixelId` | `string` | Yes | Pixel ID from **Settings > Pixel** in Vector. |
92
+ | `scriptUrl` | `string` | No | Custom SDK URL. Defaults to `https://cdn.vector.co/pixel.js`. |
93
+
94
+ **When consent is withdrawn:** Vector has no stop API, so c15t reloads the page to stop it. Keep `reloadOnConsentRevoked` on.
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Other analytics tools
3
+ description: Consent-gated helpers for analytics tools that don't need a full guide.
4
+ icon: chart-line
5
+ group: integrations
6
+ ---
7
+
8
+ Each helper below loads its vendor only after the visitor allows the listed consent category. For setup, see [Integrations overview](./overview.md).
9
+
10
+ ## Lucky Orange
11
+
12
+ Lucky Orange records sessions and builds heatmaps. Waits for `measurement` consent by default.
13
+
14
+ ```ts title="src/lucky-orange.ts"
15
+ import { luckyOrange } from '@c15t/integrations/lucky-orange';
16
+
17
+ export const scripts = [luckyOrange({ siteId: 'YOUR_SITE_ID' })];
18
+ ```
19
+
20
+ | Option | Type | Required | Description |
21
+ | ----------- | ----------------- | -------- | ------------------------------------------------------------------------------------------------------ |
22
+ | `siteId` | `string` | Yes | Site ID from Lucky Orange. |
23
+ | `category` | Consent condition | No | Category or condition that must be allowed. Defaults to `'measurement'`. |
24
+ | `scriptUrl` | `string` | No | Custom or proxied loader URL. Defaults to `https://tools.luckyorange.com/core/lo.js?site-id=<siteId>`. |
25
+
26
+ **When consent is withdrawn:** the helper calls `LO.privacy.setConsentStatus(false)`. Recording code already on the page can't be unloaded, so keep c15t's default page reload.
27
+
28
+ * Turn on **Require Consent** in the Lucky Orange dashboard. The helper grants consent through Lucky Orange's privacy API after the visitor allows it.
29
+ * The helper doesn't call `optOut()`, because that writes an opt-out cookie that lasts two years and gets in the way if the visitor grants consent again.
30
+ * A proxy `scriptUrl` must keep `lo.js` in its path. Lucky Orange finds the site ID by looking for that file name.
31
+
32
+ ## Pendo
33
+
34
+ Pendo records product usage and shows in-app guides. Waits for `measurement` consent by default.
35
+
36
+ ```ts title="src/pendo.ts"
37
+ import { pendo } from '@c15t/integrations/pendo';
38
+
39
+ export const scripts = [pendo({ apiKey: 'YOUR_API_KEY' })];
40
+ ```
41
+
42
+ | Option | Type | Required | Description |
43
+ | ------------------- | ------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
44
+ | `apiKey` | `string` | Yes | Web agent API key from Pendo. |
45
+ | `visitor` | `Record<string, unknown>` | No | Visitor metadata passed to `pendo.initialize()`. |
46
+ | `account` | `Record<string, unknown>` | No | Account metadata passed to `pendo.initialize()`. |
47
+ | `initializeOptions` | `Record<string, unknown>` | No | Other `initialize()` options, such as `disableCookies` or `excludeAllText`. |
48
+ | `category` | Consent condition | No | Category or condition that must be allowed. Defaults to `'measurement'`. |
49
+ | `scriptUrl` | `string` | No | Custom or proxied agent URL. Defaults to `https://cdn.pendo.io/agent/static/<apiKey>/pendo.js`. |
50
+
51
+ **When consent is withdrawn:** the helper calls `pendo.stopSendingEvents()`. If consent comes back on the same page, it calls `startSendingEvents()` and keeps the same visitor identity. c15t still reloads the page by default; keep the reload if the next page must run without Pendo.
52
+
53
+ * The helper never calls `clearSession()`, because that starts a new anonymous visitor. If a visitor signs out while consent is granted, call `pendo.clearSession()` yourself before you identify the next visitor.
54
+ * Stopping events doesn't delete Pendo's cookies or local storage, and guides already on the page stay there.
55
+
56
+ ## RB2B
57
+
58
+ RB2B identifies the companies and US visitors behind site traffic for sales outreach. Waits for `marketing` consent.
59
+
60
+ ```ts title="src/consent-scripts.ts"
61
+ import { rb2b } from '@c15t/integrations/rb2b';
62
+
63
+ export const scripts = [rb2b({ accountKey: 'YOUR_RB2B_KEY' })];
64
+ ```
65
+
66
+ | Option | Type | Required | Description |
67
+ | ------------ | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- |
68
+ | `accountKey` | `string` | Yes | Account key from the `reb2b.load` call on RB2B's Script Setup page. |
69
+ | `scriptUrl` | `string` | No | Loader URL from your dashboard snippet. Defaults to `https://ddwl4m2hdecbv.cloudfront.net/b/<accountKey>/<accountKey>.js.gz`. |
70
+
71
+ **When consent is withdrawn:** RB2B has no stop API, so c15t reloads the page to stop it. Keep `reloadOnConsentRevoked` on.
72
+
73
+ * Authorize your domain first: in RB2B, open **Script**, choose **Add a Domain** and save it. RB2B's script doesn't run on domains you haven't added.
74
+ * `scriptUrl` must stay on RB2B's CloudFront or S3 hosts, under `/b/<accountKey>/`. RB2B checks the script's own URL, so a proxy fails, and the helper logs an error and skips loading for other URLs.
75
+ * RB2B runs once per page load, not on client-side route changes. To count a new page view, use full-page navigation, such as a plain `<a href>`.
76
+
77
+ ## Statable
78
+
79
+ Statable is cookieless web analytics. Waits for `measurement` consent.
80
+
81
+ ```ts title="src/consent-scripts.ts"
82
+ import { statableAnalytics } from '@c15t/integrations/statable-analytics';
83
+
84
+ export const scripts = [statableAnalytics({ siteId: '12345' })];
85
+ ```
86
+
87
+ | Option | Type | Required | Description |
88
+ | ------------- | -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
89
+ | `siteId` | `string` or `number` | Yes | Numeric site ID from **Site settings > Tracking Code** in Statable. |
90
+ | `scriptUrl` | `string` | No | Loader URL for your own CDN. Each `{siteId}` is replaced with the ID. Defaults to `https://statable.com/js/{siteId}/s.js`. |
91
+ | `trackingApi` | `string` | No | Full ingestion endpoint. Defaults to the loader origin plus `/api/event`. |
92
+
93
+ **When consent is withdrawn:** Statable has no stop API, so c15t reloads the page to stop the tracker. Keep `reloadOnConsentRevoked` on.
94
+
95
+ * The `/js/<siteId>/s.js` loader is only on Statable's paid plans. The Hobby plan uses a widget with a different loader, which this helper doesn't support.
96
+ * If your CDN serves the loader but doesn't serve or proxy `/api/event`, set `trackingApi` to the full ingestion URL:
97
+
98
+ ```ts title="src/consent-scripts.ts"
99
+ import { statableAnalytics } from '@c15t/integrations/statable-analytics';
100
+
101
+ export const scripts = [
102
+ statableAnalytics({
103
+ scriptUrl: 'https://cdn.example.com/js/{siteId}/s.js',
104
+ siteId: '12345',
105
+ trackingApi: 'https://analytics.example.com/api/event',
106
+ }),
107
+ ];
108
+ ```
@@ -0,0 +1,112 @@
1
+ ---
2
+ title: Other chat and support tools
3
+ description: Consent-gated helpers for chat and support tools that don't need a full guide.
4
+ icon: messages-square
5
+ group: integrations
6
+ ---
7
+
8
+ Each helper below loads its vendor only after the visitor allows the listed consent category. For setup, see [Integrations overview](./overview.md).
9
+
10
+ ## Ada
11
+
12
+ Ada Messaging adds an Ada AI Agent chat widget to your site. Waits for
13
+ `functionality` consent.
14
+
15
+ ```ts title="src/consent-scripts.ts"
16
+ import { ada } from '@c15t/integrations/ada';
17
+
18
+ export const scripts = [ada({ handle: 'YOUR_ADA_HANDLE' })];
19
+ ```
20
+
21
+ | Option | Type | Required | Description |
22
+ | --------- | -------- | -------- | -------------------------------------------------------------------------------------------------- |
23
+ | `handle` | `string` | Yes | Your AI Agent's public handle, from your Ada team. A blank handle logs an error and nothing loads. |
24
+ | `cluster` | `string` | No | Regional cluster, such as `eu`, `us2` or `maple`. Set it only when Ada gives you one. |
25
+ | `domain` | `string` | No | Ada base-domain override. Set it only when Ada gives you one. |
26
+
27
+ The helper imports Ada's Messaging Web SDK from
28
+ `https://messaging-assets.ada.support/sdk.js` and keeps its interface private,
29
+ so `window.adaEmbed` stays unset. Remove any other Ada snippet or `embed2.js`
30
+ tag. Ada allows only one Messaging interface per page.
31
+
32
+ **When consent is withdrawn:** the helper calls Ada's `stop()`, which removes
33
+ the widget's frames. c15t then reloads the page to end any SDK work still
34
+ running.
35
+
36
+ * Use one Ada configuration per page.
37
+ * Ada has no consent API. The helper can only start and stop the widget.
38
+ * `stop()` doesn't erase stored conversations, tokens or cookies. The visitor's
39
+ conversation can still be there after a reload.
40
+ * An SDK import that has already started can't be cancelled. The helper skips
41
+ starting the widget when it finishes, but the SDK can still write its own
42
+ storage. Keep `reloadOnConsentRevoked` enabled.
43
+
44
+ ## Gorgias Chat
45
+
46
+ Gorgias Chat adds the Gorgias support chat widget to your store or site. Waits
47
+ for `functionality` consent.
48
+
49
+ ```ts title="src/consent-scripts.ts"
50
+ import { gorgiasChat } from '@c15t/integrations/gorgias';
51
+
52
+ export const scripts = [gorgiasChat({ appKey: 'YOUR_GORGIAS_APP_KEY' })];
53
+ ```
54
+
55
+ | Option | Type | Required | Description |
56
+ | --------- | ---------- | -------- | --------------------------------------------------------------------------------------------------- |
57
+ | `appKey` | `string` | Yes | Public app key from your Gorgias installation snippet. A blank key logs an error and nothing loads. |
58
+ | `version` | `2` or `3` | No | Installation snippet version. Defaults to `3`. |
59
+
60
+ Remove any other Gorgias snippet or store app installation, or Gorgias can load
61
+ before consent. Without `measurement` consent, the helper calls
62
+ `GorgiasChat.disableSegment()` when the widget is ready.
63
+
64
+ **When consent is withdrawn:** c15t removes the loader and calls
65
+ `disableSegment()` if the widget is ready. Gorgias has no shutdown API, so keep
66
+ `reloadOnConsentRevoked` enabled. The page reload stops the widget.
67
+
68
+ * Segment stays off for the rest of the page after `disableSegment()`, even if
69
+ the visitor then grants `measurement`. Gorgias has no call to turn it back on.
70
+ A reload with `measurement` allowed turns it back on.
71
+ * The v3 snippet has the key at the end of
72
+ `https://config.gorgias.chat/bundle-loader/YOUR_APP_KEY`. A v2 snippet uses
73
+ `applicationId` instead. Pass that value as `appKey` with `version: 2`.
74
+ * A placeholder or deleted key still returns HTTP 200, with only a warning
75
+ that the installation is incorrect. Check that the widget appears to confirm
76
+ the key works.
77
+
78
+ ## Zendesk Messaging
79
+
80
+ Zendesk Messaging adds the Zendesk support chat widget to your site. It doesn't
81
+ cover Web Widget Classic. Waits for `functionality` consent.
82
+
83
+ ```ts title="src/consent-scripts.ts"
84
+ import { zendeskWidget } from '@c15t/integrations/zendesk';
85
+
86
+ export const scripts = [zendeskWidget({ key: 'YOUR_ZENDESK_WIDGET_KEY' })];
87
+ ```
88
+
89
+ | Option | Type | Required | Description |
90
+ | ---------- | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
91
+ | `key` | `string` | Yes | Widget key from **Admin Center > Channels > Messaging and social > Messaging**, on the widget's **Installation** page. A blank key logs an error and nothing loads. |
92
+ | `category` | Consent condition | No | Consent needed to load the widget. Defaults to `functionality`. |
93
+
94
+ The helper passes consent to Zendesk's
95
+ [cookie setting](https://developer.zendesk.com/api-reference/widget-messaging/web/core/#set-cookies)
96
+ before the widget loads, and again on every consent change:
97
+
98
+ | Consent | Zendesk cookie setting |
99
+ | --------------------------------- | ---------------------- |
100
+ | `functionality` and `measurement` | `all` |
101
+ | `functionality` only | `functional` |
102
+ | `functionality` withdrawn | `none` |
103
+
104
+ **When consent is withdrawn:** the helper sends `none`. Zendesk hides the
105
+ widget and deletes its local and session storage. c15t then reloads the page to
106
+ stop the widget code that already ran.
107
+
108
+ * Use one widget key per page. Zendesk has one global `zE` API, so two widgets
109
+ on the same page control each other.
110
+ * Removing the helper from your configuration doesn't clear the conversation.
111
+ It sends no `none`. Revoke consent first if you need the widget storage
112
+ cleared.