TagIntact
Module 1 · Lesson 3 of 4 · 9 min

The dataLayer

The contract between your website and your tags — and the reason most "GTM problems" are actually website problems.

Verified against Google Tag Manager web container, September 2026 interface on 2026-09-27

Open any page with GTM on it, open the console, and type dataLayer. You'll see a JavaScript array. That array is the entire mechanism.

window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: "add_to_cart",
  ecommerce: {
    currency: "USD",
    value: 24,
    items: [{ item_id: "SKU-1001", item_name: "Canvas Tote", price: 24, quantity: 1 }]
  }
});

That push is the website saying, in a structured way, "something happened, and here are the facts about it." GTM watches the array. When an object with an event key lands, GTM emits that event internally; a Custom Event trigger named add_to_cart matches it; the tags on that trigger fire; a Data Layer Variable with the key ecommerce.value reads 24 out of the object.

Website pushes facts in. Container reads facts out. Neither side needs to know how the other works.

Why this beats scraping the page

The alternative to a dataLayer is reading values off the DOM — a Custom JavaScript variable that finds the price with document.querySelector('.price').innerText. It works until the designer renames the class, at which point every ecommerce tag sends undefined and nobody notices for a month.

A dataLayer push is a promise made by the developer. It's in the codebase. It survives redesigns. It can be tested. When a value is wrong, the question "is this a site bug or a container bug?" has an answer in ten seconds: look at the push.

That is why almost every "GTM problem" a consultant gets called for is a dataLayer problem: the site pushes the event after the page navigated away, pushes value as a string with a currency symbol in it, pushes items as an object instead of an array, or doesn't push at all on the thank-you page because the developer tested on a staging build where it did.

The shape GA4 wants

GA4 has a set of recommended events with fixed parameter names. If you push these shapes exactly, the GA4 Event tag can read ecommerce straight from the dataLayer with one checkbox — "Send Ecommerce data" — and every ecommerce report lights up.

Event Required inside ecommerce
view_item currency, value, items[]
add_to_cart currency, value, items[]
begin_checkout currency, value, items[]
purchase transaction_id, currency, value, items[] (plus tax, shipping)

Each entry in items[] needs at least item_id or item_name; price and quantity are how revenue by product is computed.

Two habits that save real pain:

  • Push { ecommerce: null } before every ecommerce push. The dataLayer merges objects; without the reset, an items[] from the previous event can leak into the next one.
  • Push the event before navigation, or on the next page. A push fired 50 ms before window.location = "/thank-you" may never be processed. Purchase belongs on the thank-you page, guarded so a refresh doesn't fire it twice.

Reading it

In GTM Preview mode, click any event in the left timeline and open the Data Layer tab: it shows the array's state after that push. That view — not the code, not the report — is where you check whether the contract was kept.

Try it

The sandbox store is a fake shop whose every page pushes the GA4 recommended events above with correct shapes. Open it, open the console, add something to the cart, and type dataLayer — the last element is the add_to_cart push, with the ecommerce: null reset just before it. In Module 2 you'll point your own container at it.

Try it in the sandbox

The sandbox store fires real ecommerce dataLayer events and loads your GTM container, so you can build the tag from this lesson against live events.

Open the sandbox
The dataLayer — Tracking Foundations · TagIntact