October 23, 2025
Data Layer Variable in GTM: What, Why, and Where?
Updated: October 23rd, 2025
To work with Google Tag Manager, you need to know three key concepts: tags, triggers, and variables. But, as you dive deeper, you will come across the fourth one, the Data Layer.
Google Tag Manager and Data Layer are frequently found in the same sentence. These concepts work hand in hand to make tag management significantly more straightforward. A clear understanding of both concepts ensures maximum flexibility and ease of implementation.
Without it, there would be no variables and no triggers. Therefore, Google Tag Manager wouldn’t fire any tags.
Table of Contents
Here’s what you will learn in this article
- The context
- What is a Data Layer Variable?
- Let’s create a Data Layer Variable
- Data Layer version
- Default value
- Different data structures
- Why is my Data Layer Variable undefined?
- Best practices for using Data Layer variables
- Is it worth learning Data Layer?
- Further reading
- Final words
The context
Before we dive in, let’s recall how the Data Layer (DL) works. DL is a virtual layer of a website where useful information is stored, e.g., user ID, Text of a Clicked Button, Order Total, etc.
Other marketing tools like Google Analytics, Mixpanel, and Google Ads, to name a few, can also use this data.
Google Tag Manager already supports a bunch of default built-in variables. You can find the complete list by going to Variables > Configure.

After you enable these variables, they’ll appear in the Variables tab of Google Tag Manager’s Preview and Debug mode.

Once enabled, you can use these data points in trigger conditions, tags, and other variables (e.g., Lookup or Regex Tables). And that’s awesome!
But what if we want to have some custom variables? For example, blog post author’s name, user’s registration country, etc.?
That’s where the Data Layer Variables come in handy.
What is a Data Layer Variable?
Data Layer Variable enables you to fetch a value from the Data Layer and turn it into a variable (which can be used in Tags, Triggers, and even other variables). But first, let’s look at how the Data Layer stores this data.
Enable the GTM Preview and Debug mode and go to the Data Layer tab. In the screenshot below, I am viewing my blog’s data; yours might look different.

Here, I’ve taken the example of a custom event to track which author got the most reads on a website. The event will fire when someone lands on a blog post.
Let’s say that I need to know the author, the page category, and the type of blog they are reading and I want to measure that in Google Analytics.
The blog is running on WordPress, and it’s using the GTM4WP Plugin, which pushes this data to the Data Layer every time the page loads.
If you want to get even more custom information, ask a developer to add it to the Data Layer with the help of dataLayer.push.
Anyway, let’s go back to the example. As you can see in the screenshot above, there’s some interesting data I could employ in my tags and triggers.
Unfortunately, if I navigate to the Variables tab of the Preview and Debug Console, those variables aren’t there. Why?
By default, Google Tag Manager does not recognize custom data in the Data Layer. Even though the data is present in your datalayer, you cannot use it without the Data Layer Variable.
To create this variable, you’ll need to specify the Data Layer key whose value you want to retrieve. When the variable is resolved, it will return the most recently pushed value into the key. Let me show you how.
Let’s create a Data Layer Variable
Let’s have another example. I want to track which author is generating the highest number of views on a website.
Above the Google Tag Manager container snippet, the following dataLayer code is added:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'pagePostAuthor': 'Julius Fedorovicius',
'pageCategory': 'google-tag-manager-tips',
'pagePostType': 'post'
});
In this case, I want to track and use it in GTM:
- Key: pagePostType, value: post
- Key: pageCategory, value: google-tag-manager-tips
- Key: pagePostAuthor, value: Julius Fedorovicius
Here’s what it would look like in the Preview and Debug mode:

With the help of Data Layer variables, I can easily retrieve those values and re-use them in other tags, triggers, or variables.

Say you want to send a Google Analytics event when someone leaves a comment. You also want to push the article author’s full name with every event. 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. I will only demonstrate how to pull the data from the Data Layer and turn it into a variable (within Google Tag Manager).
Go to Variables in your Google Tag Manager account 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 perform the desired action in the new tab. You should then see your newly created variable in the Variables tab of the P&D console.

Understanding when data becomes available
It’s important to understand that a Data Layer Variable can only retrieve a value if that value exists in the Data Layer at the moment the variable is requested by a tag or trigger. GTM processes events sequentially.
- Data pushed before GTM loads: If your developers push data above the GTM container snippet, that data is available very early, often by the “Consent Initialization” or “Initialization” events in GTM’s Preview mode. A DLV used in a tag firing on “Initialization” can access this data.
- Data pushed after GTM loads (e.g., on user action): If data is pushed later via dataLayer.push() when a user performs an action (like clicking a button, triggering a customEvent), that data is only available on or after that specific customEvent appears in the GTM Preview timeline.
- A DLV used in a tag firing on customEvent can access this data.
- A DLV used in a tag firing on an earlier event (like “DOM Ready”) cannot access this data yet – it will return undefined at that point.
Rule of thumb: Always check the “Data Layer” tab in GTM Preview mode for the specific event where your tag is firing or your trigger is being evaluated. Make sure the key you need exists in the data model shown at that point in time.
Data Layer version
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.
Version 1
One of the main problems with Version 1 is that it does not allow you to access nested values.
Look at the dataLayer.push code below. Suppose you create a Data Layer variable and try to access pagePostAuthor. In that case, you’d fail because it’s not in the root of the object (instead, it’s a direct child of the attributes key).
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'attributes': {
'pagePostAuthor': 'Julius Fedorovicius'
}
});
</script>
If you want to fetch the Post Author’s name (while using the Version 1), the object in the Data Layer must look like this:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'pagePostAuthor': 'Julius Fedorovicius'
});
</script>
See? There’s no parent key, and pagePostAuthor is at the root level.
That’s just one limitation of Version 1.
There’s also no merging available. So, every time you push the data to the Data Layer, it will overwrite the entire key (that you’re pushing data to). Let me illustrate.
Imagine that we have two Data Layer Pushes with different data. The first push contains a post object with only one parameter, pagePostAuthor, and the other one includes the other two keys, pageCategory and pagePostType.
//The 1st Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'authorData' : {
'pagePostAuthor': 'Julius Fedorovicius'
}
});
//The 2nd Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'authorData' : {
'pageCategory': 'google-tag-manager-tips',
'pagePostType': 'post'
}
});
As a final result, you’d have only two values in the Data Layer: pageCategory and pagePostType because the 2nd push 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. Definitely not.
For example, in GA4ecommerce tracking, it’s important not to have any artifacts (scraps) from previous pushes, meaning that every time a window.dataLayer.push occurs, it rewrites keys.
Version 2
The 2nd version is more flexible. It allows you to access nested values, arrays, merge data, or any other operations you need.
Let’s go back to the previous example with two subsequent Data Layer Pushes. The first push contains only pagePostAuthor; the other includes two more keys, pageCategory and pagePostType.
<script>
//The 1st Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'authorData' : {
'pagePostAuthor': 'Julius Fedorovicius'
}
});
//The 2nd Push
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'authorData' : {
'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.
{
'authorData' : {
'pagePostAuthor': 'John Doe',
'pageCategory': 'google-tag-manager-tips',
'pagePostType': 'post'
}
}
Simo Ahava has posted a detailed guide about Data Layer Versions. If you still have some questions, go check it out.
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.

Different data structures
Keep in mind that data can be stored in the data layer using different structures. Here’s an example (the key pagePostAuthor is in the root level).
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'pagePostAuthor': 'Julius Fedorovicius'
});
</script>
Or this (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>
Every structure requires a different way to define the key in the Data Layer variable. In the case of the first example, the key should look like this:

In the 2nd example, the correct variable name should be:

In the 3rd example, you should pull the first product’s category by entering the following name:

There’s a chance that the latter screenshot confused you a bit. Where did that 0 come from? If you want to understand better how to pull the data from the Data Layer, read this blog post.
Troubleshooting: Why is my Data Layer Variable undefined?
The most common issue with Data Layer Variables is getting an undefined value instead of the expected data. Here’s a checklist to diagnose the problem:
- Check for typos (case sensitivity!): The “Data Layer Variable Name” you entered in the GTM variable configuration must exactly match the key’s name in the Data Layer, including capitalization. pagePostAuthor is different from pagepostauthor. Double-check this first!
- Verify Data Layer version: Make sure your DLV is set to Version 2. Version 1 cannot access nested data (using dot notation). In 99% of situations where you work with Google Tag Manager, you will need to use Version 2.
- Check dot notation for nested keys: If the data is nested inside another object in the Data Layer (e.g., attributes: {‘pagePostAuthor’: ‘…’}), you must use dot notation in the GTM variable: attributes.pagePostAuthor. Similarly, for arrays, use dot notation with the index number (starting from 0): transactionProducts.0.sku. You can learn more about this here.
- Confirm timing: The dataLayer.push() containing your key must occur before or on the GTM event where you are trying to use the variable.
- In GTM Preview mode, click the specific event in the left-hand timeline (e.g., “DOM Ready”, “customEvent”) where your tag fired or your trigger condition was evaluated.
- Go to the “Data Layer” tab for that specific event. Is the key and its value present in the data model shown there?
- If the key only appears in the Data Layer on a later event, your variable will be undefined at the moment it’s needed. You might need to adjust your triggers or work with developers to push the data earlier.
Best practices for using Data Layer variables
To make your GTM setup cleaner and more reliable when using Data Layer Variables, follow these practices:
- Use a consistent naming convention: Name your GTM variables clearly. A common convention is prefixing with dlv – followed by the Data Layer key name (e.g., dlv – pagePostAuthor). This makes them easy to identify in GTM.
- Always use version 2: Unless you have a specific reason, configure your DLVs to use Data Layer Version 2 for maximum flexibility.
- Be exact with key names: Double and triple-check the spelling and case sensitivity when entering the “Data Layer Variable Name”. This is the most common source of errors.
- Use dot notation correctly: Understand how to access nested data (parent.child) and array items (array.index.child, e.g., array.1.child). Inspect the Data Layer tab in preview mode to confirm the structure.
- Consider setting a default value: If a Data Layer key might not always be present when your variable is needed, set a default value (like (not set) or undefined) to handle these cases gracefully in your reports or trigger conditions.
Do you still need to learn Data Layer in the era of server-side tagging?
Yes (at least in most cases). Many server-side GTM setups are hybrid setups (where they have a web GTM container and it sends data to the server-side container).
If your web tracking setup still has the browser-side (client-side) components, you will be using the data layer. Thus, this knowledge will be necessary.
Further reading
This is neither the first nor the last post about Data Layer in this blog. So if you have any questions, check out these posts (or subscribe to my newsletter and stay up-to-date):
- What is Data Layer in Google Tag Manager?
- 3 ways to pull data from the Data Layer
- Custom Event trigger explained (because the Custom Event trigger can be used to turn all Data Layer events can be turned into triggers)
Data Layer Variable: Final words
Data Layer variable is one of the most (if not THE MOST) used types of variables in my Google Tag Manager accounts. Most of the built-in variables in GTM are data layer variables, too.
With its help, you can access data stored in the Data Layer and utilize it in your tags, triggers, or even other variables.
In this blog post, I’ve explained how to set up a variable, how to access data (which is stored using different data structures), what’s the difference between Version 1 and Version 2, etc.

15 COMMENTS
Thank you, Julius! Your pages on DataLayers gave me much needed information about how to deal with "nested" variables that I could not find anywhere else. I wonder if I could ask one other question that I'm also having trouble finding the answer to:
Our developer has implemented DataLayers on our website using the window.dataLayer.push method. I have also set up the Variables in GTM for these variables. However, when debugging in GTM Preview, all variables appear as "undefined". I've seen some opaque references that indicate that a third step might be required- a "click trigger". Does something need to "fire" via a trigger in order for me to be able to see a variable value in GTM Debug mode or should I still be able to see the value populating without that? Thanks again!
No, nothing needs to be fired additionally if the data is already pushed to the Data Layer. My suggestions:
1. Open the Data Layer tab of the Preview and Debug console. Do you see that data pushed to the Data Layer.
2. If yes, maybe that data is stored in an array? In that case, you should define which exact array member do you wish to access. I've also explained this technique here https://www.analyticsmania.com/post/pull-data-from-data-layer-google-tag-manager-tutorial/
Hey Julius (And others that may know),
Is there a cheat sheet for GTM Syntax's that can be used. Struggling to find anything that can help. Particular reference to the RegEx variable section.
Thanks,
Josh
Hey, Josh. Could you elaborate on what you're trying to achieve? There's no such thing as a GTM syntax. GTM utilizes already existing technologies like JavaScript, Regular Expressions, CSS Selectors, DOM, etc.
If you want to learn more about the Regular Expressions, just google it. Regex in GTM is no different that Regex somewhere else. You can start here https://www.apasters.com/blog/regex-guide-google-analytics-tag-manager/
Hi, can you please give a hint, what I am doing wrong, trying to reach price value in the following data layer code:
{
"event": "productClick",
"ecommerce": {
"currencyCode": "EUR",
"click": {
"actionField": {
"list": "General Product List",
"action": "click"
},
"products": [
{
"id": "HH381621013",
"name": "Arch of Triumph",
"price": 379.43,
"category": "Handle Bags",
"stocklevel": 0,
"brand": "",
"position": 1
}
]
}
},
I tried ecommerce.products.price and ecommerce.products.0.price.
Both don't work :(
Thank you for your help.
ecommerce.click.products.0.price
Hi Julius, can you please help me with this.
I would like to scrape the DOM to extract the model selected by the user and ideally I would like to track the model on successful form submission on this page https://au.skoda.com.au/request/test-drive.
1)How to Create datalayer variable in GTM which can be used to populate the values of model selected by user.Using javascript scrape the model information .
2)Set up a GTM tag that should trigger when a user is able to successfully submit a form.
Thank you for your help.
Wrong variable. Use this https://www.analyticsmania.com/post/dom-element-variable-in-google-tag-manager/
Hey Julius,
Firstly, you're a legend and your content has helped me immensely!
If I have understood correctly, in UA I can create any variable name I want right? Then when creating the DLV in GTM I just need to make sure I'm referencing the correct var name.
And for GA4, I can do the same as long as it is not the same as the default variable names Google has reserved?
Thanks!
Hi, your question is a bit confusing to me. Can you rephrase it?
Are datalayer variables page scope or session scope? For example if I want to add user ID to the datalayer to track usage, do I need to push the userID value to the datalayer everytime a new page loads or can i do it just once post login?
Data layer variables are unrelated to GA scope. If a page refreshes, all data in your data layer is lost. Something (e.g. developer's code must push the data *again* to the data layer.
If you want to track user login, user id must be explicitly pushed on every pageview
Hi Julius,
Is it possible to send an object as a variable value ?
Or is it necessary to do something different ?
Thanks for the content you share !
Depends on where you send that data. If GA, then in most cases, GA requires you to send strings or numbers, not objects.
Julius! Thank you! The "Different Data Structures" section of this post kept me from pulling out ALL my hair. I just couldn't get a custom data layer variable to work until this.