v2.3.0 - IAB TCF 2.4, New Integrations, and Netlify Geolocation
Last updated September 30, 2026
c15t 2.3 brings IAB TCF support up to version 2.4 ahead of IAB Europe's deadline, adds three script integrations, and lets the self-hosted backend read Netlify's geolocation header.
This is a minor release with no breaking changes.
Highlights
- IAB TCF 2.4 and TCF Policies v5.0.b support, with a new Features section in
IABConsentDialog - New integrations for Front Chat, OneDollarStats, and Pinterest Tag
- Netlify geolocation support in
@c15t/backend
IAB TCF 2.4
IAB Europe requires web CMPs to meet TCF 2.4 and TCF Policies v5.0.b by 23 October 2026. If you use @c15t/iab, upgrading to 2.3 covers the c15t side of that requirement. Existing TC strings stay valid and no migration is needed.
The biggest visible change is in IABConsentDialog. Features used to sit in the locked "Essential Functions" section, each next to a checked, disabled switch. The new policies forbid showing a Feature next to a control that can't be turned off, so Features now have their own section after Special Purposes. The section shows the IAB standard text for Features, each Feature's name, description, and illustrations, and the vendors that use it. It has no switches. Special Purposes stay locked as before.
The standard text comes from the GVL's new standardTexts.features field. When the GVL doesn't include it, c15t falls back to the iab.preferenceCenter.features translation, which ships in all 35 locales. It uses IAB's official translation where one exists and English for the four locales IAB doesn't translate.
Other changes:
__tcfapiTC data now includesvendor.disclosedVendors.isServiceSpecificis deprecated. TCF 2.4 requires IsServiceSpecific to always be1, so c15t now always encodes1and logs a one-time warning if you passfalse.- Vendors that declare only Special Purposes no longer get a legitimate interest bit, including when c15t re-saves consent restored from an older TC string.
- Decoding a TC string no longer drops vendor IDs above 1000. The current GVL goes past 1000, so consents and disclosures for those vendors were lost on restore.
useGVLData()returnsfeaturesStandardText, andIABConsentDialog.PurposeItemhas aninformationalmode for custom layouts.- The schema accepts
standardTexts, and theGVLStandardTextstype is exported.
→ React IAB · Next.js IAB · IAB Consent Dialog
Three new script integrations
@c15t/scripts adds three built-in helpers. Each one has an integration guide, a CLI generate option, and a daily live-vendor check.
Front Chat. frontChat() from @c15t/scripts/front-chat loads Front's chat widget after functionality consent and forwards your CSP nonce to the scripts Front injects. It also exports shutdownFrontChat(), which asks Front to clear the chat session before the revocation reload. That call is best effort, so c15t still reloads the page.
OneDollarStats. oneDollarStats() from @c15t/scripts/one-dollar-stats loads the tracker after measurement consent. It needs no API key. Optional settings are forwarded as data-* attributes. oneDollarStats() throws if hostname includes a scheme, path, or query instead of a bare host.
Pinterest Tag. pinterestTag() from @c15t/scripts/pinterest-tag recreates Pinterest's v3 base code and loads core.js after marketing consent. The script stays loaded after revocation so c15t can call pintrk('setconsent', false), which stops tracking and clears Pinterest's first-party cookies. Re-granting consent calls setconsent(true). pinterestTagEvent() gives you typed tracking for Pinterest's 20 event types, and also accepts your own event names.
→ Front Chat · OneDollarStats · Pinterest Tag
Netlify geolocation
@c15t/backend now reads Netlify's x-country header, so geolocation works on Netlify Functions without extra setup. c15t treats it the same way as cf-ipcountry and x-vercel-ip-country. Header precedence is unchanged, and x-c15t-country still overrides everything.
Other improvements
- Hosted mode keeps a visitor's saved rejection through backend outages, and no longer throws when the browser blocks
localStorage. → Client modes - A choice saved while the consent store is starting up is kept.
- The iframe blocker skips nodes it can't read instead of stopping. An iframe with an invalid or empty
data-categorynow stays blocked and logs a console warning, so check the console for a mistyped category after upgrading. → Iframe blocking - Exported types resolve under
Node16andNodeNextmodule resolution withoutskipLibCheck. - The
@c15t/dev-toolspanel can be closed again when the OS or browser has reduced motion turned on. Before, the close button and backdrop did nothing.