Updated: July 10th, 2021
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 that 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:
+ Show table of contents +
What is the Data Layer?
Storing data in the Data Layer (dataLayer.push)
Reading data from the Data Layer
Data Layer Variable
Data Layer Versions
What about other data structures?
Pull data from child keys
Arrays
Sending data from Data Layer to other tools
Using Data Layer data as triggers
Using Data Layer events as triggers
Google Tag Manager Data Layer Tutorial: Final words
Video tutorial
If you prefer video content, here is a tutorial from my Youtube channel.
Two additional options where to learn Data Layer
Since the importance of this topic in Google Tag Manager is uncanny, I explain it in two of my premium GTM courses:
Google Tag Manager Masterclass for Beginners
Intermediate Google Tag Manager course
In the beginners’ course, we take a solid overview of what Data Layer is in general, why is it important, how to work with it.
In the Intermediate course, we take a lot deeper dive into topics that are not even explained in this blog post. Understanding the full potential (and technicalities) of the Data Layer is key to successful tracking implementations.
#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.
Once you place the Google Tag Manager 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 of how data can be pushed to the Data Layer. Actually, there is the only one you should use, but for the sake of knowledge I’ll mention both:
By adding a Data Layer snippet above the GTM container snippet (this method is called Data Layer Declaration).
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 the Google Tag Manager tracking container with parameters like product ID, product title, etc. Here’s an example:
<script>
dataLayer = [{
‘productID’: ‘123456’,
‘productTitle’: ‘Very awesome product’,
‘productPrice’: ‘13.00’
}];
</script>
<!– Google Tag Manager –>
…
<!– End Google Tag Manager –>
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:
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:
window.dataLayer.push({‘event’: ‘new_subscriber’});
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)).
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘formLocation’: ‘footer’,
‘event’: ‘new_subscriber’
});
When a visitor adds a product to his/her cart, a Data Layer event (containing the 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 Google Tag Manager snippet and dataLayer.push whenever an important event occurred.
But later I noticed multiple GTM experts suggesting that this is not the best practice. Instead, you should ALWAYS:
Use dataLayer.push (forget dataLayer = [{}];)
And upgrade it by adding window.
All examples in this blog post follow this rule, just like this one:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘event’: new_subscriber
});
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 that stores the 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:
<head>
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push [{
pagePostAuthor: ‘Julius Fedorovicius’
}];
</script>
<!– Google Tag Manager –>
…
<!– End Google Tag Manager –>
</head>
It’s very important that the 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 a 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!
Note: some screenshots in this article are still showing the older version of the GTM preview mode but that is just to show the general idea. It should not stop you from properly understanding this blog post.
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 the article’s author. This way you’ll see which authors drive the highest reader engagement.
In this example, I will not go into details on 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):
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.
#3.2. Data Layer Version
Another setting available in the Data Layer Variable is Version. When you select the Version, you’re instructing Google Tag Manager 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).
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
“attributes”: {
‘pagePostAuthor’: ‘Julius Fedorovicius’
}
});
</script>
So if you wanted to fetch Post Author’s name, the object in the Data Layer should look like this:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pagePostAuthor’: ‘Julius Fedorovicius’
});
</script>
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.
<script>
//The 1st Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pagePostAuthor’: ‘Julius Fedorovicius’
});
//The 2nd Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pageCategory’: ‘google-tag-manager-tips’,
‘pagePostType’: ‘post’
});
</script>
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.
<script>
//The 1st Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pagePostAuthor’: ‘Julius Fedorovicius’
});
//The 2nd Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pageCategory’: ‘google-tag-manager-tips’,
‘pagePostType’: ‘post’
});
</script>
Contrary to Version 1, in Version 2 all three values would remain in the Data Layer because they were not conflicting.
{
‘pagePostAuthor’: ‘Julius Fedorovicius’,
‘pageCategory’: ‘google-tag-manager-tips’,
‘pagePostType’: ‘post’
}
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:
{
‘pagePostAuthor’: ‘John Doe’,
‘pageCategory’: ‘google-tag-manager-tips’,
‘pagePostType’: ‘post’
}
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.
#3.2.3. Default Value
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.
#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:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘pagePostAuthor’: ‘Julius Fedorovicius’
});
</script>
Or this one (pagePostAuthor key is now a descendant of the attributes key):
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘attributes’: {
‘pagePostAuthor’: ‘Julius Fedorovicius’
}
});
</script>
Or even like this (there are two arrays that are the descendants of the transactionProducts key):
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
‘transactionProducts’: [{
‘sku’: ‘DD44’,
‘name’: ‘T-Shirt’,
‘category’: ‘Apparel’,
‘price’: 11.99,
‘quantity’: 1
},{
‘sku’: ‘AA1243544’,
‘name’: ‘Socks’,
‘category’: ‘Apparel’,
‘price’: 9.99,
‘quantity’: 2
}]
});
</script>
In the last two examples, entering the key’s name (pagePostAuthor) is not enough, you couldn’t be able to get its value. There’s something else you need to know.
#3.4. Pull Data from Child Keys
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 at the first level and pagePostAuthor is on the 2nd.
{
attributes: {
pagePostAuthor: ‘Julius Fedorovicius’
}
}
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?
{
attributes: {
pagePostAuthor: {
autorName: ‘Julius Fedorovicius’,
authorTag: ‘Google Tag Manager’
}
}
}
That’s right. You should define the full path to that particular key: attributes.pagePostAuthor.authorName, 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 which listens to all AJAX requests and pushes valuable information to the Data Layer. Here’s an example:
There are a lot of nested keys. In order to pull data from Data Layer, you’ll need to use dot notation in the Data Layer variable’s settings, e.g. attributes.response.
#3.5. Pull Data from Array Members
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:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
‘transactionId’: ‘1234’,
‘transactionAffiliation’: ‘Acme Clothing’,
‘transactionTotal’: 38.26,
‘transactionTax’: 1.29,
‘transactionShipping’: 5,
‘transactionProducts’: [{
‘sku’: ‘DD44’,
‘name’: ‘T-Shirt’,
‘category’: ‘Apparel’,
‘price’: 11.99,
‘quantity’: 1
},{
‘sku’: ‘AA1243544’,
‘name’: ‘Socks’,
‘category’: ‘Apparel’,
‘price’: 9.99,
‘quantity’: 2
}]
});
</script>
“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 price, name, 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?
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 arrays. transactionProducts 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 the 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.
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, the 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.
#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.
#4.1. Enable Preview and Debug Mode in Google Tag Manager
Let’s check if Google Tag Manager catches pricingPlan variable.
In your GTM panel, enter Preview and Debug mode (by clicking Preview button)
When Debug mode is enabled, a new tab should be loaded where you will have to enter the URL of your website
Click start and you will be redirected to that page.
Click Variables in the Preview mode’s tab and look for pricingPlan. Check its value. If pricingPlan is undefined, you should double-check whether you have entered a correct Data Layer Variable name in GTM’s admin panel (by the way, it’s case-sensitive). In my case, pricingPlan variable is defined correctly, because I get the value Free.
#4.2. Create a Custom Dimension in Google Analytics
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:
Scroll down and in Property section click Custom definitions > Customer dimensions
Click Create a custom dimension
Enter name pagePostAuthor (or anything else), choose User as a scope, and click Create. The user scope will apply this custom dimension to all further events of this particular user.
When a custom dimension is created, you’ll see a short code snippet.
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.
#4.3. Push pagePostAuthor Data Layer Variable to Google Analytics
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.
Enter the name for the tag – GA pageview (actually, you can name it whatever you want)
Click the Tag Configuration box.
Choose a 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 Google Tag Manager, variables are surrounded by double curly brackets {{}}.
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.
#5. Using Data Layer Data as Triggers
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 the Google Tag Manager admin panel.
Go to Tags and click New.
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 the Triggering section, Click Plus icon in the top right corner and enter the name – I suggest “Pageview – Users with the 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.
#6. Using Data Layer Events as Triggers
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.
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘formLocation’: ‘footer’,
‘event’: ‘new_subscriber’
});
Parameter event indicates that this is a Data Layer event. All events can be seen in Preview and Debug mode’s stream.
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.
Let’s get back to our window.dataLayer.push event example. Here’s the code:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
‘formLocation’: ‘footer’,
‘event’: new_subscriber
});
Wouldn’t it be nice if we also passed the formLocation data to Google Analytics? Google Tag Manager 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.
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 a Data-layer-based trigger you’ve created before Custom – new email subscriber.
Done, you’re good to go!
The following (and final) steps are:
Check all new tags in Google Tag Manager Preview and Debug console (whether they fire correctly)
Check Real-time reports in the Google Analytics account (whether new_subscriber events is working properly). If realtime reports are not working, read this troubleshooting guide.
Install Google Tag Assistant (in Chrome Browser) to make sure whether remarketing tag fires correctly (here’s a tutorial on 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: 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 you 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 it 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 that is created after GTM has loaded and is completely wiped out whenever the page refreshes or is closed.
When the 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 Google Tag Manager), 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.
The post Complete Google Tag Manager Data Layer Tutorial appeared first on Analytics Mania.
Read MoreAnalytics Mania