Updated: August 5th, 2018. Data Layer is one of the main Google Tag Manager concepts which ensures maximum flexibility, portability, and ease of implementation. Without it, there would be no variables or triggers in GTM, therefore no tags would be fired. It is what keeps your tag management running properly. It is the key to unlocking Google Tag Manager’s potential.

In this blog, I’ve already published several articles related to this topic but they are pretty much scattered. That’s why I decided to collect all the important resources, tips, and knowledge (that I’ve accumulated so far) and put it in one place. This is an extended Google Tag Manager Data Layer tutorial which explains what the Data Layer is, why is it useful, how to use it, what are best practices, etc.


table of Contents

This Google Tag Manager Data Layer tutorial is split into the following chapters:

  1. What is the Data Layer?
  2. Storing data in the Data Layer (dataLayer.push)
  3. Reading data from the Data Layer
    1. Data Layer Variable
    2. Data Layer Versions
    3. What about other data structures?
    4. Pull data from child keys
    5. Arrays
  4. Sending data from Data Layer to other tools
  5. Using Data Layer data as triggers
  6. Using Data Layer events as triggers
  7. Google Tag Manager Data Layer Tutorial: Final words

#1. What is Data Layer?

Technically speaking, a Data Layer is a JavaScript array that stores certain information. If that does not ring a bell, here’s a more simple explanation.

It’s an invisible/virtual layer of a website where you, your developers, or various tools can store data (about user, page content, etc.). From there, Google Tag Manager reads that information, uses it in tags/triggers/variables or sends further to other tools, Google Analytics, Google Ads, Facebook Pixel, you name it.

Google Tag Manager Data Layer Tutorial Scheme

Once you place GTM container’s JavaScript Snippet in your website’s source code, the Data Layer is automatically created. You don’t need to add anything more (unless you want to fill it with additional data).

Google Tag Manager Data Layer can contain various information which can be done by placing an additional Data Layer snippet above Google Tag Manager snippet or by using dataLayer.push method.

Continue reading this Google Tag Manager Data Layer tutorial to find out why dataLayer.push should be your only option to add the data to the Data Layer.


#2. Storing data in the Data Layer (datalayer.push)

There are two ways how data can be pushed to Data Layer. Actually, there is the only one you should use, but for sake of knowledge I’ll mention both:

  1. By adding Data Layer snippet above the GTM container snippet (this method is called Data Layer Declaration).
  2. Or by pushing data with dataLayer.push method. What’s the difference, you ask?

The first method is useful if you want to push any custom data right when the page loads. Example: product data when the product page loads. You might want to send that product data (from the Data Layer) to Facebook Pixel (with View Content event).

In this case, your developers should add a Data Layer snippet above GTM tracking container with the parameters like product ID, product title, etc. Here’s an example:

Later, with help of the Data Layer variable, you would be able to read that information and transfer to FB Pixel (continue reading this Google Tag Manager Data Layer tutorial and I’ll explain how to read that information).

The second method (recommended) (dataLayer.push) lets you push additional data when certain events occur on your website. Here are a few examples:

  1. You have a newsletter signup form (which cannot be easily tracked with a default GTM’s form listener). You should ask your website developer to fire a Data Layer event once a new subscriber has entered his/her email on your website:

    If you wish you can ask your developer for additional information (e.g. form location (because you might have more than one form on the same page)).
  2. When a visitor adds a product to his/her cart, a Data Layer event (containing product’s information) could be fired.

IMPORTANT: After I wrote my first blog post about the Data Layer back in 2016 (later, I updated it several times), I was following Google’s documentation which suggested that I have to place dataLayer = [{}] above the GTM snippet and dataLayer.push whenever an important event occurred.

But later I noticed multiple GTM experts suggesting that this is not the best practice (Phil Pearce, Simo Ahava). Instead, you should ALWAYS:

  1. Use dataLayer.push (forget dataLayer = [{}];)
  2. And upgrade it by adding window.

All examples in this blog post follow this rule, just like this one:

If you want to learn more about dataLayer.push, read this guide.

Like this Google Tag Manager Data Layer tutorial so far? Consider subscribing! Just enter your email address in the form below and you’ll more of awesome GTM content.

#3. Reading data from THE DATA LAYER

Imagine, there are several authors in this blog:

  • Me
  • John Doe
  • Jack Torrance
  • etc.

I want to find out which authors write the most engaging content and then segment sessions in Google Analytics. I am using a DurecellTomi WordPress plugin which stores post author name in the Data Layer. If you don’t have WP, ask a developer to add additional data points to the Data Layer.  The snippet looks like this:

It’s very important that Data Layer snippet is placed above Google Tag Manager’s container code in your website’s code if you want to access that information with the Page View event.


#3.1. Data Layer Variable

By default, Google Tag Manager does not recognize custom data in the Data Layer thus you cannot use it as variables. Unless you use the Data Layer Variable. In order to create it variable, you’ll need to specify the Data Layer key of which value you want to retrieve. When the Variable is resolved, it will return whatever was most recently pushed into the key. Easy as that!

Turn data layer variable into GTM variable

If I wanted to fetch pagePostAuthor value, I’d just need to set the pagePostAuthor key in variable’s settings.

Say, you want to send a Google Analytics event when someone leaves a comment. With every event, you also want to push the full name of article’s author. This way you’ll see which authors drive the highest reader engagement.

In this example, I will not go into details how to create a tag, as I will only demonstrate how to pull the data from the Data Layer and turn it into a variable (within Google Tag Manager).

In GTM account, you should go to Variables and create a new one with the following settings (dlv stands for data layer variable):

post author data layer variable

That’s it! Save this variable, refresh Preview and Debug (P&D) mode, and refresh the website you’re working on. You should then see your newly created variable in the Variables tab of Preview & Debug console.

Data Layer Variable in Preview and Debug console



Another setting available in the Data Layer Variable is Version. When you select the Version, you’re instructing GTM to treat the values in the data model in two different ways.


#3.2.1. VERSION 1

It’s pretty limited and does not allow you to access nested values. If you create a DL variable and tried to access pagePostAuthor (in the example below), you’d fail because it’s not in the root of the object (instead, it’s a direct child of attributes key).

So if you wanted to fetch Post Author’s name, the object in the Data Layer should look like this:

See? There’s no attributes key and pagePostAuthor is at the root level.

That’s not the only limitation of Version 1. There’s also no merging available. Every time you push the data to the Data Layer, it will overwrite the entire object. Let me illustrate. Imagine that we have two Data Layer Pushes with different data. The first push contains only pagePostAuthor, the other one includes two more keys, pageCategory and pagePostType.

As a final result, you’d have only two values in the Data Layer: pageCategory and pagePostType because it has completely overwritten the data of the 1st push.

So what’s the point of the 1st Version? It sounds like a useless thing, you might say. That’s not entirely true. I’ve noticed that sometimes (e.g. in Enhanced E-commerce) it’s really important to have a “clean” Data Layer without previous values, meaning that every time a window.dataLayer.push occurs, it completely wipes out the old data and stores the new one.


#3.2.2. VERSION 2

The 2nd version is much more flexible. It allows you to access nested values, arrays, merge data.

Let’s go back to the previous example with two subsequent Data Layer Pushes. The first push contains only pagePostAuthor, the other one includes two more keys, pageCategory and pagePostType.

Contrary to Version 1, in Version 2 all three values would remain in the Data Layer because they were not conflicting.

If the 2nd Data Layer push also had pagePostAuthor key, as a result, the final data in the Data Layer would have looked like this:

This happened because pagePostAuthor from the 2nd push overwrote the pagePostAuthor from the 1st one. Simo Ahava has posted a detailed guide about Data Layer Versions. If you still have some questions, go check it out.



The last setting in the Data Layer Variable is Default Value. If you’re trying to access the value of a particular key in the Data Layer AND that key does not exist, “undefined” will be returned. Sometimes you might need to get a different default value, e.g. (not set), empty, or anything else.  In that case, click the checkbox and set the default value.

Data Layer Variable Default Value


#3.3. But what about other data structures?

Keep in mind that data can be stored in the Data Layer using different structures. Here’s an example where the key pagePostAuthor is in the root level:

Or this one (pagePostAuthor key is now a descendant of the attributes key):

Or even like this (there are two arrays that are the descendants of the transactionProducts key):

In the last two examples, entering key’s name (pagePostAuthor) is not enough, you couldn’t be able to get its value. There’s something else you need to know.



Let’s try to put this as non-technical as possible: when keys are descendants of other keys, they are called child keys (to be honest, I’ve found various terms on this one, but child key sounds the most comprehensible for non-developers). In the example below, you can see that attributes are in the first level and pagePostAuthor is in the 2nd.

In order to pull its value, you should slightly change one setting in a variable (within Google Tag Manager). Instead of pagePostAuthor, you should enter attributes.pagePostAuthor as the Data Layer Variable Name.


What if pagePostAuthor also had a child key? What would you do?

Inception we need to go deeper

That’s right. You should define the full path to that particular key: attributes.pagePostAuthor.someOtherKey, and so on… and so on… Every level should be separated by a dot.

Accessing child keys in Data Layer is pretty common. When someone asks me to give an example, I always tell them about the AJAX listener which helps to track AJAX form submissions.

In my blog post, Google Tag Manager AJAX form tracking, I’ve explained how to use the AJAX listener (by Lunametrics) which listens to all AJAX requests and pushes valuable information to the Data Layer. Here’s an example:

ajaxComplete - full response

There are a lot of nested keys. In order to pull data from Data Layer, you’ll need to use dot notation in Data Layer variable’s settings, e.g. attributes.response.

dlv - attributes.response



I was working with a developer on the implementation of Google Analytics E-commerce tracking (standard, not enhanced). Following Google’s guidelines, I asked a developer to push successful order’s data to the Data Layer. Then, I could fetch that event via Transaction tag within Google Tag Manager.

It’s very important that the developer follows guidelines and pushes data using the structure as instructed by Google. Here’s the official example from their knowledge base:

“You know what?”, I asked myself, “This is very useful information”. I’d also want to push this order data to other marketing tools I’m using at Omnisend (e.g. Facebook Pixel). I was mostly interested in pricename, and quantity.

I tried my best and, unfortunately, failed. I used transactionProducts.price, transactionProducts.name, etc., but my newly created Data Layer variables always returned undefined. So what’s wrong?

Failed - undefined data layer variable

Notice anything suspicious? In my Standard Ecommerce example (taken from Google Knowledge Base), transactionProducts has 2 name keys, 2 price keys, etc. So how the heck can Google Tag Manager know which value I am interested in? The first or the second one? And what would happen if a user purchased 5 products?

What we are dealing here with is called arraystransactionProducts has an array containing two products with the same collections of keys: sku, name, category, price, quantity.

In Javascript, if you want to pull the value of first product’s price, you’d need to use transactionProducts[0].price (the index starts from 0), but Google Tag Manager does not support square brackets in this context, so you’d need to use dot notation, like this: transactionProducts.0.price.

access array members in data layer

In Google Tag Manager, your Data Layer variable should look like this:


If there were 5 products in the array and you wanted to access the price of the 5th product, Data Layer Variable name should be transactionProducts.4.price. Remember, the index here starts from zero, so the first product is actually not the 1st, but 0th.

Tired? If yes, then feel free to bookmark this Google Tag Manager Data Layer tutorial an come back later.

Google Tag Manager Course - Learn More

#4. Send data from the data layer to other tools

A quick checkpoint in our Google Tag Manager Data Layer Tutorial. Let’s see what we have achieved so far:

  • Custom data was stored in the Data Layer (thanks to your coding skills, your developer’s coding skills, or some 3rd party plugin).
  • Google Tag Manager started recognizing that custom data (thanks to the Data Layer variable).
  • Now, we need to send this data to other tools, like Google Analytics.



After Data Layer variable is created, check if Google Tag Manager catches it properly.

  • In your GTM panel, enter Preview and Debug mode (by clicking Preview button)
    GTM Preview button
  • When Debug mode is enabled, you should see an orange notification bar:
    Preview and Debug mode
  • Go to the website you are currently working on and refresh it.
  • A GTM debug console should appear at the bottom of the screen.
    Post author in Preview and Debug mode
  • Click Variables and look for pagePostAuthor, check its value. If pagePostAuthoer is undefined, double-check whether you have entered a correct Data Layer Variable name in GTM’s admin panel (keep in mind, it’s case-sensitive). In my case, pagePostAuthor variable is defined correctly, because I got the value Julius Fedorovicius.



pagePostAuthor is a custom parameter that was defined by you (or your developer) so Google Analytics will not catch it by default. You need to create a custom dimension called pagePostAuthor (actually, you can call it whatever you want) in order to let Google Analytics know about this new parameter.

  • Login to your Google Analytics account.
  • Open your website’s account, click Admin. You should see something like this:
    Google Analytics Admin
  • Scroll down and in Property section click Custom definitions > Customer dimensions
    analytics custom dimensions
  • Click Create custom dimension
  • Enter name pagePostAuthor (or anything else), choose User as a scope and click Create. User scope will apply this custom dimension to all further events of this particular user.
    Create dimension in Google Analytics
  • When a custom dimension is created, you’ll see a short code snippet.
    google analytics custom dimension code
    Take a closer look at the second line of code, there’s a dimension3. Number 3 is the index of pagePostAuthor custom dimension. Keep this in mind.



  • Go back to your Google Tag Manager account.
  • Open Universal Analytics Pageview tag. If you don’t have one, create it.
  • Go to Tags and click New:
    create new tag
  • Enter the name for the tag – GA pageview (actually, you can name it whatever you want)
  • Click Tag Configuration box.
    tag configuration bo
    Choose a tag type – Universal Analytics
    tag type universal analytics
  • Now it’s time to configure a tag. Enter Google Tracking ID (UA-xxxxxxx). In fact, it would be better if you used a variable with Google Analytics Settings, instead.
  • Track type – Pageview
  • Click More settings > Custom dimensions
  • Enter 3 in Index field (that’s the index that you got in step 3)
  • Enter {{dlv – pagePostAuthor}} Data Layer variable in the Dimension value field. In GTM, variables are surrounded by double curly brackets {{}}.
    Custom dimensions in Google Tag Manager
  • In the Triggering section choose All pages.
  • This way with every page view you’ll also send the value of a pagePostAuthor variable as custom dimension No. 3.

That’s how you can transfer additional data from Google Tag Manager Data Layer to Google Analytics. But don’t limit yourself just to custom dimensions. You can use Data Layer variables in Google Analytics Event tags, Facebook Pixel, etc.

To see how you can use custom dimensions in action, read this guide on Moz blog.



Data Layer can also be used for more advanced tag-firing rules. For example, you can fire a Google Ads remarketing tag only when a user is on a Free plan. Let’s take a closer look at this example.

  • Open GTM admin panel.
  • Go to Tags and click New.
    create new tag
  • Enter a name, i.e. Google Ads remarketing tag
  • Choose Tag Type – Google Ads Remarketing
  • Enter Conversion ID and Conversion Label
  • Leave all other settings as default and click Continue
  • In Triggering section, Click Plus icon create tag in triggers listin the top right corner and enter the name – I suggest “Pageview – Users with free plan”. Choose Pageview as a trigger type.
  • You don’t want this tag to fire on every page. In This Trigger Fires on section, click Some Page Views and enter the following rule: dlv – pricingPlan equals Free. This means that Google Ads remarketing tag will fire only when pricingPlan Data Layer variable is exactly Free. Premium users will not trigger the rule.
    trigger configuration



Another common example of Data-layer-based triggers is to use events. In addition to custom data, you can also push events to the Data Layer by using window.dataLayer.push.

Parameter event indicates that this is a Data Layer event. All events can be seen in Preview and Debug mode’s stream.

new subscriber event

Now let’s set this event as a trigger for Google Analytics Event Tag.

  • Go to Triggers and click New
  • Enter name. I suggest calling it Custom – new email subscriber
  • Choose type – Custom event (all Data Layer events are treated as custom events in GTM).
  • Fire on – new_subscriber. You need to enter the exact title of the event that you see in Preview and Debug console.

Custom Trigger

Let’s get back to our window.dataLayer.push event example. Here’s the code:

Wouldn’t it be nice if we also passed the formLocation data to Google Analytics? GTM will not catch this parameter by default, so we need to create another variable. Go to Variables > User-defined variables and click New.

  • I recommend naming it dlv – formPosition.
  • Choose type – Data Layer Variable. Variable Name – formPosition (that’s exactly how the parameter is called in the previous code example. Leave all other settings as is and click Create Variable.
    Form position - data layer variable

Finally, let’s create a Google Analytics Event tag when a new subscriber submits his/her email address.

  • Go to Tags and click New
  • Choose the product – Google Analytics
  • Choose Tag Type – Universal or Classic Analytics (depending on your currently installed version of GA).
  • Set Tracking ID parameter or choose Google Analytics Settings Variable.
  • Track type – Event
  • Category – Form Submission (this means that all events (related to this trigger) will have the same Category
  • Action – New subscriber
  • Label – {{dlv – formPosition}}. That’s the variable that we have just created. The value of this parameter will change depending on the position of your form. If you have 3 different forms on the same page, and they all fire the same new_subscriber Data Layer event but with different formPosition value, and Google Tag Manager will pass the correct value as GA event’s label. This is extremely useful if you want to understand which forms are performing better.
  • Click Continue
  • Fire On – Click More and choose Data-layer-based trigger you’ve created before Custom – new email subscriber.
  • Done, you’re good to go!

GA Event Tag - New Email Subscriber

The following (and final) steps are:

  • Check all new tags in GTM Preview and Debug console (whether they fire correctly)
  • Check Real-time reports in Google Analytics account (whether new_subscriber events is working properly)
  • Install Google Tag Assistant (in Chrome Browser) to make sure whether remarketing tag fires correctly (here’s a tutorial how to use it)

Update: by the way, you can learn more about Custom Event Trigger in this blog post.


Google Tag Manager Data Layer Tutorial: Conclusion

If you read the entire Google Tag Manager Data Layer tutorial, well done (and thank you)! If you skipped to the summary without reading the entire thing, I suggest bookmarking this page so you can come back later.

In this Google Tag Manager Data Layer tutorial, I’ve explained the key concepts of what the Data Layer is, why should bother learning more about it, why is it important, etc. If you haven’t read this guide and just scrolled down to the conclusion, then spoiler alert, it’s SUPER IMPORTANT.

In a nutshell, here’s what the Data Layer is and how does it work:

  • Data Layer is a central place (virtual layer) of a website where you, your developers, various tools can store data (about user, his behavior, etc.). From there, Google Tag Manager reads that information and sends further to other tools, Google Analytics, Google Ads, Facebook, etc.
  • Data Layer is not some magical place on a server where you keep the data. It’s a temporary data storage which is created after GTM has loaded and is completely wiped out whenever the page refreshes or is closed.
  • When Google Tag Manager code is loaded on the page, the Data Layer is created automatically.
  • If you want to have some custom data in the Data Layer, you have to use window.dataLayer.push method to push the data. If you don’t know how to code, ask developers to do that or look for 3rd party plugins/tools which can do that.
  • By default, Google Tag Manager does not recognize custom data store in the DL, therefore you need to create Data Layer variables in GTM. In the case of Data Layer events, you also have to create Custom Event Triggers.
  • Finally, feel free to insert Data Layer variables in tags (within GTM), e.g. Google Analytics event tag, Custom HTML tag, etc. Variables must be surrounded by double curly brackets {{ }}.

Is there anything I missed in this Google Tag Manager Data Layer tutorial? Let me know in the comments section below.

Julius Fedorovicius

Head of Developer Operations at Omnisend. I am highly interested in Google Tag Manager, Google Analytics, Adwords, Email marketing, Email Deliverability, Digital Marketing in general. You can follow me on Twitter or Linkedin.