Consent String Errors That Silently Kill Your Ad Revenue
The Silent Revenue Leak
When your eCPM drifts down a few percent every month, the cause is rarely inventory or floor prices. More often it is a broken TC string — the IAB Transparency & Consent Framework (TCF) signal that travels with every ad request. A malformed or missing string throws no loud error. Instead, the ad server quietly falls back to non-personalized ads, demand partners drop out, and revenue bleeds without a single alert. For app and game publishers monetizing in the EEA & UK, it is the most overlooked cause of lost income.
What the TC String Actually Carries
The TC string is a base64-encoded blob created by your Consent Management Platform (CMP). It encodes the user's choices: consented purposes, allowed vendors, your CMP ID, policy version, and a timestamp. Buyers decode it in milliseconds to decide whether they can bid with personalized targeting. Two signals matter as much:
gdprApplies— a flag (1, 0, or undefined) telling buyers whether GDPR is in scope.- Google Consent Mode v2 — the
ad_storage,ad_user_data, andad_personalizationsignals Google reads independently of the TCF string.
If any of these is wrong, demand evaporates — even when the user actually consented.
The Five Errors That Quietly Cost You Money
1. Missing or expired string. If the CMP never writes a string, or cached consent ages past your re-prompt window, requests go out with no signal. Buyers treat "no string" as "no consent" and bid only with low-eCPM contextual demand, or skip the auction.
2. Wrong CMP ID. Every certified CMP has a registered ID baked into the string. If an unrecognized ID is written, Google and IAB vendors reject it — common after a migration with the old SDK still bundled.
3. Vendor not declared. A demand partner may have full consent, but if its vendor ID is not in the allowed-vendor list, it cannot bid personalized. Publishers often forget to update the list after adding a partner.
4. Malformed gdprApplies. Passing a string "1" instead of an integer, or leaving it undefined for a user clearly in the EEA, confuses buyers. An incorrect gdprApplies=0 can also expose you to compliance risk while looking fine.
5. Consent Mode signals not firing. The TCF string can be perfect while Consent Mode stays in its default denied state — for instance, when the SDK loads ads before consent resolves. Google then serves non-personalized ads regardless of the TC string.
A Step-by-Step Debugging Workflow
Work from the device outward to the ad server, and reproduce in a clean state — clear app data or use a fresh browser profile so stale consent does not mislead you.
- Step 1 — Capture the raw string. On web, read it via
__tcfapi('getTCData', 2, cb). In an app, dump theIABTCF_TCStringkey fromSharedPreferences(Android) orNSUserDefaults(iOS). - Step 2 — Decode and validate. Paste it into the IAB TCF decoder or a CMP validator. Confirm the CMP ID is yours, the policy version and timestamp are current, and your key vendor IDs appear in the list.
- Step 3 — Inspect the ad request. Use Charles Proxy or a network inspector to watch the GAM request, and verify the
gdprandgdpr_consentparameters carry the right values. - Step 4 — Check Consent Mode. Use Google Tag Assistant to confirm
ad_user_dataandad_personalizationflip to granted when the user accepts. - Step 5 — Confirm in GAM. Open Ad Manager's non-personalized ads reporting dimension. A spike in NPA traffic that does not match your opt-out rate is the fingerprint of a bad string.
Fixing the Root Cause
Patching one bad request is easy; preventing the next is the work. Make ads wait for consent before initializing, keep your vendor list synced with your demand stack, and track the ratio of personalized to non-personalized impressions — a shift there is your earliest warning.
This is where a Google-certified CMP earns its keep. FlexyConsent emits valid IAB TCF 2.3 strings with the right CMP ID and vendor declarations, fires Consent Mode v2 signals so ad_user_data and ad_personalization track the user's choice, and surfaces consent-rate analytics across web, Android, and iOS — so a broken string surfaces on a dashboard, not in your payout.
Key Takeaways
- A bad TC string does not crash — it quietly downgrades you to non-personalized ads and lower eCPM.
- Five culprits: missing/expired strings, wrong CMP ID, undeclared vendors, malformed
gdprApplies, and dead Consent Mode signals. - Debug device to ad server: capture, decode, inspect the request, verify Consent Mode, check GAM.
- Track your personalized-to-NPA ratio continuously — a certified CMP like FlexyConsent makes valid strings and correct Consent Mode v2 signals the default.