c15t 3.1 gives every framework one event dispatcher for your own analytics calls, adds Google Additional Consent to IAB TCF setups and supports TanStack Start 1.0. It also fixes problems found since 3.0.0. The dialog showed vendor switches nobody asked for, stopped scrolling under some app CSS, and ran legal links into the banner text.
If you self-host the backend, run its migrations before you deploy 3.1. The
3.1 backend reads and writes a new column on every consent save, so it can't
record consent until migration 9 has run. Also read
Before you upgrade if you show vendor switches, use
@c15t/iab with custom translations, or type your __tcfapi callbacks.
Highlights
- Event dispatcher in every framework.
useEventDispatcher()andgetEventDispatcher()send your own events and pageviews to the scripts you registered, and drop them when the visitor hasn't consented. - Google Additional Consent. IAB TCF setups can ask for consent for Google ad tech providers that are not on the Global Vendor List.
- TanStack Start 1.0.
@c15t/tanstack-startbuilds and tests against TanStack Start 1.0. - Vendor switches only when you declare vendors. Sites that add only
@c15t/integrationshelpers get category switches, as in v2. - Fixes. The preference dialog scrolls again, legal links read the same in every framework, and PostHog stays off after a refusal that arrives while its script is still downloading.
Send your own events
Each framework now gives you the provider's event dispatcher. It sends to the scripts registered with the provider and checks consent when the event goes out, not when you created the dispatcher.
| Framework | Import |
|---|---|
| React, Next.js, TanStack Start | useEventDispatcher() from c15t/react, c15t/next or c15t/tanstack-start |
| Vue and Nuxt | useEventDispatcher() from c15t/vue/vue-plugin, auto-imported in Nuxt |
| Svelte and SvelteKit | getEventDispatcher() from @c15t/svelte |
| Astro | getEventDispatcher() from c15t/astro/client |
| Script tag | getEventDispatcher(runtime) from @c15t/browser |
All dispatchers for one provider share a pageview history. A consent change
or a remount no longer drops or repeats a pageview, and an event sent right
after the visitor withdraws consent is dropped. Pass scripts to add
destinations and pageviews to choose which integrations get single-page-app
pageviews. createEventDispatcher from @c15t/integrations/events still works
for code outside a provider.
→ React · Next.js · Nuxt · Svelte · Astro · JavaScript
Google Additional Consent
Google works with ad tech providers that are not on the IAB Global Vendor List.
List their Google ATP IDs in the manifest's iab.additionalConsent.providers.
The self-hosted backend loads their names and privacy policies, caches them
and sends them in /init. Setups without a backend can pass
additionalConsent.providers to the browser instead.
The React, Vue, Svelte and script-tag preference centres list each provider
with its privacy policy and a switch, and the banner's partner count includes
them. __tcfapi returns an Additional Consent v2 string, such as
2~89~dv.2572, as addtlConsent beside tcString. A provider counts as
consented only when its switch is on and the visitor consented to TCF
purposes 1, 3 and 4.
c15t stores the string in the addtl_consent cookie and localStorage entry,
restores it for returning visitors and removes it with the TC String. The
self-hosted backend records it in a new consent.addtlConsent column.
→ React IAB · Next.js IAB · Backend configuration
TanStack Start 1.0
@c15t/tanstack-start now builds and tests against TanStack Start 1.0
(@tanstack/react-start 1.169 and @tanstack/react-router 1.170.44). The
peer ranges are unchanged, so later 1.168 releases still work.
TanStack Start 1.0 needs Vite 8. Upgrade Vite first, then upgrade
@tanstack/react-router with @tanstack/react-start, because each Start
release depends on one exact router version. Start 1.0 also renames
.inputValidator() to .validator() on createServerFn() and
createMiddleware(). c15t and the code its CLI generates don't call either.
Fixes
- Vendor switches. Since 3.0.0, the preference dialog showed a switch for
the vendor of each
@c15t/integrationshelper, so a site that added onlyposthog()got a PostHog switch under Analytics. The dialog now shows only category switches until you declare a vendor. A helper vendor the visitor already switched off stays listed, so they can turn it back on, and its saved denial keeps blocking it until they do. - Dialog scrolling. Visitors can scroll to every category and vendor
again.
overflow: hiddenon the category list or a category row, for example to clip rounded corners, used to stop the list scrolling on phones. - Saves interrupted by navigation. When a visitor made a choice and then reloaded or left the page before the backend answered, the browser kept the choice but the backend never recorded it. c15t now queues each choice before sending it, and the next page load resends it with the original decision time.
- Legal links. Astro, Vue, Nuxt, Svelte and the script tag now match React: a space after the description, then the links separated by commas.
- Vendor list requests. In manifest mode, the browser fetches the Global
Vendor List without the
x-c15t-versionandx-c15t-policy-contractheaders. The request skips the CORS preflight, and hosts that reject those headers no longer fail it. - TC data outside TCF. When the visitor's policy doesn't use IAB TCF,
__tcfapireturns only the base fields CMP API v2 allows. No TC String,addtlConsent, purpose or vendor data reaches vendors. - PostHog. With
posthog({ loadMode: 'after-consent' }), a refusal that arrived whilearray.jswas downloading let PostHog start once the download finished. The refusal now clears PostHog's queued init. - Sentry.
sentry({ getClient })now declares the same vendor name and privacy policy assentry({ dsn }), so Sentry gets a vendor switch and core stops warning about a missing declaration. - CLI. Canary builds of the CLI install
c15t@3and other@c15t/*packages from@latestinstead of@canary. Setup also replaces a c15t package pinned to an exact prerelease. - Svelte.
@c15t/sveltedeclaressvelte@^5.20.0as its peer. Earlier Svelte 5 versions already failed to compile its components, and package managers now warn at install time.
Before you upgrade
Vendor switches need a declared vendor. If you relied on 3.0.0's helper
vendor switches, declare at least one vendor in the vendors option or on
your backend. The dialog then lists your helpers' vendors too. This changes
only the dialog, not when scripts load.
Declare the vendors.
Custom IAB translations need two keys.
IABPreferenceCenterTranslations.vendorList adds adTechProvidersHeading and
adTechProvidersNotice. Every built-in locale has them. Custom translation
sets fail type checks until you add both.
__tcfapi callbacks take a union. Callbacks now receive
TCData | TCDataOutsideTCF, and TCData.gdprApplies is true. Check
gdprApplies before you read tcString.
Self-hosted backends run a migration. Migration 9 adds the
consent.addtlConsent column, and the backend reads it on every consent save.
Run migrations before you deploy 3.1, whether or not you use Additional
Consent.
Packages
c15t, @c15t/core, @c15t/react, @c15t/nextjs, @c15t/tanstack-start,
@c15t/vue, @c15t/svelte, @c15t/astro, @c15t/browser, @c15t/iab,
@c15t/integrations, @c15t/backend, @c15t/cli, @c15t/node-sdk,
@c15t/schema, @c15t/translations and @c15t/dev-tools release as 3.1.0.
@c15t/ui and @c15t/scripts release as 3.0.1.