How dataLayer.push works
The data layer is a simple list the page creates before Tag Manager loads. Pushing adds an object to that list, and Tag Manager processes each addition in order. Any values in the object become available to variables. If the object also carries a key named event, Tag Manager treats the push as a named occurrence that triggers can listen for — which is how a website says “a form was submitted” rather than leaving the container to guess.
Sequence is the part beginners miss. A tag can only read what has already been pushed, so the push has to happen before the tag fires, and the data layer has to be declared above the container snippet so that early pushes are not thrown away. Get the order wrong and everything looks installed while nothing arrives.
Why dataLayer.push matters
It is the supported way for a website to describe what happened in its own words. Order value, currency, lead type, which package a visitor asked about, whether a returning customer is logged in, whether the enquiry passed server-side validation — none of that is visible to a container watching from outside. It can only arrive because the application deliberately hands it over.
It is also the durable option. A push lives in the site’s code beside the thing it describes, so it survives a redesign that would break any trigger built on button text or CSS classes. When measurement matters to the business, this is the difference between tracking that lasts and tracking that has to be rebuilt every time the site changes.
Where dataLayer.push goes wrong
Pushing at the wrong moment is the most expensive fault. A success event fired when the confirmation message appears, rather than when the server confirms the record was saved, counts enquiries that never reached anyone’s inbox.
Stale values cause the quieter kind. Once pushed, a value stays available for the rest of that page view, so a product object left over from an earlier interaction can attach itself to the next event and report the wrong item. Clearing the keys you no longer want, before the next push, prevents it.
Then there is naming. One template pushing form_submit while another pushes formSubmitted gives you two half-populated reports and a trigger that works on some pages only. And reassigning the data layer to a new list, instead of pushing to the existing one, disconnects it from Tag Manager entirely — the code runs, no error appears, and nothing fires.
How to act on it
Write the specification before anyone writes code: a short table of the events worth recording, the exact name of each, and the fields each one carries. Hand that to whoever builds or maintains the site, and keep it as the reference both sides work from. This is the cheapest part of an analytics and tracking setup and the part that most often gets skipped.
Use lowercase names with underscores, keep them identical across every template, and never push an email address, phone number or full name — the data layer is readable by anything running on the page. Then test in preview against real journeys, including the awkward ones, and retest after each website release, because a deployment that moves a button will happily leave the tracking behind.