Why TCF Alone Falls Short for Google
The TCF only carries consent for vendors registered on the IAB Global Vendor List. Google works with a set of ad technology partners (ATPs) that aren't on the GVL, so a pure TCF string has no field to express a user's choice about them. Google's Additional Consent specification exists to close that gap. It's a lightweight companion string, meant to be used alongside a TCF v2 implementation, that signals transparency and consent for those non-GVL partners.
If you run Google Ad Manager, AdSense, or AdMob against European traffic and you support TCF, you almost certainly need to produce this string too. Without it, Google can't serve its non-GVL partners even when the user consented. For how TCF and Google's consent signals relate more broadly, see TCF 2.2 versus Google Consent Mode v2.
What the AC String Looks Like
The current format is version 2, usually written ACv2. It's a compact, dot-and-tilde structure with three parts:
- The version prefix,
2. - A tilde, then the consented provider ids as a dot-separated list.
- Another tilde, then
dv.followed by the disclosed but not consented provider ids, again dot-separated.
So the anatomy is 2~[consented ids]~dv.[disclosed ids]. The ids are Google ATP ids, not IAB vendor ids. The two id spaces are separate, which is the whole reason this string exists.
Reading Three Example States
The spec's own examples make the states concrete:
2~~dv.1.2.3.4.10: the user hasn't decided yet. No ids sit in the consented slot; providers 1, 2, 3, 4, and 10 are disclosed.2~1.2.3.4.10~dv.: the user consented to all disclosed providers. Every id moved into the consented slot; the disclosed-only slot is empty.2~1.10~dv.2.3.4: a mixed decision. Providers 1 and 10 got consent; 2, 3, and 4 were disclosed but not consented.
The pattern to internalize: an id is either in the consented list or in the disclosed list, never both. When a user grants consent to a provider, it moves from disclosed to consented. CookieBeam's builder enforces this by removing any id from the disclosed set if it already appears in the consented set, so the two lists never overlap.
Where the ATP List Comes From
You don't invent provider ids. Google maintains the authoritative list of ad tech partners not registered with the IAB, along with their ids, as a downloadable CSV at storage.googleapis.com/tcfac/additional-consent-providers.csv. Your CMP discloses providers from this list and lets the user consent to them, then encodes the result. Like the GVL, this list changes, so treating it as a static snapshot will eventually leave you disclosing a stale set.
A careful builder also validates the ids it's handed against the known-valid set, dropping anything that isn't a positive integer on the list. CookieBeam's AC builder does this filtering and sorts the ids numerically so the output is deterministic, which makes strings comparable and testable.
Delivering It Through the TCF API
The AC string doesn't get its own global function. It rides along inside the TCF API. When a vendor calls for TCData, the CMP includes an addtlConsent property carrying the AC string next to the usual TCF fields. That co-delivery is deliberate: a Google tag reads one object and gets both the TCF signal and the additional-consent signal in the same response.
CookieBeam implements this with a custom command layered onto its TCF CmpApi. When TCData is assembled, the runtime injects the current AC string into addtlConsent, pulling it from an in-page value or from the standard IABTCF_AddtlConsent localStorage key. If neither is present, it returns an empty AC signal rather than a malformed one, which keeps consumers from choking on a half-formed string.
Keeping the Two Sets Straight
Most bugs here come from letting the consented and disclosed sets drift out of sync with the user's actual choices. A few rules keep it clean:
- Every disclosed provider that gains consent must move out of the disclosed list and into the consented list, not be added to both.
- Before any interaction, the consented list is empty and every provider sits in the disclosed slot (
2~~dv...). - Validate ids against Google's current ATP list; silently drop unknown ids rather than encoding them.
- Regenerate the AC string whenever consent changes, and redeliver it through
addtlConsentso vendors reading via event listeners get the update.
Common Mistakes
- Confusing ATP ids with IAB vendor ids. They're different registries. An IAB vendor id in the AC string is meaningless.
- Putting an id in both lists. Consented and disclosed are mutually exclusive per id.
- Encoding a default-granted state before the user chose. Pre-interaction, nothing is consented.
- Shipping the AC string only once. If the user changes their mind and you don't re-emit, Google reads the stale grant.
- Skipping it entirely. Without an AC string, Google can't serve its non-GVL partners even with full TCF consent.