How do I feed an existing GTM dataLayer into Adobe Launch (or push data the other way)?
Google Tag Manager's window.dataLayer and Adobe Launch's data elements are both just reading state off the page - there's no special integration required, only an agreement on where the data lives. Point a Launch Core extension "JavaScript Variable" data element at dataLayer, or add a small custom code data element that reads the latest matching push, and use Launch's own triggers (not GTM's) to fire your Adobe rules. Going the other direction - Adobe/AEP data into GTM - means having Launch push into the same dataLayer array GTM already listens to.
Why this happens
Teams end up needing this bridge for an ordinary reason: GTM and Launch were adopted at different times, by different teams, for different vendors, and the site's actual data layer only ever got built once - usually the GTM one, since GTM shipped first in most organizations. Rebuilding a second, Adobe-specific data layer is wasted engineering effort when the existing dataLayer array already carries the same page/event context both tools need.
The two systems model "an event happened" differently, though, which is where the confusion comes from: GTM triggers are usually configured to react to a dataLayer.push() as it happens (an event-driven model), while a naive Launch data element just reads the current value of a variable at rule-evaluation time - it has no built-in concept of "a push just occurred." Copying a GTM trigger's timing assumptions into Launch without accounting for that difference is the usual source of "the data element read stale data" bugs.
Fix it
1. Reading GTM's dataLayer from a Launch data element (state, not events). If you only need the current value of a field (a product ID, a page category), a JavaScript Variable data element works directly against the array's most recent matching object:
return (function () {
var dl = window.dataLayer || [];
for (var i = dl.length - 1; i >= 0; i--) {
if (dl[i] && dl[i].event === 'productViewed') {
return dl[i].productId || '';
}
}
return '';
})();2. Reacting to a specific GTM-style event in Launch (event-driven, not state). Add a small listener once, early in the page lifecycle, that re-dispatches matching pushes as a native custom event Launch's Core extension can trigger on:
(function () {
var dl = window.dataLayer = window.dataLayer || [];
var originalPush = dl.push;
dl.push = function () {
var result = originalPush.apply(dl, arguments);
Array.prototype.forEach.call(arguments, function (item) {
if (item && item.event) {
document.dispatchEvent(new CustomEvent('adobe:' + item.event, { detail: item }));
}
});
return result;
};
})();Then create a Launch rule with a Core "Custom Event" trigger listening for adobe:productViewed on document, and read event.detail in a data element for the actual payload. This fires reliably even if the push happened before Launch's listener attached, as long as the override runs early - place it ahead of the Launch embed code, or as the very first thing a Launch rule's condition checks for.
3. Going the other direction - Adobe/AEP context into GTM. Push into the same array GTM already reads, from a Launch rule's custom code action, using the field names your GTM triggers expect:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'aepIdentityReady',
ecid: _satellite.getVar('ECID') || ''
});Do this only for context GTM's own tags genuinely need (a resolved identity, a consent decision already made). Mirroring every Adobe event into GTM's data layer just to "keep them in sync" duplicates two tag managers' worth of firing logic and doubles the places a broken change can hide.
How to verify it worked
- In the browser console, run
window.dataLayerand confirm the object you expect is actually in the array, with the field names your data element reads. - Open the Adobe Experience Platform Debugger, trigger the action, and check the data element's resolved value in the Debugger's rule/data-element inspector - not just whether the rule fired, but what value it actually captured.
- Confirm the resulting Adobe Analytics or Web SDK beacon in the Network tab carries that value in the expected variable or XDM field - a data element resolving correctly in the Debugger but never reaching the report suite usually means a separate mapping issue further down the rule, not the bridge itself.
Illustrative, not a measured result: a site that maintained two parallel data layers - one hand-built for Adobe, one for GTM - might retire the Adobe-specific one entirely once Launch reads directly off the array GTM already populates, removing an entire class of "the two data layers drifted apart" bugs.
Related
- Why does "_satellite is not defined" happen even though Adobe Launch is installed?
- What's the right pattern for Adobe Analytics/Launch in a React, Next.js, or Angular SPA?
- How do I build an Adobe Launch rule that reliably tracks form submissions and clicks?