If you run ads in Europe, somewhere between your cookie banner and your ad server there's a base64-encoded string doing an enormous amount of legal work. It records which of eleven data-processing purposes the user agreed to, which of 1,100+ ad tech vendors may act on that agreement, and on what legal basis — all packed into something like CQliWsAQliWsAEsABBENCiFoAPLAAELAAAYg....
That string, and the machinery around it, is the IAB Transparency & Consent Framework (TCF). Most explainers stop at "it's an industry consent standard." This one goes further: we'll decode an actual TC string, call the __tcfapi JavaScript API, and walk through what changed in TCF 2.2, what TCF 2.3 made mandatory in 2026, and where the long-running Belgian legal saga actually landed.
A heads-up on versions: most guides you'll find still describe TCF 2.2. As of June 2026, TCF v2.3 is the version in force — the migration deadline passed on 28 February 2026, and Google now rejects newly created v2.2 strings. Details below.
What is the IAB TCF?
The IAB Transparency & Consent Framework (TCF) is a standard, run by IAB Europe and IAB Tech Lab, for collecting GDPR consent once and passing it to hundreds of ad tech vendors in a machine-readable "TC string." Your CMP encodes the user's choices; every vendor in the chain decodes the string to learn what it's allowed to do.
Without something like the TCF, every SSP, DSP, and measurement vendor in a programmatic auction would need its own consent dialog — obviously unworkable. The TCF replaces that with one banner, one encoded signal, and a published rulebook (the TCF Policies) that every registered participant agrees to follow.
Be precise about what the TCF is not: it isn't a law, and using it doesn't automatically make you GDPR-compliant. Regulators judge the consent you collect; the TCF standardizes how that consent travels.
Who actually needs the TCF?
In practice, one requirement drives most adoption: since 16 January 2024, Google requires publishers serving ads to users in the EEA or UK through AdSense, Ad Manager, or AdMob to use a Google-certified CMP that integrates the TCF when serving personalized ads. The same rule extended to Switzerland on 31 July 2024.
The consequences are financial, not theoretical. Per Google's policy:
| Your setup | Ads you're eligible for |
|---|---|
| Certified CMP + TCF | Personalized, non-personalized, and limited ads |
| Non-certified or no CMP | Non-personalized or limited ads only |
Limited ads are contextual-only, no-cookie ad serving, and they typically pay a fraction of personalized rates. So "do I need the TCF?" usually reduces to "do I monetize EEA/UK/Swiss traffic with Google's ad stack or TCF-registered exchanges?" If yes, you need it. A SaaS site with analytics and a few marketing pixels needs a consent management platform — but probably not the TCF.
The four actors (and the Global Vendor List)
The TCF defines distinct roles:
- Publishers — sites and apps that surface the consent UI and monetize the audience.
-
CMPs — consent management platforms that render the banner, encode choices into a TC string, and expose it via the
__tcfapiAPI. CMPs must be registered with IAB Europe (each gets a numeric CMP ID) and validated against the technical spec. - Vendors — ad tech companies that register the purposes they process data for and the legal bases they claim. Each gets a vendor ID (Google Advertising Products is 755, Amazon Ads is 793).
- The Global Vendor List (GVL) — the canonical registry of all vendors, their declared purposes, and policy metadata. It's a public JSON file, refreshed weekly. At the time of writing (June 2026) the v3 GVL is at version 162 and lists 1,175 vendors.
That last number matters: your banner is asking users to make decisions about over a thousand companies. TCF 2.2 forced CMPs to put that vendor count on the banner's first layer, precisely so users grasp the scale before clicking "Accept."
What's inside a TC string
A TC string is a dot-separated, base64url-encoded structure with up to three segments:
- Core segment (required) — metadata plus the user's purpose and vendor choices.
- Disclosed vendors segment (required since v2.3) — a bit field recording exactly which vendors the CMP actually showed the user.
- Publisher TC segment (optional) — the publisher's own purposes.
The choices themselves revolve around 11 standardized purposes and 2 special features:
| # | Purpose | Allowed legal bases |
|---|---|---|
| 1 | Store and/or access information on a device | Consent only |
| 2 | Use limited data to select advertising | Consent or legitimate interest |
| 3 | Create profiles for personalised advertising | Consent only (since v2.2) |
| 4 | Use profiles to select personalised advertising | Consent only (since v2.2) |
| 5 | Create profiles to personalise content | Consent only (since v2.2) |
| 6 | Use profiles to select personalised content | Consent only (since v2.2) |
| 7 | Measure advertising performance | Consent or legitimate interest |
| 8 | Measure content performance | Consent or legitimate interest |
| 9 | Understand audiences (statistics, combined data) | Consent or legitimate interest |
| 10 | Develop and improve services | Consent or legitimate interest |
| 11 | Use limited data to select content (added in v2.2) | Consent or legitimate interest |
Special features (always opt-in): 1. use precise geolocation data; 2. actively scan device characteristics for identification.
Here's a real TC string we generated against GVL v162 with the official @iabtechlabtcf/core library, and what it decodes to:
CQliWsAQliWsAEsABBENCiFoAPLAAELAAAYgGMwAwAOALzAYyBecAEBeYAAA.IGMwAwAOALzAYyAA
{
"version": 2,
"policyVersion": 5, // 5 = TCF v2.3 policies
"created": "2026-06-09",
"cmpId": 300,
"consentLanguage": "EN",
"vendorListVersion": 162,
"isServiceSpecific": true,
"publisherCountryCode": "DE",
"purposeConsents": [1, 2, 3, 4, 7, 9, 10],
"purposeLegitimateInterests": [2, 7, 9, 10],
"specialFeatureOptins": [1],
"vendorConsents": [28, 755, 793], // TripleLift, Google, Amazon
"vendorLegitimateInterests": [755],
"disclosedVendors": [28, 755, 793] // the segment after the dot
}
Read it like a vendor would: Google (755) has consent for purposes 1–4, 7, 9, 10, may also claim legitimate interest for 2, 7, 9, 10, and — per the second segment — was actually disclosed in the UI. A vendor not in vendorConsents gets nothing, no matter what the purpose bits say. Note the string never contains the user's identity; it's pure permission state.
The __tcfapi JavaScript API
Every TCF CMP must expose window.__tcfapi(command, version, callback, parameter). Since v2.2, the way to read consent is an event listener (the old getTCData command is deprecated — listeners handle the async reality that consent changes mid-session):
window.__tcfapi('addEventListener', 2, (tcData, success) => {
if (!success) return;
// Fires on registration and every TC string change
if (tcData.eventStatus === 'tcloaded' ||
tcData.eventStatus === 'useractioncomplete') {
const canMeasureAds =
tcData.gdprApplies === false ||
(tcData.purpose.consents[1] && tcData.purpose.consents[7]);
const googleAllowed = !!tcData.vendor.consents[755];
if (canMeasureAds && googleAllowed) {
// safe to request personalized ads / fire measurement
}
// Done listening? Clean up:
window.__tcfapi('removeEventListener', 2, () => {}, tcData.listenerId);
}
});
The three eventStatus values map to the user's position in the flow: cmpuishown (banner is up), useractioncomplete (they just chose), tcloaded (a prior choice was loaded, no UI needed). There's also a synchronous ping command, and for iframes (ad slots) a postMessage bridge via the __tcfapiLocator frame — see the CMP API spec.
What changed in TCF 2.2
TCF v2.2 (switchover completed 20 November 2023) was the consent-quality release, largely shaped by regulator pressure:
- Legitimate interest banned for personalization. Purposes 3–6 — building and using profiles for personalized ads and content — became consent-only. Vendors could no longer slide ad profiling through on an LI basis.
- Vendor count on the first layer. CMPs must disclose the total number of vendors seeking consent right on the banner, not buried in layer two.
- Plain-language purposes. Standardized, user-tested names and descriptions with real-world examples, replacing legalese.
- Easier withdrawal. Publishers must make resurfacing the CMP (to change or withdraw consent) straightforward.
-
getTCDatadeprecated in favor of event listeners, as shown above. - Purpose 11 added ("use limited data to select content") to cover basic, non-profiled content selection.
TCF 2.3: the current version (June 2026 status)
TCF v2.3 was released by IAB Europe on 19 June 2025. It's a narrow but consequential release: it makes the disclosedVendors segment mandatory in every TC string.
The problem it fixed: under v2.2, a vendor seeing its legitimate-interest bit at 0 couldn't tell whether the user had objected or the CMP had simply never disclosed that vendor — a GDPR-sized hole for vendors relying on special purposes like fraud prevention. The mandatory segment gives a binary, verifiable answer: 1 = disclosed to this user, 0 = not.
The timeline, which has already fully played out:
| Date | What happened |
|---|---|
| 19 June 2025 | TCF v2.3 released; transition period opens |
| 3 November 2025 | Google announces it accepts v2.3 strings immediately and sets its deadline |
| 28 February 2026 | Transition ends; Google stops supporting newly created v2.2 strings |
| 1 March 2026 | Any new TC string without a disclosedVendors segment is invalid |
Two practical notes for where we are now, mid-2026. First, valid v2.2 strings created before the deadline remain grandfathered — but every string your CMP creates or updates today must be v2.3 (TCF policy version 5, which is exactly what the live GVL reports). Second, the failure mode is quiet: an invalid string doesn't break your site, it just drops Google ad requests to limited ads. If your EEA RPM cratered around March 2026, check your CMP's TCF version before anything else. There was no UI re-surfacing requirement, so users never noticed the migration — only revenue dashboards did.
TCF and Google Consent Mode: complementary, not alternatives
A persistent confusion: "we have Consent Mode, do we still need the TCF?" They solve different problems.
- TCF broadcasts consent to the entire ad tech ecosystem — every registered vendor in a programmatic chain reads the TC string.
-
Google Consent Mode governs how Google's own tags (gtag, GTM, GA4, Google Ads) behave — the
ad_storage,ad_user_data,ad_personalization, andanalytics_storagesignals.
They also interoperate directly. Set window['gtag_enable_tcf_support'] = true (or have your CMP set enableAdvertiserConsentMode: true in TCData) and Google tags will read the TC string and derive consent mode behavior from it: no Purpose 1 consent → ad_storage and ad_user_data denied; no Purposes 3 and 4 → ad_personalization denied. Google tags wait up to 500 ms for your CMP to respond before falling back to defaults, which is why CMP load performance matters.
If you monetize with Google ads in Europe, the practical answer is: you need both, and your CMP should handle both.
The Belgian litigation: where it actually landed
The TCF spent four years in legal limbo, and the headlines ("TCF ruled illegal!") aged badly. The verified sequence:
- February 2022 — The Belgian DPA (APD/GBA), acting as lead authority, found IAB Europe acted as a joint controller for TC strings, fined it €250,000, and ordered an action plan to fix the framework.
- 7 March 2024 — The CJEU, on referral, ruled in C-604/22 that (a) a TC string is personal data when it can reasonably be linked to an identifier like an IP address, and (b) IAB Europe is a joint controller for the creation and dissemination of TC strings — but not automatically for the downstream ad processing built on top of them.
- 14 May 2025 — The Belgian Market Court applied that ruling: it upheld the €250,000 fine and the narrow joint-controllership finding, but annulled the APD's broader conclusions extending IAB Europe's responsibility into subsequent adtech processing. The court also noted it was judging TCF v2.0 — not the v2.2/v2.3 framework actually in use.
- January 2026 — The Market Court annulled the APD's 2023 validation of IAB Europe's action plan, finding the decision procedurally flawed (IAB Europe wasn't heard) and too broad in scope. The case went back to the APD for a fresh decision reflecting the narrower controllership.
So as of June 2026: the TCF is operational, has never been ordered shut down, IAB Europe's responsibility is confirmed but tightly scoped to the TC string itself, and the remaining open thread is a redo of the action-plan process at the APD. The structural takeaways for publishers already shipped in v2.2 and v2.3.
What to actually do
- Check whether the rule applies to you. EEA/UK/Swiss traffic + AdSense/Ad Manager/AdMob (or programmatic via TCF exchanges) = you need a Google-certified, TCF-registered CMP. Google publishes the certified list.
-
Verify your CMP is emitting v2.3 strings. Run
__tcfapi('addEventListener', ...), grabtcData.tcString, and decode it (iabtcf libraries or any online decoder). Confirm policy version 5 and a disclosedVendors segment after the first dot. - Trim your vendor list. Nothing requires you to ask for all 1,175 GVL vendors. Fewer vendors means a more honest banner and likely better consent rates.
-
Wire up the Consent Mode bridge (
enableAdvertiserConsentModeorgtag_enable_tcf_support) so Google tags and the TC string can't disagree. - Test the failure path. Reject everything in your own banner, then confirm ad requests degrade gracefully and no vendor fires that shouldn't.
- Keep consent records. The TC string is the signal; you still need logged proof of consent for audits.
Where CookieChimp fits
CookieChimp is a modern, simple yet powerful CMP that handles the consent plumbing this article describes: geo-targeted banners for EEA/UK/Swiss traffic, Google Consent Mode v2 signals, vendor management, automatic cookie scanning, and consent logging that gives you an audit trail behind every signal you send. If you're comparing options for an ad-monetized site, start with our developer-focused CMP comparison.
FAQ
Is the IAB TCF legally required under GDPR?
No. GDPR requires valid consent; it doesn't mandate any framework. The TCF is an industry standard for transporting consent. The practical mandate comes from Google: since 16 January 2024, serving personalized ads to EEA/UK users through AdSense, Ad Manager, or AdMob requires a Google-certified CMP integrated with the TCF.
Is TCF 2.2 still valid in 2026?
Not for new consent strings. TCF v2.3's transition period ended on 28 February 2026: TC strings created from 1 March 2026 onward must include the disclosedVendors segment, and Google no longer supports newly created v2.2 strings. Valid v2.2 strings collected before the deadline remain usable until they expire or the user revisits their choices.
Was the TCF ruled illegal by the Belgian DPA?
No — and the final rulings narrowed the original 2022 decision considerably. The CJEU (C-604/22, March 2024) confirmed TC strings are personal data and IAB Europe is a joint controller for them, but not for downstream ad processing. The Belgian Market Court upheld the €250,000 fine in May 2025 while annulling the DPA's broader findings, and in January 2026 it also annulled the DPA's validation of the remedial action plan on procedural grounds. The framework keeps operating throughout.
What is a TC string, in one sentence?
It's a compact, base64url-encoded record of a user's consent and objection choices — across 11 purposes, 2 special features, and every disclosed vendor — that travels with ad requests so each vendor knows what it may do.
Do I need both the TCF and Google Consent Mode?
If you run Google ads in Europe, effectively yes. The TCF informs the broad ad tech ecosystem; Consent Mode governs Google's own tags. They integrate: with TCF support enabled, Google tags derive their consent mode state directly from your TC string, so the two signals stay consistent.
How do I check what my CMP is actually sending?
In the browser console, run __tcfapi('ping', 2, console.log) to confirm the CMP is loaded, then register an addEventListener callback and inspect tcData.tcString. Decode the string with the @iabtechlabtcf/core library and check the policy version, purpose bits, and vendor bits against what your banner claims.
References
- IAB Europe, "All You Need to Know About the Transition to TCF v2.3": iabeurope.eu
- IAB Tech Lab (GitHub), "Transparency and Consent String with Global Vendor List Format": github.com
- IAB Tech Lab (GitHub), "Consent Management Platform API v2": github.com
- Google Ad Manager Help, "Google consent management requirements for serving ads in the EEA, the UK, and Switzerland": support.google.com
- Google for Developers, "Implement the Transparency & Consent Framework": developers.google.com
- IAB Europe, "Understanding the Transparency & Consent Framework v2.2": iabeurope.eu
- IAB Europe, "CJEU Judgement of 7 March 2024 in TCF Case: IAB Europe's Analysis": iabeurope.eu
- IAB Europe, "IAB Europe Wins Appeal Against APD Decision on TCF Corrective Measures": iabeurope.eu
- Lewis Silkin, "IAB TCF: Belgian Market Court upholds €250,000 fine against IAB for GDPR violations": lewissilkin.com
- PPC Land, "Google mandates TCF v2.3 migration by February 2026": ppc.land
- IAB Europe, Global Vendor List (v3, live JSON): vendor-list.consensu.org
Running ads in Europe and want the TCF, Consent Mode, and consent logging handled without a six-week integration project? Get started with CookieChimp.