Home / dataLayer inspector
A dataLayer inspector that keeps the order
You can type dataLayer in the console. What comes back is an array with no timing, no consequences and nothing from before the last navigation.
The console is the default answer and it is not wrong, exactly. Typing dataLayer
gives you the pushes as an array, which is enough to confirm a key exists. It is the questions
after that one where it runs out.
Why the console is not enough
- The array is not the model. GTM keeps a merged state built from every push; the array is the log that produced it. A key written by one push and overwritten by a later one appears twice in the array, and neither entry tells you which value a tag actually read.
- There is no timing in it. Whether the push landed before or after the tag that needed it is very often the entire bug, and an array of objects carries no clock.
- It ends at the last navigation. On a normal site the pushes you wanted are gone the moment the page changed. On a single-page app the array survives but the ordering across routes is exactly what you cannot see.
- Nothing connects a push to its consequences. The console shows the push. It does not show that the push fired three tags, or that it fired none.
What the panel shows
Every push, in the order it happened, held across navigations, with the tracking requests each one produced nested underneath it. The event name, the full object, and — for the pushes that caused something — the platforms that reacted.
A push with nothing under it is a trigger that did not match. Requests with no push above them are a tag firing on something else entirely. Both readings are impossible from an array, and both are the answer most of the time.
From a push to GTM variables
Once you have found the push you need, the rest of the job is transcription: writing each dot-path into GTM as a Data Layer Variable, then a Custom Event trigger, then wiring a tag to them. Picking the event in the panel and ticking the values you want produces all three, already shaped for import.
What comes out is a GTM container export, not a session file — it goes into GTM, and there is no loading it back into the extension. What that file has to contain covers the two fields that make GTM refuse the whole import, and picking the event covers the step before it.
Where the console still wins
Reading the merged model right now.
google_tag_manager['GTM-XXXXXX'].dataLayer.get('ecommerce') returns the value GTM
would hand a variable at this instant, which is exact, immediate and something a recorded
history cannot give you. A panel that captures pushes is a record of what happened; the console
is a probe into what is true. Use the probe when you are asking about now.
Questions
How do I view the dataLayer on a page?
Typing dataLayer in the browser console returns the array of pushes. For the order, the timing and what each push caused, a panel that records them as they happen shows what the array cannot.
Why is the console dataLayer different from what GTM reads?
The array is the log of pushes; GTM keeps a separate merged state built from them. When a key is written twice, the array holds both and the model holds the last one — which is the value a variable resolves to.
Does it work on single-page apps?
Yes, and this is where it matters most. Pushes are held across route changes, so the ordering between a virtual pageview and the events around it stays readable instead of scrolling away.
Can I turn what I find into GTM variables?
Yes. Picking an event and ticking the values you want produces the Data Layer Variables, the Custom Event trigger and a tag wired to them, as a GTM container export ready to import.
Does it work on sites I do not own?
Yes. Nothing is required from the site — no container access, no code change, no debug session.
Guides
The longer form, on the parts that catch people out.
- One click, three pushes: picking the right dataLayer event — Adding to cart rarely fires one event. What a real storefront pushes, which of them a trigger should use, and the four kinds of push that are never the answer.
- Turning captured dataLayer pushes into a GTM container you can import — What a container export file has to contain, the two fields that make GTM refuse the whole import, and why placeholders beat blanks.
- How a visual element picker works on a page that fights back — Pointing at an element sounds simple until the page navigates under you. What a picker has to intercept, what it snaps to, and the selector call that throws.
- A GTM click trigger the next deploy will not break — Why a copied CSS selector stops matching, which attributes are worth anchoring to, and the Tailwind class that silently makes a selector invalid.
- Tracking inside an embedded widget — A booking widget or payment step in an iframe has its own dataLayer. Why Preview shows one event where the log shows two, and what crosses the boundary.
- How to inject a GTM container into any website — Test a container before it ships — on a client site, a staging build, or a page you do not control — without touching the codebase.
The other two: GTM debugger, GA4 debugger
Try it on your own site
Tag Master is free, needs no account, and collects no data.
Add to Chrome — Free