scalpel@labs: ~/glossary/datalayer.mdx5 sections

What is the dataLayer?

The `dataLayer` is a plain JavaScript array on the page. Your site pushes objects into it (events, ecommerce details, user state), and Google Tag Manager reads those objects to decide which tags to fire and what data to send.

extension: Scalpel Tagsupdated: 2026-08-14read_time: 2 min
less datalayer.mdx

Why it matters

Without the dataLayer, your site and Google Tag Manager can't communicate. Tags would have no way to know what a user just did or what data matters for a goal. The array is where your custom events live, where you stash user login state, where ecommerce data sits before a tag reads it. If you're running GTM and not using the dataLayer, you're leaving GTM nearly powerless.

How it works

The dataLayer starts as a simple JavaScript array on the page, initialised before any GTM code runs. You push objects into it. Each object is a snapshot of what happened: a user viewing a product, adding to cart, or logging in. GTM watches for these pushes. When a push arrives, triggers check the event value inside it; if there's a match, tags fire with that data.

Here's the order:

  1. Your page creates an empty dataLayer (or GTM creates it for you if you skip this).
  2. Your site pushes data into it as things happen on the page.
  3. GTM's script loads, reads the dataLayer, applies any existing entries.
  4. Pushes after that trigger in real time.

One key detail: GTM merges objects into a running state. If you push {page: 'home'} then later push {page: 'about'}, the second push overwrites the first. But if you push {user: {name: 'Alice'}} and then push {user: {id: 123}}, GTM merges them into {user: {name: 'Alice', id: 123}}. This is important because it means later pushes can add to the state without wiping out earlier data.

What does not matter

You do not need to use the dataLayer if you're only running gtag.js directly to Google Analytics. gtag has its own internal arguments array; they're separate systems. But if you're running GTM at all, the dataLayer is not optional. It's the only channel GTM has to receive structured data from the page. Also, the size of your dataLayer array doesn't matter for performance; even with thousands of pushes, it's negligible overhead.

Code example

// Initialise the dataLayer before the GTM snippet loads
window.dataLayer = window.dataLayer || [];

// Push a custom event with an ecommerce object
dataLayer.push({
  event: 'view_item',
  ecommerce: {
    items: [
      {
        item_id: 'SKU123',
        item_name: 'Blue Running Shoe',
        price: 79.99,
        quantity: 1
      }
    ]
  }
});

// Push a user login event (overwrites the previous event, adds new data to state)
dataLayer.push({
  event: 'login',
  user_id: 'u_42',
  user_email: 'alice@example.com'
});

How Scalpel Tags shows it

The DevTools panel has a dedicated dataLayer tab. You'll see a timeline of every push, with the timestamp, the event name, and the data inside. Click a push to see the full object. The diff view next to it shows what that push changed in the accumulated state: what got added (green), what changed (amber), and what got removed (red). The State view shows the entire dataLayer as it stands after that push, with all earlier pushes folded in using GTM's merge rules.

Sources