
January 23, 2023
3 Ways to Pull Data from Data Layer with Google Tag Manager
Updated: January 23rd, 2023.
The Data Layer is the foundation on which Google Tag Manager heavily relies. It ensures maximum flexibility, portability, and ease of implementation.
In my other blog post, I have explained how it works and how you can get the most out of it. However, not all aspects were covered there. Since data can be saved using different structures, it should be accessed differently, as well. In today’s blog post, I’ll explain three ways how you should pull data from the data layer.
Although all three methods include Data Layer Variable that can be created in the Google Tag Manager container, their settings will differ slightly.
If you have read my guide about GTM Preview and Debug mode, you already know that the Data Layer tab is the most undervalued and totally untapped part of the GTM debug console, which is forgotten by beginners and (especially) intermediate users.
This tab shows the same message object as it was pushed to the data layer for the selected event and what the data layer looks like after the message transaction is complete.
In other words, you can see all data that is currently available in the data layer and what values were available after every Google Tag Manager event. And the best part: every data point (pushed to the data layer) can be turned into a variable in Google Tag Manager.
Table of Contents
– Hide table of contents –
- Before we continue
- #1. Accessing first-level keys (a.k.a. primitive values)
- #2. Pull the data from child keys (a.k.a. nested fields)
- #3. Pull the data from array members
- Final words
Before we continue: this topic is also thoroughly explained in the Intermediate GTM Course
In this blog post, you’ll take a glimpse at 3 data types in JavaScript: strings, objects, and arrays. However, if you want to dive deeper and properly understand how they work in GTM, enroll in my Intermediate Google Tag Manager course.

#1. Accessing first-level keys (a.k.a. primitive values)
You’re probably asking why did I call them “first-level keys”? I’ll explain that at the end of this chapter.
For my WordPress blog, I’m using GTM4WP plugin, which pushes some keys and values with each page load:
- Key: pagePostType, value: post
- Key: pagePostType2, value: single-post
- Key: pageCategory, value: google-tag-manager-tips
- Key: pagePostAuthor, value: Julius Fedorovicius
See the screenshot below.
With the help of Google Tag Manager, I can easily turn each of them into data layer variables and reuse them in other tags.
Say you want to send a Google Analytics event when someone leaves a comment. With every event, you also want to push the article author’s full name. 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 data from the data layer and turn it into a variable (within Google Tag Manager).
In the Google Tag Manager 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 P&D console.
Oh, I almost forgot. You’re probably still thinking, why did I call it “First-level key”? Well, that’s because all those four keys have no parent keys. Let me illustrate. Here’s an example where the key is on the first level.
{ pagePostAuthor: 'Julius Fedorovicius' }
And here’s 2nd level key because pagePostAuthor is a descendant of attributes key:
{ attributes: { pagePostAuthor: 'Julius Fedorovicius' } }
In the next chapter, I’ll explain how you can pull data from the data layer if the key is not on the first level.
#2. Pull the data from child keys (a.k.a. nested fields)
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' } }
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 Data Layer Variable Name.
What if pagePostAuthor also had a child key? What would you do?
{ attributes: { pagePostAuthor: 'Julius Fedorovicius': { someOtherKey: 'example' } } }
The answer is:
That’s right. You should define the full path to that particular key: attributes.pagePostAuthor.someOtherKey, and so on… and so on… A dot should separate every level.
Accessing child keys in the data layer is pretty standard. 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 AJAX listener (by Bounteous). It listens to all AJAX requests and pushes their data to the data layer. Here’s an example:
There are a lot of nested keys. To pull data from the data layer, you’ll need to use dot notation in the data layer variable’s settings, e.g., attributes.response.
#3. Pull the data from array members
I was working with a developer on implementing Google Analytics Ecommerce tracking . Following Google’s guidelines, I asked a developer to push successful order data to the data layer. Then, I could fetch that event (and its data) with a GA4 event tag within Google Tag Manager.
It’s essential that the developer follows guidelines and pushes data using the structure as instructed by Google. Here’s the official example from their knowledge base:
window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'purchase', ecommerce: { transaction_id: 'T_12345', affiliation: 'Google Merchandise Store', value: 25.42, tax: 4.90, shipping: 5.99, currency: 'USD', coupon: 'SUMMER_SALE', items: [ { item_id: 'SKU_12345', item_name: 'Stan and Friends Tee', item_category: 'Apparel', price: 9.99, quantity: 1 }, { item_id: 'SKU_12346', item_name: 'Google Grey Women's Tee', item_category: 'Apparel', price: 20.99, quantity: 1 }] } });
“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 (e.g., Facebook Pixel). I was mostly interested in price, name, and quantity.
So I tried Method #2 (from this blog post) and failed. I used ecommerce.price, ecommerce.item_name, etc., but my newly created data layer variables always returned undefined. So what’s wrong?
Notice anything suspicious? In my GA4 Ecommerce example (taken from Google’s Knowledge Base), there are 2 item_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. The ecommerce.items has an array containing two products with the same collections of keys: item_id, item_name, item_category, price, quantity.
In Javascript, if you want to pull the value of the first product’s price, you’d need to use ecommerce.items[0].price (the index starts from 0), but Google Tag Manager’s data layer variable does not support square brackets in this context, so you’d need to use dot notation, like this: ecommerce.items.0.price.
In Google Tag Manager, your data layer variable should look like this:
If there were five products in the array and you wanted to access the price of the 5th product, the Data Layer Variable name should be ecommerce.items.4.price. Remember, the index here starts from zero, so the first product is actually not the 1st, but the 0th.
Final words on pulling data from the Data Layer
Since data can be saved using different structures, it should be accessed differently, as well.
Now, you know how to pull data from the data layer in 3 different ways. Although they all use the same Data Layer Variable, their names are different, which depend on the data structure – arrays, nested keys, or single (first-level) keys.
29 COMMENTS
Hello.
Thank you por your post. Nice information.
I have a doubt: can I create a dataLayer inside the Google Tag Manager? for example place the code of the dataLayer inside a custom HTML tag.
Is any way to do that?
In other words create the datalayer without touching the code.
Thank you
When GTM loads, it automatically creates a data layer. If you want to push some data into it, ]you can use window.dataLayer.push method to do that (with Custom HTML tag). I've described how Data Layer works in detail here https://www.analyticsmania.com/post/ultimate-google-tag-manager-data-layer-tutorial/.
You'll also find how to push data to the data layer.
Hi, i have one question: i push event from GTM custom html tag. Is there a way to make the GTM dataLayer variable that is picking value from this event get the updated value? Right now the custom event is fired from this tag on form submit, there is no page reload and it's after window loaded, so the datalayer variable will be undefined. Is there any way to solve this using dataLayer variable? Or the easiest is just to use JS variable?
Data Layer Variable will start returning some value only when that information is pushed to the Data Layer.
>Right now the custom event is fired from this tag on form submit, there is no page reload and it's after window loaded, so the datalayer variable will be undefined.
If you push an "event" key and some custom parameters to the Data Layer, those custom parameters can be retrieved with the Data Layer variables. Just include the "event" key in the dataLayer.push
Hi Julius,
Thanks for writing this blog. It's super useful for non-technical people like myself. I have a question.
How do I pull out "option in actionField" variable from
dataLayer.push({
'event': 'checkout',
'ecommerce': {
'checkout': {
'actionField': {'step': 1, 'option': 'Visa'},
'products': [{
'name': 'Triblend Android T-Shirt',
'id': '12345',
'price': '15.25',
'brand': 'Google',
'category': 'Apparel',
'variant': 'Gray',
'quantity': 1
Is that "ecommerce.checkout.actionField.option" or "ecommerce.checkout.actionField.0.option"?
Hey, it's ecommerce.checkout.actionField.option because actionField is an object, not an array. Arrays are surrounded by brackets [], objects are surrounded by curly brackets {}.
The best way to find out for you in the future is to check it in the Preview and Debug mode. Create a Data Layer Variable, refresh preview mode and go to the website where that dataLayer.push occurs. If variable's value is undefined, something's wrong. If you see the correct value, then you did everything correctly.
Hey Julius, nice article! Really difficult to find useful articles.
But there is one question:
The used "dataLayer.push({ 'transactionId'..." isn´t the right one for enhanced ecommerce tracking, or? ususal my DataLayer looks different and ist not only based on the basic transaction. In one project i have seen a tansaction tag, which is running because of the datalayer u are using too. But at the Checkout Behaviour Analysis i see the steps which i have defined via gtm, but at the last point no transaction. I hope u know what i mean ;)
Hey, that snippet is supported only in the Standard Ecommerce. Enhance Ecommerce require totally different implementation and codes pushed to the data layer. You need to push "purchase" event. Here's a guide I always recommend to read https://canonicalized.com/enhanced-ecommerce-tag-manager/.
Good article, and really a bridge to go from simple data layer usage ecomm for me ... However, what would be the best and easiest way to fill the datalayer with all this data ? I don't think that duraceltomi's plugin goes this far ...
Hey, you'll need to cooperate with a developer to have that custom data in the Data Layer.
Thanks ... actually, I found out that gtm4wp does populate the data layer with the complete e-commerce data ... it's a beta feature, but it works great ...
Exactly what I needed, thanks!
Julius this is brilliant! Suppose I don't want to push the data into GA, but into a Google Sheet spreadsheet. What setup would I use to push that from GTM to that spreadsheet? Any thoughts or articles?
It would much more reliable if you just asked developers to push the data from your server to zapier that is connected to google sheets (and avoid GTN here). Or maybe utilize google appscript. Unfortunately, I'm not that experienced here so I cannot give you a more precise advice.
Thank you very much Julius for your useful blogposts. I follow and advice your content.
Hi,
I ticked the "Use Data Layer" as you and many other sites recommend and It doesn't work as I expected. I expected that all these data like a product is, name, category etc. will be added to GA reports automatically. But I cannot find these data. What should I do?
Thanks for your help.
If someone clicks a product, and you have the product click information PROPERLY formatted in the Data Layer, then all data points of that single dataLayer.push will eventually appear in GA (not in real-time, but at within 24 hours. Usually, less).
If you don't see any information in GA after 24 hours, most likely your dataLayer.push is not following the strict requirements of Google Analytics EE.
Amazing work! Big fan of your explanations. Helped me integrate GTM throughout!
Hi If there are more arrays like 5 products or 10, we have to create each variable for 5 or 10 products. Example. We have to create 10 variables like this:- ecommerce.items.0.name, 1.name, ......, ecommerce.itmes.9.name for the 10 products. Similarly for ids and price we also have to do the same. is that correct? Is there any easy and quick method to overcome this?
This is not recommended. To handle multiple products you would need to learn JavaScript and how to work with arrays/objects
Hi,
I'm having an issue. My data variables are displaying correctly in debug mode, but when i try to print them in console, or try to send them to a mixpanel variable, they show as undefined.
, e.g.:
<script>
console.log({{Name}});
</script>
I am unable to understand why. Can you please help? I have been trying to figure out since 2 daays
GTM {{variables}} are understood only by GTM. They are not available outside of it (e.g. in the console). What's you are trying to achieve would never work.
Hey thanks for your article. It really help me!
Can i ask u something?
If i have an array, and i wanna get sum of prices, or format all id of product like contents_id: 3, 9, 15, 21 for example... How can i get those variables?
You wound need to learn Javascript fundamentals and work with objects/arrays.
@Henrique Reis
Just put the whole object into a datalayer variable (DLV Product Object). Then create another variable (custom js this time).
And use something like this:
function() {
var transactionProducts = {{DLV Product Object}}
var products = [];
var i;
if(!transactionProducts) {return;}
for(i=0; i<transactionProducts.length; i++) {
products.push(transactionProducts[i].name);
products.push(transactionProducts[i].price);
}
return products;
}
This will return the name and the price.
Hi there, I am struggling to pull the following from the data layer attributes.videoName
Here is the data layer:
{
event: "optimize.domChange",
gtm: {
uniqueEventId: 5012,
start: 1665604259828,
element: "HTMLDivElement: div.pp_overlay",
elementClasses: "pp_overlay",
elementId: "",
elementTarget: "",
triggers: "34934571_53",
elementUrl: "",
visibleRatio: 100,
visibleTime: 0,
visibleFirstTime: 6689,
visibleLastTime: 6689
},
pageId: "22",
pageType: "page",
pageCategory: [
"articles",
"case-studies",
"communities-cat",
"creative-tech",
"data-and-ai",
"data-challenges",
"help-me-sell",
"tell-me-more",
"videos"
],
pageTags: [],
userId: "00uztxft4ptZmRiVI416",
wpId: "142605",
userRole: ["subscriber"],
attributes: {videoAction: "10", videoName: "WPP Open Introduction"}
}
Weird, attributes.videoName should work. Maybe something else is causing the problem but it's difficult to tell without auditing the setup.