Glossary

How a Data Layer Feeds Events to Your Analytics Tags

Taras Shynkarenko
Taras Shynkarenko
•Updated: •8 min read
How a Data Layer Feeds Events to Your Analytics TagsHow a Data Layer Feeds Events to Your Analytics Tags

TL;DR, Quick Answer

8 min read

A data layer is a JavaScript object where a page writes events and values for analytics tags to read. Google Tag Manager and gtag.js share one array, window.dataLayer, and process pushed messages first in, first out, firing tags on the "event" key. Pushed values merge into an abstract data model, so nested objects and arrays carry over between pushes, which is why Google's GA4 ecommerce examples push ecommerce: null before every ecommerce event. The older W3C community spec takes the other approach: one state object named digitalData.

What is a data layer?

In web analytics, a data layer is a JavaScript object on the page where your site writes events and their values, so analytics and marketing tags read clean, named data instead of scraping it out of the HTML. Google's Tag Manager documentation gives the short version: "The data layer is an object used by Google Tag Manager and gtag.js to pass information to tags."

The point of the layer is separation. Your application code knows that a checkout just completed and what it was worth. Your tags know where to send that fact. The data layer sits between them, and Google states the design goal directly: tags "are designed to reference information that is 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." When a redesign moves the price into a different <div>, tags reading the data layer keep working and tags scraping the page break.

What are the two kinds of data layer?

Data layers come in two shapes: a state object that describes the page, and an event queue that records what happened in order. The shape decides how a tag reads it.

State objectEvent queue
ExampleW3C Customer Experience Digital Data Layer 1.0Google Tag Manager, Adobe Client Data Layer
Global namedigitalDatadataLayer, adobeDataLayer
StructureOne nested object with page, product, cart, transaction, event and user childrenA plain array; each push() appends a message
How tags read itRead properties when the tag runsProcess messages in order and react to events
Timing problemA tag that runs before the object is filled reads nothingMessages pushed before the tag library loads wait in the queue

The state-object model is the older one. The Customer Experience Digital Data Layer 1.0, a Community Group Final Report dated December 10, 2013, says the root object "MUST be digitalData, and all data properties within this specification MUST fall within the hierarchy of the digitalData object." Its status section adds that "It is not a W3C Standard nor is it on the W3C Standards Track." Events live in an array inside the object, digitalData.event[n], which the spec defines as a "List of events that were measured."

The queue model won in practice because of load order. Adobe's documentation explains the benefit: pages and scripts "can start to register data, to trigger events, and to register callbacks by adding them to the array, even before the data layer script itself has been loaded." A plain array accepts pushes before any vendor code exists on the page.

A whiteboard diagram of an ordered queue, illustrating how messages are processed one at a time in the order they arrive.

How does a dataLayer.push become an analytics event?

A dataLayer.push() becomes an analytics event when Tag Manager processes the message, matches its event key to a trigger, and fires a tag that reads the pushed values. The sequence has five steps:

  1. Declare the array once, above the container snippet. Google's installation code is window.dataLayer = window.dataLayer || [];, placed before Tag Manager loads.
  2. Push a message with an event name. Google's syntax is dataLayer.push({'event': 'event_name'}), and one push can carry values alongside the event, as in dataLayer.push({'color': 'red', 'conversionValue': 50, 'event': 'customize'}).
  3. Tag Manager queues and processes the message. Google states that "Tag Manager processes messages on a first-in, first-out basis: Each message is processed one at a time, in the order it was received."
  4. A Custom Event trigger matches the event name. "If the message is an event, any tags with trigger conditions that have been met will fire before Tag Manager moves on to the next message."
  5. A Data Layer Variable hands the value to the tag, and the tag sends it on, for example as a GA4 event parameter.

Step 4 explains a rule that trips people up. A push without an event key updates values but fires nothing. Google warns that pushes from page code "are not guaranteed to be available for the next event", and its fix is to "add an event name to a message as it is pushed to the data layer, and then listen for that event name with a Custom Event trigger."

The gtag.js snippet uses the same queue. Google's own snippet defines the gtag function as a one-line wrapper:

window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');

So a site running both gtag.js and Tag Manager has one array receiving messages from both. Google is explicit that "Only one dataLayer object is supported per page."

Why do data layer values carry over from one push to the next?

Data layer values carry over because each push is merged into a running "abstract data model" rather than replacing it. Google's open-source data-layer-helper library, which documents this model, says it "holds the most recent value for all keys that have been set by a data layer message." Scalars overwrite. Plain objects and arrays merge recursively: a new object's keys are copied onto the old object, and a new array's indexes are written over the old array's indexes, leaving any index the new array does not set in place.

That rule is harmless for a pageType string and dangerous for ecommerce. Push a cart view with two items, then a purchase with one item, and the model can still hold the second item from the earlier push. Google's GA4 ecommerce guide for Tag Manager prevents this by clearing first in all 14 of its event examples. Its purchase example, shortened:

dataLayer.push({ ecommerce: null });  // Clear the previous ecommerce object.
dataLayer.push({
  event: "purchase",
  ecommerce: { transaction_id: "T_12345", value: 72.05, currency: "USD", items: [ ... ] }
});

The null works because null counts as "everything else" in the merge table, so it overwrites the old object outright. The next push then merges onto nothing. If your revenue reports show items nobody bought, check for a missing clear before auditing anything else. The GA4 side of that setup is covered in choosing ecommerce tracking tools without overtracking.

A developer troubleshooting code on a laptop, matching the section on tracking down what breaks a data layer.

Ecommerce push without and with a clear
No ecommerce: null
  • Cart view pushes two items
  • Purchase push adds one item
  • The merge keeps the earlier item in the model
  • The GA4 purchase event reports an item nobody bought
ecommerce: null pushed first
  • The clear push overwrites the old ecommerce object
  • The purchase push merges onto nothing
  • GA4 sees only transaction_id T_12345 and its own items
The same merge rule that carries a pageType string forward also carries stale cart items into a purchase event unless the push clears the model first.

What breaks a data layer?

Six mistakes account for most data layers that look correct and drop events. Each comes from Google's own troubleshooting list or follows from the merge rules above.

Flowsery
Flowsery

Start Your 14-Day Free Trial

Real-time dashboard

Goal tracking

Cookie-free tracking

MistakeWhat happensFix
dataLayer = [{...}] after the container loads"it will overwrite any existing values", and Tag Manager stops seeing pushesDeclare once with Google's guarded snippet, then only call push()
datalayer.push(...) in lowercase"The dataLayer object name is case-sensitive", so the push goes nowhereMatch the casing everywhere
visitorType on one page, visitor_type on another"your tags will be unable to consistently fire in all intended locations"One naming convention for the whole site
Values pushed with no event keyValues update but no trigger firesName an event in the same push
Expecting values to survive navigationEach variable "will persist only as long as the visitor remains on the current page"Push page-level values on every page load
No ecommerce clearStale items and values merge into the next eventPush { ecommerce: null } first

The naming row is where a data layer meets the rest of your instrumentation. A data layer is only as consistent as the spec behind it, which is the job of a tracking plan, and the names themselves follow the rules in how an event naming convention survives its first rename.

What should a data layer push contain?

A data layer push should contain the event name and the values a report needs, and nothing that identifies a person. Everything pushed is readable by every tag in the container, including tags added later by someone else. Form field contents, email addresses and names do not belong in the queue; push a form identifier and a result instead, as the practical guide to tracking without cookies lays out for forms.

A useful test is the same one you apply to any event: each value in the push should answer a question a report asks. If nobody can name the report, drop the key. The underlying practice, recording actions as named events with properties, is covered in how event tracking records what users actually did.

Does every analytics tool need a data layer?

No analytics tool strictly needs a data layer; the layer exists so a tag manager can route one set of values to many vendors. A tool that takes events from a direct function call skips the queue and the merge rules. Flowsery works that way: its goal tracking records events from a single call like window.flowsery("signup"), with "No complex setup or tag managers needed." Events appear in a real-time feed so you can "Debug and validate your tracking instantly", revenue values can be attached to events to measure the impact of each action, and events are tracked without cookies or personal data. The goal and event tracking feature shows the setup. Sites that already run a data layer for other vendors can keep it, and call window.flowsery() from the same code that pushes the event.

Frequently asked questions

Is the data layer the same as Google Tag Manager?

No. The data layer is the array on your page, and Tag Manager is one consumer that reads it. Google's snippet for gtag.js uses the same dataLayer array without Tag Manager, and Adobe's client data layer uses its own array named adobeDataLayer.

Where should the data layer code go on the page?

Declare it as high in the page as possible, above the Tag Manager or gtag.js snippet. Google says any values that "need to be available to Tag Manager when the page loads" must be pushed above the container code as well. Pushes placed lower still reach the queue but arrive after the container's first events.

Can I rename the dataLayer variable?

Yes. Tag Manager takes the name as a parameter in its container snippet, and gtag.js takes an l query parameter, as in l=myNewName. Every declaration and every push must then use the new name, because pushes to the old name reach nothing.

Why does my GA4 purchase event contain items from an earlier event?

The earlier push merged into the data model and your purchase push did not clear it. Arrays and plain objects merge recursively, so leftover items survive. Push { ecommerce: null } immediately before each ecommerce event, as Google's examples do.

Do data layer values persist across page loads?

No. Google states that each data layer variable persists "only as long as the visitor remains on the current page." Values that matter on every page, such as a visitor type or page category, have to be pushed again on each page load.

What is the difference between dataLayer.push and gtag?

gtag() is a wrapper that calls dataLayer.push(arguments), so both write to the same queue. The difference is the message format and custom methods: Google says functions pushed to access set, get and reset "must use .push" directly, because gtag interprets a function as "an invalid command" and ignores it.

Why didn't my dataLayer.push fire a tag?

A push only fires a tag when it carries an event key that a Custom Event trigger is listening for. Values pushed without one still update the data layer, but Tag Manager has nothing to match against, so no trigger runs and no tag fires. Add the event name to the same push, or those values sit there until a later message brings one.

Should I use digitalData or dataLayer for a new project?

Pick the event queue model, the one dataLayer and adobeDataLayer both use. It accepts pushes before any vendor script has loaded, which is exactly the load-order problem the state-object model runs into: a tag that reads digitalData before the object is filled reads nothing. digitalData also comes from a 2013 Community Group report that states plainly it is not a W3C Standard.

Is it safe to push email addresses to the data layer?

No. Everything pushed to the data layer is readable by every tag in the container, including tags added later by someone else. Push a form identifier and a result instead, never the actual field contents, name, or email address.

Is adobeDataLayer the same as Google's dataLayer?

Both are plain arrays that process messages in order, but they are separate globals. Google's Tag Manager and gtag.js share window.dataLayer, and Adobe's client data layer uses its own array, window.adobeDataLayer. Adobe's documentation describes the same load-order advantage. Pages and scripts can register data and trigger events by pushing to the array before the data layer script itself has loaded.

Was This Article Helpful?

Let us know what you think!

See us more often in Google

One click marks Flowsery as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.

Before you go...

Flowsery

Flowsery

Revenue-first analytics for your website

Track every visitor, source, and conversion in real time. Simple, powerful, and cookie-free.

Real-time dashboard

Goal tracking

Cookie-free tracking

Related Glossary Terms

Related Articles