The GTM Data Layer: Passing Site Data to Tags

The data layer is how your website hands facts to Google Tag Manager: that a form was sent, which service it was about, what was bought. This guide explains how to set it up, push events and values, read them in Tag Manager, get the timing right, send ecommerce data and avoid the mistakes Google lists.

This guide is based on Google's own documentation: the developer guide to the data layer, the Tag Manager Help pages on user-defined variable types, the custom event trigger, built-in variables and preview and debug, and the Google Analytics developer guide to measuring ecommerce with Tag Manager, all checked on 8 November 2026. If you are new to containers, tags and triggers, start with our Google Tag Manager basics guide; this one goes one level down, to the code your developer writes.

What the data layer is

Google's developer guide defines the data layer as "an object used by Google Tag Manager and gtag.js to pass information to tags". In code it is a JavaScript array called dataLayer. Your site adds messages to it, such as "a form was sent" or "this page is in the pricing section", and Tag Manager reads them.

The point is to give tags a clean, agreed source of facts. Google says its tags are designed to use information added to the data layer "in an organized and predictable way, rather than by parsing variables, transaction information, page categories, and other signals scattered throughout your page." Reading a price from a page element works until someone redesigns the page. A value your site pushes to the data layer keeps working as long as the developer keeps pushing it.

Typical things a business site puts in the data layer:

  • an event when an enquiry form is really sent, not just when the button is clicked;
  • details of that enquiry that are not personal, such as which service was chosen;
  • a page type or category, such as service page, guide or checkout;
  • for a shop, the products viewed, added to the cart and bought.

Everything here is about the web container that runs on your pages. Moving tags to a server container is a separate step, covered in our server-side tagging guide.

Setting it up on the page

"For Tag Manager web page installations, you must create a data layer," Google says. The line that creates it goes above the Tag Manager container snippet, as high in the page as possible:

<script>
  window.dataLayer = window.dataLayer || [];
</script>
<!-- Google Tag Manager container snippet follows -->

The || [] part matters. It keeps whatever is already in the data layer and only creates a new, empty array if none exists. The Google tag snippet that you copy from Google Analytics or Google Ads already contains this line, so a site with both does not need it twice.

Two rules from Google's guide apply to every site:

  • One data layer per page. "Only one dataLayer object is supported per page." Tag Manager and the Google tag listen to a single global array; pushes to a second array are not seen, so tags do not fire.
  • The name. The default name is dataLayer. You can rename it by changing the data layer parameter in the container snippet, but then every push on the site must use the new name. Most sites have no reason to change it.

Pushing events and values

Everything after setup goes in with dataLayer.push(). Google's guide shows two kinds of message.

Events

An event is a message with the special key event:

dataLayer.push({'event': 'event_name'});

Google's examples of names are 'login', 'purchase' and 'search'. On its own, an event name does nothing. In Tag Manager you create a Custom Event trigger with the same name and attach it to the tags that should fire. Google's help page for that trigger notes its most common use: tracking form submissions when the form's normal submit behaviour has been changed. More broadly, Google describes it as a way to track interactions that "aren't handled by standard methods."

Values

Values are plain key and value pairs, and they can travel in the same push as the event:

dataLayer.push({
  'event': 'enquiry_sent',
  'service': 'website-maintenance'
});

The names here are our example, not Google's. Google's own examples include a colour chosen in a product tool and, on the custom event trigger page, a conversion value sent with a button click and then used "in the conversion value field of your Google Ads conversion tracking tag."

One detail to know: "If you push a variable with the same name as an existing variable to the data layer, the existing value will be overwritten by the new value." That is useful for updating a value, and a source of wrong data if two scripts use the same name for different things.

Reading values in Tag Manager

To use a value in a tag, you create a Data Layer Variable in Tag Manager (Variables, then New under User-Defined Variables) and type the key name, such as service. Google suggests descriptive names such as "Data Layer Variable - Product Name". The variable can then fill a field in any tag, for example an event parameter in a Google Analytics event tag.

The variable has a version setting that decides how dots in key names are read:

SettingHow Tag Manager reads "a.b.c"
Version 1Dots are allowed in key names, so it looks for one key literally called a.b.c.
Version 2Dots mean nesting, so it reads {a: {b: {c: "value"}}}. This is what lets a variable reach inside an object such as ecommerce.value.

Tag Manager also writes to the data layer itself. Its automatic events and built-in variables use keys that start with gtm.; the built-in variables page, for example, describes History Change values read from gtm.newUrlFragment and similar keys. Our advice: avoid that prefix for your own names. To pass a value onward to Google Analytics as a custom parameter, you also need to register it in GA4, which our GA4 custom dimensions guide covers.

Order, timing and page loads

Most strange data layer bugs come from timing. Google describes the processing order: Tag Manager handles messages "on a first-in, first-out basis", one at a time, and when a message is an event, all tags whose triggers match fire before the next message is processed.

Pushes made by code on the page, in a Custom HTML tag or in a custom template are queued behind messages already waiting, so Google warns that "any updated data layer values are not guaranteed to be available for the next event." Its fix: add an event name to the push that carries the new value, and fire the tag on that event with a Custom Event trigger. In practice, send the value and its event together, as in the enquiry example above, rather than in two separate pushes.

The data layer also starts empty on every page. "Each variable declared within the data layer object will persist only as long as the visitor remains on the current page." A value needed on every page, such as a visitor type in Google's example, has to be pushed on every page. If Tag Manager needs it as soon as the container loads, the push goes above the container snippet. Google adds that you don't need the same set of variables on every page, but "you should use a consistent naming convention".

For pages that stay open a long time, such as single-page apps, Google offers a reset method, "most useful with a page that will remain open and the data layer size continues to grow over time." It only works through dataLayer.push(); sent through gtag(), Google says the function is ignored as an invalid command.

The ecommerce object

Shops send product data to Google Analytics through the data layer in a fixed shape: an event such as view_item or purchase, with an ecommerce object holding the currency, value and an items list. Our GA4 ecommerce tracking guide covers which events to send and how they show up in reports. The data layer details from Google's Tag Manager version of that guide are:

  • Clear the old object first. Every example pushes dataLayer.push({ ecommerce: null }); before the new event, with the comment "Clear the previous ecommerce object." That way each event starts from an empty ecommerce object instead of building on the previous one.
  • Let the tag read it. In the Google Analytics event tag, use the built-in {{Event}} variable as the event name, then under More Settings, Ecommerce, choose Send Ecommerce data with Data Layer as the data source.
  • Currency. Google asks you to "Set currency at the event level when sending value (revenue) data."
  • Trigger. Each ecommerce event gets a Custom Event trigger with the matching name, for example view_item_list.

Mistakes Google warns about

Google's troubleshooting section and its help pages name these errors.

MistakeWhat happensWhat Google says to do
Writing dataLayer = [...] instead of pushingOverwrites everything already in the data layerCreate it once with window.dataLayer = window.dataLayer || []; and use push() after that. "Never overwrite or re-assign the window.dataLayer variable."
Wrong casing, such as datalayer.push"the push won't work"The object name is case-sensitive: dataLayer.
Key names without quotes, such as new-variable: 'value'Not a valid JavaScript objectPut data layer variable names in quotes.
Different names for one thing, such as visitorType and visitor_typeTags "will be unable to consistently fire in all intended locations"Keep names the same across pages.
More than one data layer, or resetting it after Tag Manager loadsTags may not fire, data goes missing or is incomplete, debugging gets hardOne data layer per page, created high in the <head>.
A Custom Event trigger with the regex .*Fires on all events, "including events that Google Tag Manager and Google tag emit automatically"Use a more restricted pattern.
Setting consent or loading gtag.js code in Custom HTML tagsConsent may be applied too late for tags on the same eventUse Tag Manager's consent APIs and its built-in Google Ads, Analytics and Floodlight templates.

The consent point ties into how your banner works; our cookie consent banners guide explains consent mode and what the banner should send.

Checking it in preview mode

Tag Manager's preview mode lets you "browse a site on which your container code is implemented as if the current container draft was deployed." It opens Tag Assistant, which shows which tags fired, in which order and with what data, and it is "not visible to your regular website visitors." Google's data layer guide adds that you can use Tag Assistant "to inspect the status of your data layer at any point in a chain of events."

A simple test routine: open preview, do the action (send the test form, add a product to the cart), then click that event in Tag Assistant and check that the event name, every value and the tags that fired are what the spec says. Preview links can be shared, so a developer and a marketer can check the same session.

Writing it down

Our suggestion, not a Google rule: keep a short data layer document next to the site's code. For each event, list the name, when it fires (after the form is accepted, not on the click), each key and an example value, and which tags use it. It does not need special software; a table in a shared document is enough.

  • Use one naming style for every key, and never reuse a name for something else.
  • Keep names, email addresses and phone numbers out of the data layer unless a tag is specifically built and consented for them.
  • Have the developer run the test routine above after each release that touches forms, checkout or templates.
  • When the site is rebuilt, hand the document to the new developer with the brief, so tracking is part of the build and not an afterthought.

If your site needs a clean data layer added, it is part of our website development work. Keeping it working through updates fits our website maintenance.

Frequently asked questions

What is the data layer in Google Tag Manager?

A JavaScript array called dataLayer that your site uses to pass information to Tag Manager and the Google tag. The site pushes events and values into it, and Tag Manager uses them in triggers and variables.

Where does the dataLayer code go?

Google says to create it with window.dataLayer = window.dataLayer || []; as high in the page as possible, above the Tag Manager container snippet. Any values Tag Manager needs when the container loads should be pushed above the snippet too.

How do I fire a tag from a data layer event?

Push the event with dataLayer.push({'event': 'your_event_name'}), then create a Custom Event trigger in Tag Manager with the same event name and attach it to the tag.

Why is my data layer variable empty?

Common causes in Google's documentation: the key is spelled or cased differently on that page, the value was pushed after the event that fired the tag, the value was set on an earlier page (values only last for the current page), or the dataLayer was overwritten instead of pushed to.

Why push ecommerce: null before an ecommerce event?

Google's Tag Manager ecommerce examples clear the previous ecommerce object with dataLayer.push({ ecommerce: null }) before each new ecommerce event, so the event starts from an empty ecommerce object.

Tracking is only useful when the site behind it works. See our website development and website maintenance services and all our services, or email [email protected].