GTM, Adobe Launch, Matomo – and why a “universal consent dataLayer” does not exist
Many teams assume that CMPs (Axeptio, Didomi, OneTrust, Cookiebot…) all push the same consent attributes into the dataLayer.
This is false.
Each Tag Manager (Google Tag Manager, Adobe Launch, Matomo Tag Manager…) expects different signals, via different APIs, and none of them consumes the TCF directly — including Adobe, even though many people still think so.
This article breaks down everything you actually need to know:
- how a CMP really works
- what attributes each TMS expects
- how GTM interprets Consent Mode V2
- why Adobe does NOT read TCF
- how Matomo handles consent
- which JavaScript objects you need to populate
- how to map CMP → TMS
- how to avoid “fallback mode” and broken attribution
1. First: how does a CMP actually work?
A CMP does three things:
- Display a banner (notice layer or choice layer).
- Expose user choices via:
- TCF v2 API (__tcfapi)
- internal callbacks
- JavaScript variables
- events (custom events, dataLayer pushes…)
- Allow the website to trigger or block tracking tools accordingly.
A CMP does not talk directly to a Tag Manager.
It only exposes its own consent model (TCF v2 or proprietary).
Then you or your TMS must translate these signals into what the tracking tools expect.
2. TCF v2: the language of CMPs, not the language of Tag Managers
TCF = Transparency & Consent Framework (IAB Europe)
It defines:
- the __tcfapi() function
- a consent “TC String”
- Purposes (finalities)
- Vendors
- a standardized RGPD-compliant mechanism
CMPs speak TCF.
Tag Managers do NOT.
Google, Adobe, Matomo all require their own consent APIs.
- Google GTM does not consume TCF directly
- Adobe Launch does NOT consume TCF
- Matomo does NOT consume TCF
- You always need a mapping: CMP → TMS API
TCF is a source of truth, not a tracking standard.
3. Case 1: Google Tag Manager (GTM) + Consent Mode V2
GTM does NOT read:
- TCF
- the TC String
- CMP events
- CMP vendors
- CMP purposes
GTM only reads the Consent Mode V2 signals, injected into gtag.js.
The four attributes are:
ad_storage
analytics_storage
ad_user_data
ad_personalization
Example:
gtag('consent', 'update', {
ad_storage: 'granted',
analytics_storage: 'granted',
ad_user_data: 'granted',
ad_personalization: 'granted'
});
These four attributes drive the entire Google ecosystem:
- GA4
- Ads conversion tracking
- Ads linking (gclid / wbraid persistence)
- modeling
- remarketing
- enhanced conversions
If these signals are missing or late: fallback mode → loss of attribution and unusable Ads data.
The CMP must therefore call:
gtag('consent', 'update', {...})
BEFORE any Google tag triggers.
4. Case 2: Adobe Launch + Adobe Opt-In Service
This is the point where most teams get it wrong.
Adobe does NOT read:
- TCF
- __tcfapi
- the TC String
- vendors or purposes
- any CMP dataLayer
Adobe uses its own consent system: Opt-In Service.
It exposes:
window.adobe.optIn
with “scopes”:
analytics
ecid
target
aam
media
personalization
Example:
adobe.optIn.approve(['analytics', 'ecid']);
adobe.optIn.deny(['target']);
This is the only language Adobe understands.
Therefore, to integrate a CMP with Adobe Launch, you must map:
CMP (TCF or internal API)
→ mapping script
→ adobe.optIn.approve() / deny()
Example mapping:
if (cmpConsent.purposes.analytics === true) {
adobe.optIn.approve(['analytics', 'ecid']);
} else {
adobe.optIn.deny(['analytics']);
}
Why doesn’t Adobe adopt TCF?
- Adobe is deployed globally (US, Asia, LatAm). TCF is EU-only.
- Adobe needs per-product granularity (Analytics ≠ Target ≠ AAM).
- Adobe cannot rely on the IAB framework to control its internal product suite.
Conclusion:
Adobe does not speak TCF.
Adobe speaks Opt-In Service.
You must translate TCF → Opt-In.
5. Case 3: Matomo Tag Manager + _paq consent API
Matomo also does not read the TCF string.
Matomo exposes its own consent API via its tracker:
_paq.push(['requireConsent']);
_paq.push(['rememberConsentGiven']);
_paq.push(['rememberCookieConsentGiven']);
_paq.push(['forgetConsentGiven']);
These are the only signals that allow Matomo to decide whether:
- cookies can be set
- tracking requests can fire
Example CMP → Matomo mapping:
if (cmpConsent.analytics === true) {
_paq.push(['rememberConsentGiven']);
} else {
_paq.push(['forgetConsentGiven']);
}
Then, Matomo Tag Manager applies its own rules (Require Cookie Consent, Require Tracking Consent, etc.).
6. Comparison Table
| TMS | Understands TCF? | Expected API | Attributes / Methods |
|---|---|---|---|
| GTM | No | Consent Mode V2 | ad_storage, analytics_storage, ad_user_data, ad_personalization |
| Adobe Launch | No | adobe.optIn | approve(), deny(), scopes (analytics, ecid, target…) |
| Matomo TM | No | _paq consent API | rememberConsentGiven(), forgetConsentGiven(), requireConsent() |
Clear conclusion:
CMPs never expose the attributes your TMS needs.
A manual mapping is always required.
7. Universal CMP → TMS mapping schema
CMP (TCF or proprietary API)
→ mapping script
→ target consent API (gtag, adobe.optIn, _paq)
This mapping layer is mandatory in every stack.
8. Most common mistakes
Mistake 1: “The CMP already sends the right data to GTM.”
False. CMPs only expose TCF or their own internal API.
Mistake 2: Loading GTM or Adobe Launch before CMP signals are ready.
This forces a default “denied” state → broken analytics.
Mistake 3: Forgetting the two new Consent Mode V2 attributes:
ad_user_data and ad_personalization
This disables major Google Ads features in Europe.
Mistake 4: Believing Adobe reads TCF.
If Opt-In is not explicitly triggered → Adobe Analytics and ECID simply do not fire.
Mistake 5: Not handling “withdraw consent”.
For Matomo, you must call forgetConsentGiven().
For Adobe, deny().
For GTM, update with denied values.
Final summary
CMPs speak TCF.
TMS tools speak their own APIs.
- Google → Consent Mode V2
- Adobe → Opt-In Service
- Matomo → _paq consent API
There is no universal consent dataLayer.
You must always implement a mapping CMP → TMS API and apply it before any tracking tool fires.
This is what separates a reliable analytics stack from a broken, under-attributing, non-optimizable setup.