@c15t/react 3.2.0-canary.0 → 3.2.1

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 (50) hide show
  1. package/AGENTS.md +33 -10
  2. package/README.md +5 -7
  3. package/dist/styles.tw3.css +2 -2
  4. package/dist/version.js +1 -1
  5. package/dist-types/version.d.ts +1 -1
  6. package/docs/README.md +33 -10
  7. package/docs/concepts/choose-your-setup.md +8 -9
  8. package/docs/concepts/modes.md +5 -3
  9. package/docs/customization/stylesheets.md +39 -0
  10. package/docs/frameworks/react/hooks.md +2 -1
  11. package/docs/frameworks/react/quickstart.md +3 -3
  12. package/docs/frameworks/react/upgrade-v3.md +2 -2
  13. package/docs/integrations/activecampaign.md +297 -0
  14. package/docs/integrations/ada.md +396 -0
  15. package/docs/integrations/adobe-target.md +460 -0
  16. package/docs/integrations/adroll.md +336 -0
  17. package/docs/integrations/amazon-ads.md +424 -0
  18. package/docs/integrations/appcues.md +368 -0
  19. package/docs/integrations/attentive.md +313 -0
  20. package/docs/integrations/building-integrations.md +29 -16
  21. package/docs/integrations/clearbit.md +1 -1
  22. package/docs/integrations/customer-io.md +369 -0
  23. package/docs/integrations/databuddy.md +139 -50
  24. package/docs/integrations/default-com.md +497 -0
  25. package/docs/integrations/dynamic-yield.md +373 -0
  26. package/docs/integrations/fullstory.md +298 -0
  27. package/docs/integrations/gainsight-px.md +418 -0
  28. package/docs/integrations/gorgias.md +365 -0
  29. package/docs/integrations/hubspot.md +529 -0
  30. package/docs/integrations/insider.md +550 -0
  31. package/docs/integrations/liveintent.md +327 -0
  32. package/docs/integrations/lucky-orange.md +336 -0
  33. package/docs/integrations/marketo.md +309 -0
  34. package/docs/integrations/optimizely.md +411 -0
  35. package/docs/integrations/oracle-eloqua.md +301 -0
  36. package/docs/integrations/overview.md +124 -111
  37. package/docs/integrations/pendo.md +339 -0
  38. package/docs/integrations/rb2b.md +363 -0
  39. package/docs/integrations/salesforce-pardot.md +342 -0
  40. package/docs/integrations/statable-analytics.md +345 -0
  41. package/docs/integrations/the-trade-desk.md +328 -0
  42. package/docs/integrations/vector.md +333 -0
  43. package/docs/integrations/wisepops.md +416 -0
  44. package/docs/integrations/zendesk.md +359 -0
  45. package/package.json +8 -8
  46. package/docs/integrations/other-ads-and-pixels.md +0 -94
  47. package/docs/integrations/other-analytics.md +0 -108
  48. package/docs/integrations/other-chat-and-support.md +0 -112
  49. package/docs/integrations/other-email-and-sms.md +0 -156
  50. package/docs/integrations/other-experience.md +0 -222
@@ -0,0 +1,416 @@
1
+ ---
2
+ title: Wisepops
3
+ description: Load Wisepops popups, bars, embeds and notification feeds after
4
+ marketing consent with c15t. Configure its site ID, cookie options and reload
5
+ behavior.
6
+ seoTitle: Wisepops cookie consent with c15t
7
+ seoDescription: Load Wisepops after marketing consent, configure its site ID and
8
+ cookie options, and use c15t's reload on consent revocation to stop the
9
+ running SDK.
10
+ icon: megaphone
11
+ group: integrations
12
+ ---
13
+
14
+ The c15t `wisepops` helper loads Wisepops only after `marketing` has consent.
15
+ Before then, it creates no Wisepops snippet queue and writes no Wisepops
16
+ storage. It queues `defaultConsent: 'denied'` before the SDK runs and calls
17
+ `wisepops('consent', 'granted')` after the loader finishes with consent still
18
+ allowed. Keep c15t's default reload on revocation enabled because Wisepops
19
+ cannot revoke consent programmatically.
20
+
21
+ ## Configure Wisepops
22
+
23
+ In Wisepops, open **Settings > Install Wisepops** and copy your site's setup
24
+ code. The loader URL contains your public site ID in its `h` parameter:
25
+ `https://wisepops.net/loader.js?v=3&h=YOUR_WISEPOPS_SITE_ID`.
26
+
27
+ Use the c15t helper in place of the Wisepops installation snippet. Remove
28
+ other Wisepops installations, including any tag manager or CMS plugin that
29
+ loads it, so they do not bypass c15t's consent check. Use one Wisepops site
30
+ ID per document. Reload the page when changing site IDs; replacing a helper
31
+ configuration does not reinitialize an SDK that has already started.
32
+
33
+ | Package manager | Command |
34
+ | :-------------- | :------------------------------- |
35
+ | npm | `npm install @c15t/integrations` |
36
+ | pnpm | `pnpm add @c15t/integrations` |
37
+ | yarn | `yarn add @c15t/integrations` |
38
+ | bun | `bun add @c15t/integrations` |
39
+
40
+ The `scripts` export below uses marketing consent. `experienceScripts` is an
41
+ alternative for campaigns whose purpose and policy call for experience
42
+ consent. Register one array.
43
+
44
+ ```ts title="src/consent-scripts.ts"
45
+ import { wisepops } from '@c15t/integrations/wisepops';
46
+
47
+ export const scripts = [wisepops({ siteId: 'YOUR_WISEPOPS_SITE_ID' })];
48
+
49
+ export const experienceScripts = [
50
+ wisepops({
51
+ category: 'experience',
52
+ options: { browserStorage: true },
53
+ siteId: 'YOUR_WISEPOPS_SITE_ID',
54
+ }),
55
+ ];
56
+ ```
57
+
58
+ ## Register the scripts
59
+
60
+ Complete your [framework quickstart](https://c15t.com/docs/frameworks) first. Keep its Inth
61
+ endpoint, policy, styles and consent UI. Remove the vendor's original script,
62
+ SDK initializer or tag-manager entry, so the vendor loads only through c15t.
63
+
64
+ The vendor pages put the helper in `src/consent-scripts.ts`. If your framework
65
+ quickstart already has a `scripts` array, such as the one in `c15t.config.ts`
66
+ in the Next.js guide, add the helper to that array instead of creating a
67
+ second file.
68
+ The `scripts` export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
69
+ point for your framework below. These are edits to that provider, not a second
70
+ provider.
71
+
72
+ **Next.js**
73
+
74
+ Add the configuration to `scripts` in `c15t.config.ts`, next to
75
+ `next.config.ts`:
76
+
77
+ ```ts title="c15t.config.ts"
78
+ import { defineConsentConfig } from 'c15t/next';
79
+ import { scripts } from './src/consent-scripts';
80
+
81
+ export default defineConsentConfig({ scripts });
82
+ ```
83
+
84
+ Keep the rest of your config, such as `mode` and `routePrefix`, in the
85
+ same call. `ConsentRoot` reads the config in the browser, so the layout
86
+ keeps passing only `state`. App Router, Pages Router and static export all
87
+ read the same file. See
88
+ [Next.js scripts and embeds](https://c15t.com/docs/frameworks/next/scripts).
89
+
90
+ **TanStack Start**
91
+
92
+ Import the configuration into your root route and pass it to the existing
93
+ `ConsentRoot` as a top-level prop. Keep the loader from the
94
+ [TanStack Start quickstart](https://c15t.com/docs/frameworks/tanstack-start/quickstart):
95
+
96
+ ```tsx title="src/routes/__root.tsx"
97
+ import { scripts } from '../consent-scripts';
98
+
99
+ <ConsentRoot state={consent} scripts={scripts}>
100
+ ```
101
+
102
+ Import vendor helpers in the root route module, not in a server function.
103
+ A server function's return value must be serializable, and script
104
+ configurations carry callbacks. See
105
+ [TanStack Start scripts](https://c15t.com/docs/frameworks/tanstack-start/scripts).
106
+
107
+ **React**
108
+
109
+ Add the configuration to the existing `ConsentProvider` options, next to
110
+ `mode`:
111
+
112
+ ```tsx title="src/consent.tsx"
113
+ import { scripts } from './consent-scripts';
114
+
115
+ <ConsentProvider options={{ mode, scripts }}>
116
+ ```
117
+
118
+ `mode` is the `manifest()` value from the
119
+ [React quickstart](../frameworks/react/quickstart.md). Keep the banner,
120
+ dialog and preferences link inside the provider. See
121
+ [React scripts and embeds](../frameworks/react/scripts.md).
122
+
123
+ **Nuxt**
124
+
125
+ Register the scripts under the `c15t` key in `app/app.config.ts`. Adjust the
126
+ relative import to where you created `consent-scripts.ts`:
127
+
128
+ ```ts title="app/app.config.ts"
129
+ import { scripts } from '../src/consent-scripts';
130
+
131
+ export default defineAppConfig({
132
+ c15t: { scripts },
133
+ });
134
+ ```
135
+
136
+ The Nuxt module merges this over its options in `nuxt.config.ts` and starts
137
+ one script loader in the browser after hydration, once it has applied the
138
+ visitor's stored choice and privacy signals. Keep `scripts` out of
139
+ `nuxt.config.ts`, which reaches the browser as JSON and drops the vendor
140
+ callbacks. Write the vendor IDs into `consent-scripts.ts`. See
141
+ [Nuxt scripts and embeds](https://c15t.com/docs/frameworks/nuxt/scripts).
142
+
143
+ **Vue**
144
+
145
+ Pass the scripts to the existing `c15tVue` plugin call in `src/main.ts`:
146
+
147
+ ```ts title="src/main.ts"
148
+ import { c15tVue, manifest } from 'c15t/vue/vue-plugin';
149
+ import { scripts } from './consent-scripts';
150
+
151
+ app.use(c15tVue, {
152
+ mode: manifest(),
153
+ scripts,
154
+ });
155
+ ```
156
+
157
+ Keep your existing `mode` and other options. The plugin starts one
158
+ script loader when the app mounts, after it has applied the visitor's stored
159
+ choice. Do not also call `createScriptLoader` from a component. See
160
+ [Vue scripts and embeds](https://c15t.com/docs/frameworks/vue/scripts).
161
+
162
+ **Astro**
163
+
164
+ Add the scripts to the client entrypoint from the
165
+ [Astro quickstart](https://c15t.com/docs/frameworks/astro/quickstart), `src/c15t.client.ts`,
166
+ which the integration finds on its own. Keep `astro.config.mjs` as it is.
167
+ If the module already exports scripts, combine the two arrays.
168
+
169
+ ```ts title="src/c15t.client.ts"
170
+ import type { C15tClientOptionsExtension } from 'c15t/astro';
171
+ import { scripts } from './consent-scripts';
172
+
173
+ export default { scripts } satisfies C15tClientOptionsExtension;
174
+ ```
175
+
176
+ Vendor helpers contain callbacks, and the integration options in
177
+ `astro.config.mjs` are serialized into the page, so do not put helpers in
178
+ the integration's `scripts` option. The integration passes the client
179
+ entrypoint to the one runtime every page shares, including across
180
+ `ClientRouter` navigation.
181
+
182
+ **Svelte**
183
+
184
+ Import the scripts in the component that owns your existing provider and
185
+ pass them as a top-level prop:
186
+
187
+ ```svelte title="src/App.svelte"
188
+ <script lang="ts">
189
+ import { ConsentProvider, manifest } from 'c15t/svelte';
190
+ import { scripts } from './consent-scripts';
191
+ </script>
192
+
193
+ <ConsentProvider mode={manifest()} {scripts}>
194
+ <!-- Keep your application, consent UI and preferences link here. -->
195
+ </ConsentProvider>
196
+ ```
197
+
198
+ Retain the styles and consent UI from the [Svelte quickstart](https://c15t.com/docs/frameworks/svelte/quickstart).
199
+ The provider owns the loader and disposes it on unmount.
200
+
201
+ **SvelteKit**
202
+
203
+ Add the scripts to the existing `ConsentRoot` in the root layout. Keep the
204
+ handle and the layout load from the [SvelteKit quickstart](https://c15t.com/docs/frameworks/sveltekit/quickstart).
205
+
206
+ ```svelte title="src/routes/+layout.svelte"
207
+ <script lang="ts">
208
+ import { ConsentRoot } from 'c15t/svelte';
209
+ import { scripts } from '../consent-scripts';
210
+
211
+ let { children, data } = $props();
212
+ </script>
213
+
214
+ <ConsentRoot state={data.consent} {scripts}>
215
+ {@render children()}
216
+ <!-- Keep your consent UI and preferences link here. -->
217
+ </ConsentRoot>
218
+ ```
219
+
220
+ Import vendor helpers in the layout component, not in `+layout.server.ts`:
221
+ a server load cannot send functions to the browser. Prerendered, static and
222
+ SPA-mode pages use the same `scripts` prop. If you pass an externally owned
223
+ `runtime` to the provider, register scripts when creating that runtime instead.
224
+
225
+ **HTML**
226
+
227
+ The helpers in `@c15t/integrations` are ES modules that need a bundler. On a
228
+ page that loads the c15t script tag, paste the vendor's own snippet instead
229
+ and keep it inert until its category is allowed:
230
+
231
+ ```html
232
+ <script type="text/plain" data-c15t-category="measurement">
233
+ // The vendor's snippet, unchanged
234
+ </script>
235
+ ```
236
+
237
+ Use the category this guide names for the vendor. c15t runs the snippet
238
+ once that category is allowed, and reloads the page when the visitor
239
+ withdraws it. Helper options on this page, such as `loadMode`, do not apply
240
+ to a pasted snippet. See [HTML scripts](https://c15t.com/docs/frameworks/html/scripts).
241
+
242
+ **JavaScript**
243
+
244
+ Pass the scripts to `init()` from `@c15t/browser`, next to your mode:
245
+
246
+ ```ts
247
+ import { init, manifest } from '@c15t/browser';
248
+ import { scripts } from './consent-scripts';
249
+
250
+ const consent = init({
251
+ mode: manifest(),
252
+ scripts,
253
+ });
254
+ ```
255
+
256
+ Keep the mode from your quickstart. With
257
+ `createConsentRuntime` from `c15t/runtime`, pass `scripts` to it instead.
258
+ A kernel you create yourself needs a loader from
259
+ `c15t/modules/script-loader`. Attach one loader per kernel. See
260
+ [JavaScript scripts](https://c15t.com/docs/frameworks/javascript/scripts).
261
+
262
+ To use the experience alternative, change the registration example's import
263
+ to `import { experienceScripts as scripts } from './consent-scripts'`, adjusting
264
+ the relative path for your framework. It also enables Wisepops localStorage.
265
+
266
+ ## Options
267
+
268
+ | Option | Default | Behavior |
269
+ | ------------------------ | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
270
+ | `siteId` | Required | Public site ID from the setup snippet's `h` parameter. Trimmed and URL-encoded. A missing or blank value logs an error and skips the loader. |
271
+ | `category` | `'marketing'` | Consent category or condition required before any Wisepops setup. Use `'experience'` if it matches your campaign's purpose and policy. |
272
+ | `options.autoPageview` | Wisepops v3 default, `'url'` | `'url'` checks for campaigns after URL changes. `'init'` checks only after initialization. `false` disables automatic pageviews. |
273
+ | `options.browserStorage` | Omitted; new visitors use cookies | `true` stores visitor data in localStorage instead of cookies and migrates existing cookies. The data is then separate for each origin and cannot be shared across subdomains. Wisepops can reuse localStorage selected on an earlier visit. |
274
+ | `options.cookieMaxSize` | Wisepops keeps each cookie under 3 KB | Cookie size limit in bytes. Wisepops removes older visitor history when it reaches the limit. For example, `1024` sets a 1 KB limit. |
275
+ | `nonce` | None | CSP nonce for the c15t-managed loader. A nonce from your consent provider also applies. This does not set a nonce on resources created by Wisepops. |
276
+
277
+ The helper always sets `defaultConsent: 'denied'`; it is not a configurable
278
+ option. The helper grants Wisepops cookie consent only after c15t permits
279
+ the mapped category and the vendor. It has no `alwaysLoad` mode.
280
+
281
+ The helper's `options` are bootstrap configuration, queued before its loader
282
+ runs. Changing the configuration object does not update an SDK already
283
+ running on the page. Set these values before registering the scripts.
284
+
285
+ ### Single-page applications
286
+
287
+ The helper uses Wisepops' v3 loader, whose default `autoPageview: 'url'`
288
+ detects URL changes. With `autoPageview: false`, call the browser SDK through
289
+ `window.wisepops?.('pageview')` after your router updates the URL, only while
290
+ the mapped category and Wisepops vendor are allowed. Recheck permission on
291
+ every manual call. The snippet queue can remain after revocation, so the
292
+ existence of `window.wisepops` alone is not a consent check.
293
+
294
+ Avoid sending manual pageviews alongside automatic ones. Duplicate pageviews
295
+ can cause campaigns to appear and disappear immediately. `autoPageview: false`
296
+ does not stop an SDK that has already started.
297
+
298
+ ## Loading and revocation
299
+
300
+ Once the mapped consent allows Wisepops, c15t creates `window.wisepops` with
301
+ its snippet queue and timestamp, queues the runtime options and appends the
302
+ loader to `<head>`. After the SDK loads, c15t grants Wisepops cookie consent.
303
+ If c15t removes a downloading loader after revocation, the helper ignores
304
+ its later load event and sends no consent grant.
305
+
306
+ Wisepops' own denied mode still displays campaigns and uses session-only
307
+ cookies. This helper waits for c15t consent before loading Wisepops at all.
308
+ Do not install Wisepops separately to use its denied mode alongside this
309
+ helper.
310
+
311
+ On revocation, c15t removes the loader and reloads the page by default. The
312
+ new page does not load Wisepops while the mapped consent is denied. The
313
+ helper does not call `wisepops('consent', 'denied')`: Wisepops documents that
314
+ this call produces an error. The reviewed Wisepops documentation provides no
315
+ shutdown or destroy call for the helper to use.
316
+
317
+ Keep `reloadOnConsentRevoked` enabled. Setting it to `false` leaves the
318
+ already-running SDK, displayed campaigns, timers and listeners active.
319
+ Removing a script element also cannot guarantee that an in-flight download
320
+ will never execute. A reload ends the document; it does not erase data
321
+ already stored by Wisepops.
322
+
323
+ ## Cookies and browser storage
324
+
325
+ Wisepops documents the following first-party cookies on your site's domain.
326
+ Actual values and lifetimes can vary with its configuration and the browser:
327
+
328
+ | Cookie | Documented lifetime |
329
+ | ------------------ | ------------------- |
330
+ | `wisepops_session` | Session |
331
+ | `wisepops_visitor` | 750 days |
332
+ | `wisepops_noshow` | 2 years |
333
+ | `wisepops_props` | 2 years |
334
+ | `wisepops_visits` | 2 years |
335
+ | `wisepops_tld` | Session |
336
+ | `wisepops` | 2 years |
337
+
338
+ With `options.browserStorage: true`, Wisepops moves visitor data to
339
+ localStorage. c15t does not automatically delete Wisepops cookies or
340
+ localStorage on revocation. Your cleanup can remove only browser-accessible
341
+ data on domains, paths and origins your application can reach. It cannot
342
+ clear HttpOnly cookies or vendor-side records. Wisepops can remember an earlier
343
+ consent grant in its stored state, so reloading with `defaultConsent: 'denied'`
344
+ alone does not reset that grant. After c15t revocation, keep Wisepops blocked
345
+ on the new page.
346
+
347
+ Wisepops automatically integrates with Shopify Customer Privacy. Check
348
+ Wisepops' [Shopify consent behavior](https://support.wisepops.com/en/articles/12679556-cookie-consent-mode)
349
+ and your Shopify privacy settings separately. c15t's Wisepops helper does not
350
+ synchronize c15t choices with Shopify. Contact Wisepops support if you need to
351
+ disable its Shopify privacy integration, and use a single installation so a
352
+ Shopify app does not load the vendor outside c15t.
353
+
354
+ ## Verify Wisepops
355
+
356
+ Use a private window with an opt-in policy. Open DevTools Network, disable
357
+ the cache and filter by `wisepops`. Check Cookies, Local Storage and Session
358
+ Storage in the Application panel too.
359
+
360
+ 1. Load the page before choosing. There should be no Wisepops request, no
361
+ `window.wisepops` snippet queue and no new Wisepops storage entry.
362
+ 2. Reject consent and reload. Wisepops should stay blocked. Then allow an
363
+ unrelated category, such as `measurement`, while the mapped category
364
+ remains denied. Repeat the request, global and storage checks.
365
+ 3. Allow the mapped category. Expect `loader.js?v=3&h=...` to load without a
366
+ page reload. The query URL can redirect to a URL under
367
+ `wisepops.net/h/<siteId>/`. Configured campaigns become eligible, but
368
+ targeting and publishing settings can still prevent display.
369
+ 4. Navigate within your app and check that Wisepops detects URL changes with
370
+ automatic pageviews enabled. For manual pageviews, also test navigation
371
+ while the category or vendor is denied.
372
+ 5. Withdraw the mapped consent and save. Confirm that c15t reloads the page.
373
+ The new document should make no Wisepops request and have no snippet queue.
374
+ Previously stored data can remain; check deletion separately if you
375
+ configured cleanup.
376
+ 6. Test the Wisepops vendor switch inside an allowed category. Turning the
377
+ vendor off should reload the page and keep Wisepops blocked even though the
378
+ category remains allowed. Restore the mapped category and vendor permission
379
+ to check that Wisepops can load again.
380
+
381
+ Keep `reloadOnConsentRevoked` enabled for these checks. Wisepops has no
382
+ documented opt-out API that a callback-only script could call in place of the
383
+ reload.
384
+
385
+ Sources: [Add Wisepops to a custom website](https://support.wisepops.com/en/articles/9975472-how-to-add-wisepops-to-a-custom-website),
386
+ [public installation snippet](https://wisepops.com/),
387
+ [Cookie Consent Mode](https://support.wisepops.com/en/articles/12679556-cookie-consent-mode),
388
+ [data collection and cookies](https://support.wisepops.com/en/articles/9898232-data-collection-cookies),
389
+ [browser storage and cookie size options](https://support.wisepops.com/en/articles/9898261-limit-the-impact-of-wisepops-cookies-on-your-website),
390
+ and [single-page applications](https://support.wisepops.com/en/articles/9897249-single-page-applications-spa).
391
+
392
+ Test in a private window with an opt-in policy. Open DevTools Network, disable
393
+ the cache and filter by the vendor's domain:
394
+
395
+ 1. Load the page. No request goes to the vendor before you choose.
396
+ 2. Click Reject, then reload. There is still no vendor request.
397
+ 3. Open Privacy settings and allow the helper's category. The vendor script
398
+ loads without a page reload.
399
+ 4. Turn the category off again and save. c15t reloads the page, and the new
400
+ page makes no vendor request.
401
+
402
+ c15t reloads on revocation because removing a script element does not stop
403
+ code that already ran. The vendor's listeners, timers and queued events stay
404
+ alive until the page unloads. If you set `reloadOnConsentRevoked: false`, stop
405
+ the vendor yourself. Register a callback-only script whose `onConsentChange`
406
+ calls the vendor's opt-out API, as shown in
407
+ [custom integrations](./building-integrations.md), and check the
408
+ permission before each of your own event calls. The reload does not delete
409
+ cookies the vendor already set; see
410
+ [clear on revocation for your framework](./overview.md#vendor-switches-and-cookie-cleanup).
411
+
412
+ The helper lists its vendor by name in the preference dialog, so a visitor can
413
+ turn it off inside an allowed category. See
414
+ [vendor consent for your framework](./overview.md#vendor-switches-and-cookie-cleanup). The
415
+ [consent verification guide](../guides/verify-consent.md) covers navigation,
416
+ expiry and hosting checks.