The symptom is disorienting because everything else looks right. The shop takes orders, the reports fill up, GA4 shows purchases. You open a dataLayer inspector on the same page to check what the checkout pushes, and the list is empty. Not wrong — empty.
Almost every answer to this assumes a mistake: the container is missing, the snippet is above the push,
the layer is named something else. Sometimes it is one of those. On four widely-used platforms it is
none of them, and no amount of looking at window.dataLayer will help, because that is not
where the events are.
The dataLayer is not the only data layer
An extension reading dataLayer is reading one array on the top window. That convention
belongs to GTM. Other stacks never adopted it:
- Tealium carries events through
utag.view()andutag.link()— function calls, not an array. There is autag_dataobject, but it holds page variables, not the sequence of what happened. - Adobe Launch uses
_satellite.track()and its own rules. - Adobe CEDDL uses
digitalData, and the newer Adobe Client Data Layer usesadobeDataLayer.push()— an array, but a different one. - Commanders Act uses
tc_varsandtC.event.
A panel that shows an empty list on a Tealium site is not reporting the truth. The truth is that the
events exist and travel by another road. Tag Master names the foreign layer it found and says what it
sends — Tealium, through utag.view() and utag.link() — rather than leaving
a blank list to interpret. For Adobe Launch it goes one step further and reads the rules that fired,
through the monitor hook Adobe publishes for exactly that purpose.
Shopify is the hardest case, and the most common
Shopify moved its tracking into Web Pixels: small scripts that run inside a sandboxed
frame with their own event bus and their own dataLayer. product_added_to_cart,
checkout_started and checkout_completed are dispatched in there. They do not
reach the top window, and nothing running in the page can subscribe to them — not this extension, not
any other. That is the sandbox working as designed.
Checkout makes it worse, because Shopify’s checkout has always been a separate context. So the one
event most implementations care about most, purchase, is also the one furthest out of reach
of anything reading the page.
The exception is a store running Elevar or a similar relay, which republishes the
sandbox’s events onto the page as dl_purchase, dl_add_to_cart and the rest. If
those names are showing up, the layer is being relayed and you are reading a copy — a good copy, but
under a different spelling.
Where to read them instead
On every one of these platforms the events still turn into network requests, and requests cannot be
sandboxed away from a debugger that watches the network. What GA4 received is in the
/g/collect hit; what Meta received is in the /tr call. The push is hidden; the
consequence is not.
So the procedure inverts. Instead of reading the push and checking that the tag matched it, you read the hit and work backwards to whether it carried what it should have: the right event name, a value, a currency, a transaction ID. Reading a GA4 hit parameter by parameter is the whole skill on these shops, and listing what the page sent is how you find out which platforms are involved before you start.
Before you go looking for a bug
- Confirm which layer the site actually has.
window.utag,window._satellite,window.adobeDataLayer,window.Shopify— one line in the console each, and the answer changes what you do next. - If it is Shopify without a relay, stop looking for pushes. Go to the network.
- If it is Tealium or Launch, the events are in the vendor’s own debug console, which can be switched on for the tab you are already using.
- Only then, if the site really is a GTM site with a real
dataLayer, treat an empty list as a bug worth chasing.
An empty inspector is a fact about where the events are, not a verdict on whether they exist. The shops above are the reason to check which of the two you are looking at.
Questions
Why is my Shopify dataLayer empty?
Because Shopify’s Web Pixels run inside a sandboxed frame with their own dataLayer. product_added_to_cart and checkout_completed never reach the top window, so no extension running in the page can see them — this one included. The requests they produce are still on the network.
Is checkout tracking really invisible?
The pushes are. Shopify’s checkout has always run in its own context, and Web Pixels formalised that. What the pixels send out is ordinary network traffic and is readable in full, which is why the answer on a Shopify store is to work from the hits rather than the layer.
What about Tealium and Adobe?
Neither uses an array. Tealium sends events through utag.link() and utag.view(), Adobe Launch through _satellite.track(). Those are function calls, so no list of dataLayer names reaches them. Launch is the exception with a documented monitor hook, and the rules it fired can be read through it.
Does an empty dataLayer mean tracking is broken?
No, and treating it that way is the expensive mistake. A shop can send a perfectly correct purchase to five platforms with nothing in window.dataLayer at all. Check the network before concluding anything about the layer.
The rest of this group: Shops and their data layers
More in Shops and their data layers
Try it on your own site
Tag Master is free, needs no account, and collects no data.
Add to Chrome — Free