Experimentation and personalization
Wisepops
The c15t wisepops helper loads Wisepops only after marketing has consent.
Before then, it creates no Wisepops snippet queue and writes no Wisepops
storage. It queues defaultConsent: 'denied' before the SDK runs and calls
wisepops('consent', 'granted') after the loader finishes with consent still
allowed. Keep c15t's default reload on revocation enabled because Wisepops
cannot revoke consent programmatically.
Configure Wisepops
In Wisepops, open Settings > Install Wisepops and copy your site's setup
code. The loader URL contains your public site ID in its h parameter:
https://wisepops.net/loader.js?v=3&h=YOUR_WISEPOPS_SITE_ID.
Use the c15t helper in place of the Wisepops installation snippet. Remove other Wisepops installations, including any tag manager or CMS plugin that loads it, so they do not bypass c15t's consent check. Use one Wisepops site ID per document. Reload the page when changing site IDs; replacing a helper configuration does not reinitialize an SDK that has already started.
The scripts export below uses marketing consent. experienceScripts is an
alternative for campaigns whose purpose and policy call for experience
consent. Register one array.
Register the scripts
Complete your framework quickstart first. Keep its Inth endpoint, policy, styles and consent UI. Remove the vendor's original script, SDK initializer or tag-manager entry, so the vendor loads only through c15t.
The vendor pages put the helper in src/consent-scripts.ts. If your framework
quickstart already has a scripts array, such as the one in c15t.config.ts
in the Next.js guide, add the helper to that array instead of creating a
second file.
The scripts export is a configuration, not an initializer. Add it to the c15t provider you already have, at the registration
point for your framework below. These are edits to that provider, not a second
provider.
Add the configuration to scripts in c15t.config.ts, next to
next.config.ts:
Keep the rest of your config, such as mode and routePrefix, in the
same call. ConsentRoot reads the config in the browser, so the layout
keeps passing only state. App Router, Pages Router and static export all
read the same file. See
Next.js scripts and embeds.
To use the experience alternative, change the registration example's import
to import { experienceScripts as scripts } from './consent-scripts', adjusting
the relative path for your framework. It also enables Wisepops localStorage.
Options
| Option | Default | Behavior |
|---|---|---|
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. |
category | 'marketing' | Consent category or condition required before any Wisepops setup. Use 'experience' if it matches your campaign's purpose and policy. |
options.autoPageview | Wisepops v3 default, 'url' | 'url' checks for campaigns after URL changes. 'init' checks only after initialization. false disables automatic pageviews. |
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. |
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. |
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. |
The helper always sets defaultConsent: 'denied'; it is not a configurable
option. The helper grants Wisepops cookie consent only after c15t permits
the mapped category and the vendor. It has no alwaysLoad mode.
The helper's options are bootstrap configuration, queued before its loader
runs. Changing the configuration object does not update an SDK already
running on the page. Set these values before registering the scripts.
Single-page applications
The helper uses Wisepops' v3 loader, whose default autoPageview: 'url'
detects URL changes. With autoPageview: false, call the browser SDK through
window.wisepops?.('pageview') after your router updates the URL, only while
the mapped category and Wisepops vendor are allowed. Recheck permission on
every manual call. The snippet queue can remain after revocation, so the
existence of window.wisepops alone is not a consent check.
Avoid sending manual pageviews alongside automatic ones. Duplicate pageviews
can cause campaigns to appear and disappear immediately. autoPageview: false
does not stop an SDK that has already started.
Loading and revocation
Once the mapped consent allows Wisepops, c15t creates window.wisepops with
its snippet queue and timestamp, queues the runtime options and appends the
loader to <head>. After the SDK loads, c15t grants Wisepops cookie consent.
If c15t removes a downloading loader after revocation, the helper ignores
its later load event and sends no consent grant.
Wisepops' own denied mode still displays campaigns and uses session-only cookies. This helper waits for c15t consent before loading Wisepops at all. Do not install Wisepops separately to use its denied mode alongside this helper.
On revocation, c15t removes the loader and reloads the page by default. The
new page does not load Wisepops while the mapped consent is denied. The
helper does not call wisepops('consent', 'denied'): Wisepops documents that
this call produces an error. The reviewed Wisepops documentation provides no
shutdown or destroy call for the helper to use.
Keep reloadOnConsentRevoked enabled. Setting it to false leaves the
already-running SDK, displayed campaigns, timers and listeners active.
Removing a script element also cannot guarantee that an in-flight download
will never execute. A reload ends the document; it does not erase data
already stored by Wisepops.
Cookies and browser storage
Wisepops documents the following first-party cookies on your site's domain. Actual values and lifetimes can vary with its configuration and the browser:
| Cookie | Documented lifetime |
|---|---|
wisepops_session | Session |
wisepops_visitor | 750 days |
wisepops_noshow | 2 years |
wisepops_props | 2 years |
wisepops_visits | 2 years |
wisepops_tld | Session |
wisepops | 2 years |
With options.browserStorage: true, Wisepops moves visitor data to
localStorage. c15t does not automatically delete Wisepops cookies or
localStorage on revocation. Your cleanup can remove only browser-accessible
data on domains, paths and origins your application can reach. It cannot
clear HttpOnly cookies or vendor-side records. Wisepops can remember an earlier
consent grant in its stored state, so reloading with defaultConsent: 'denied'
alone does not reset that grant. After c15t revocation, keep Wisepops blocked
on the new page.
Wisepops automatically integrates with Shopify Customer Privacy. Check Wisepops' Shopify consent behavior and your Shopify privacy settings separately. c15t's Wisepops helper does not synchronize c15t choices with Shopify. Contact Wisepops support if you need to disable its Shopify privacy integration, and use a single installation so a Shopify app does not load the vendor outside c15t.
Verify Wisepops
Use a private window with an opt-in policy. Open DevTools Network, disable
the cache and filter by wisepops. Check Cookies, Local Storage and Session
Storage in the Application panel too.
- Load the page before choosing. There should be no Wisepops request, no
window.wisepopssnippet queue and no new Wisepops storage entry. - Reject consent and reload. Wisepops should stay blocked. Then allow an
unrelated category, such as
measurement, while the mapped category remains denied. Repeat the request, global and storage checks. - Allow the mapped category. Expect
loader.js?v=3&h=...to load without a page reload. The query URL can redirect to a URL underwisepops.net/h/<siteId>/. Configured campaigns become eligible, but targeting and publishing settings can still prevent display. - Navigate within your app and check that Wisepops detects URL changes with automatic pageviews enabled. For manual pageviews, also test navigation while the category or vendor is denied.
- Withdraw the mapped consent and save. Confirm that c15t reloads the page. The new document should make no Wisepops request and have no snippet queue. Previously stored data can remain; check deletion separately if you configured cleanup.
- Test the Wisepops vendor switch inside an allowed category. Turning the vendor off should reload the page and keep Wisepops blocked even though the category remains allowed. Restore the mapped category and vendor permission to check that Wisepops can load again.
Keep reloadOnConsentRevoked enabled for these checks. Wisepops has no
documented opt-out API that a callback-only script could call in place of the
reload.
Sources: Add Wisepops to a custom website, public installation snippet, Cookie Consent Mode, data collection and cookies, browser storage and cookie size options, and single-page applications.
Test in a private window with an opt-in policy. Open DevTools Network, disable the cache and filter by the vendor's domain:
- Load the page. No request goes to the vendor before you choose.
- Click Reject, then reload. There is still no vendor request.
- Open Privacy settings and allow the helper's category. The vendor script loads without a page reload.
- Turn the category off again and save. c15t reloads the page, and the new page makes no vendor request.
c15t reloads on revocation because removing a script element does not stop
code that already ran. The vendor's listeners, timers and queued events stay
alive until the page unloads. If you set reloadOnConsentRevoked: false, stop
the vendor yourself. Register a callback-only script whose onConsentChange
calls the vendor's opt-out API, as shown in
custom integrations, and check the
permission before each of your own event calls. The reload does not delete
cookies the vendor already set; see
clear on revocation for your framework.
The helper lists its vendor by name in the preference dialog, so a visitor can turn it off inside an allowed category. See vendor consent for your framework. The consent verification guide covers navigation, expiry and hosting checks.