
March 10, 2025
Quick Guide: dataLayer.push with examples
Updated: March 10th, 2025.
This quick guide was born after getting multiple questions from Google Tag Manager beginners/intermediate users: when should I use dataLayer.push() and when Data Layer declaration (dataLayer = [{}])?
The reason why this question was raised at all is that Google Tag Manager’s official documentation used to be a bit misleading in some parts. Continue reading, and I’ll show you where.
Video tutorial
If you prefer video content, here’s a tutorial from my Youtube channel.
dataLayer.push?
So what is dataLayer.push in the first place? It’s a code that enables one to add/update data that is stored in the Data Layer, for example:
<script> window.dataLayer = window.dataLayer || []; window.dataLayer.push({ 'event': 'new_subscriber', 'formLocation': 'footer' }); </script>
But what does it mean? Well, let’s have a quick refresher on what the Data Layer is. P.S. If (after reading this blog post) the topic still looks confusing, consider enrolling in my Google Tag Manager course for Beginners where I explain what dataLayer.push is in much greater detail.
What is Data Layer?
Data Layer is one of the main Google Tag Manager concepts, which ensures maximum flexibility, portability, and ease of implementation. Without it, GTM would not work. It is what keeps your tag management running properly. It is the key to unlocking Google Tag Manager’s potential.
I’ve already covered the Data Layer in my other guide, Complete Data Layer Guide, but to save you some time, here’s the TL;DR version.
Simply put, a Data Layer is like a bucket that stores certain information. It’s a central place (virtual layer) of a website where you, your developers, or 3rd-party-tools tools can temporarily store data (about a user, page content, etc.). From there, Google Tag Manager reads that information, uses it in tags/triggers/variables, or sends it further to other tools, such Google Analytics, Google Ads, Facebook/Meta, 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 have to add anything more. However, if you want some more custom data, like user ID, Product price, Order total, etc. (and use that in Google Tag Manager), additional configurations will be needed, and that’s where dataLayer.push plays an important role.
Store/update data in the data layer
There are two ways the data can be pushed to the data layer. Actually, there is only one that you should be using, but for the sake of knowledge, I’ll mention both:
- By adding a Data Layer snippet above the Google Tag Manager container snippet ( dataLayer = [] ). This method is also mentioned in the official GTM documentation. It’s called Data Layer declaration.
- Or by pushing data with dataLayer.push method.
What’s the difference, you ask?
Data Layer declaration (not recommended)
This method of inserting data into the Data Layer could be used if you want to add any data right when the page loads, for example, user ID. As a result, you could utilize the user ID variable in the All Pages trigger.
In this case, your developers should add a Data Layer snippet above (this is important!) GTM tracking container with the actual user ID. Once this information is added to the Data Layer, you can start working with it in Google Tag Manager. Here’s a code example:
<script> dataLayer = [{ 'userID': '123456' }]; </script> <!-- Google Tag Manager --> // this is where your Google Tag Manager container snippet should be placed <!-- End Google Tag Manager -->
If a developer places this snippet below the Google Tag Manager container, it will break things. One of the consequences will be broken All Pages trigger. Also, Google Tag Manager will not be able to track various website interactions, such as clicks, form submissions, etc.
Why? Because by using the syntax dataLayer = [], you are resetting the dataLayer variable to a new Array (read: you clear the bucket), thus overwriting anything that was in it before (such as Google Tag Manager’s customizations needed for tracking to work). Since you overwrite the dataLayer, it no longer works properly with Google Tag Manager, and the typical symptom is that GTM’s triggers don’t work anymore, either.
dataLayer.push (recommended)
The second method of putting data in the data layer is dataLayer.push, which is recommended and should be your only choice. Regardless of where you place it (below or above the Google Tag Manager container), dataLayer.push will work properly. Here are a few examples:
- You have a newsletter signup form (which cannot be easily tracked with a default GTM’s form listener), so you decided to ask a website developer to fire a Data Layer event once a new subscriber has successfully entered his/her email on your website:
<script> window.dataLayer = window.dataLayer || []; window.dataLayer.push({'event': 'new_subscriber'}); </script>
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)).
<script> window.dataLayer = window.dataLayer || []; window.dataLayer.push({ 'formLocation': 'footer', 'event': 'new_subscriber' }); </script>
- When a visitor adds a product to his/her cart, a Data Layer event (containing the product’s information) could be fired.
One more thing. Suppose you compare code snippets in this blog post to those explained in the official Google Tag Manager documentation for developers. In that case, you’ll notice that my code examples also have the “window” prefix (instead of dataLayer.push, I use window.dataLayer.push).
This helps with potential scope conflicts in the JavaScript code. Those conflicts are pretty rare, but still possible.
Therefore, you should add a prefix window to the dataLayer.push as a rule of thumb. The final dataLayer.push code snippet could look like this:
<script> window.dataLayer.push({ 'formLocation': 'footer', 'event': 'new_subscriber' }); </script>
By the way, the dataLayer name is case-sensitive. This means that only the letter L must be uppercase:
- DataLayer.push will not work (because D is uppercase)
- datalayer.push will also not work (all letters are lowercase, although L should have been uppercase).

One more dataLayer.push example
Previously mentioned dataLayer.push examples are pretty basic, but if you need to, you can also push data as objects or arrays, for example:
<script> window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: "view_item_list", ecommerce: { items: [ { item_id: "SKU_12345", item_name: "Stan and Friends Tee", price: 10.03, quantity: 1 }, { item_id: "SKU_12346", item_name: "Google Grey Women's Tee", price: 21.01, quantity: 1 }] } }); </script>
What happened here is that with one dataLayer.push, we also pushed an array (items) containing two objects. Each object contains the same set of keys (item_id, item_name, price, quantity), but their values differ. And that’s logical because two different products will usually have different characteristics.
OK, now what?
After the data/events are pushed into the Data Layer, it’s time to start working with them:
- Do you want to use a Data Layer event as a trigger? Do it with the Custom Event Trigger.
- Do you wish to access some data (e.g., userID) and send it to Google Analytics 4? Create a Data Layer Variable for each data point you want to access from the Data Layer.
- If you are working with the GA4 ecommerce setup, you don’t need to create separate variables for each ecommerce data point. GA4 event tags can automatically pick that data from the dataLayer with a checkbox called “Send ecommerce data”.
Don’t forget the comments
There is a bunch of helpful comments below this article. So if you are still confused about the dataLayer,push, take a look below. Maybe the questions you have are already answered there.
dataLayer.push: Final Words
DataLayer.push is a way for you/developers/3rd-party-plugins to pass some useful data to the Data Layer. From there, you can “play with it” in Google Tag Manager and use it in your tag management.
dataLayer.push should be the only way how you add data. Google Tag Manager’s official documentation used to mention/recommend using a Data Layer declaration (dataLayer = [{}]), but eventually even they switched all code examples to contain the “push”.
40 COMMENTS
If I push an event to the dataLayer before GTM is loaded in what order do things happen once GTM loads? Say I have GA set for 'all pages' and another GA set for this specific event... would all pages always 'run' before the event trigger or because the event was pushed before GTM loads it would happen immediately?
Tag Sequencing makes it seem like that tag would be fired 'again' or in addition to the tag you add it. If I have GA set to fire once per event on all pages then on another tag choose GA as the setup tag (fire before)... it seems like GA would be fired twice or just once if it already had - right? Isn't ordering of the tags what Tag Firing Priority is for?
Hey, if you push event + data before the GTM snippet, then that event will occur before the Pageview event.
As for your second question, a tag might fire once, it might fire twice. It depends.
Imagine there are 2 tags:
- Event tag
- Some other tag.
If:
- "Some other tag" fires on All pages
- AND you also set Event tag as its setup tag
- AND also Event tag is set to fire on All pages, then Event tag will fire only once because everything is happening within the boundaries of "Pageview" event.
If you set event tag to fire on DOM Ready, then Event tag will fire twice per page:
- On All pages
- And on DOM Ready
Hi Julius,
Thanks for sharing all the great posts. These are really helpful for people like me to get an understanding. We are working on a task to track user login and account creation on our website; however, we handle login and account creation process through Centralized account / sub-domain. i.e. if I try to login from a landing page --> it takes to the sub-domain --> after authentication, user returns back to the landing page.
Looking for your suggestion, what will be the best approach to track login using data layer in multi domain cases.
Thanks!
Tracking visitors across the main domain and its subdomains is not a "multi-domain tracking". It's still happening on the same domain. Just keep the "cookieDomain: auto" in your GA Settings Variable and you're good to go.
Hi,
We use Oracle Infinity as Analytics tool. I have added Oracle Infinity tag to GTM and data is being correctly sent to tool for standard variables.
We have custom variables we need added. I have added a Custom HTML Tag in GTM to trigger on a button click which is clicked after a user makes specific selections. Developer added code to site to push data(user selections) to dataLayer.
When I test, GTM has current dataLayer values but what is sent when tag fires( dcs call ) is always previous data (previous user selections).
Is triggering tag on button click wrong solution?
here is code:
//Oracle Infinity UDO testing
dataLayer.push({'o_filteraction':'AdvancedSearch'});
dataLayer.push({'o_filtertype':checkTypes.join(';')});
dataLayer.push({'o_filterfeature':checkFeatures.join(';')});
dataLayer.push({'o_filtercategory':checkCategory.join(';')});
dataLayer.push({'o_filteraccommodation':checkAccommodation.join(';')});
dataLayer.push({'o_filterlocation':checkLocation.join(';')});
dataLayer.push({'o_filterdates':checkDates.join(';')});
dataLayer.push({'o_filterprice':checkPrice.join(';')});
Hi, if you want to use the latest data from the data layer in your tags, your dataLayer.push codes need to have 'event' key).
E.g.
dataLayer.push({
'event' : 'some_event_name', //this could be the same for all the pushes that you listed in your comment
'o_filteraction':'AdvancedSearch'
});
Then create a custom event trigger that will be activated on "some_event_name". That way you will get the latest data in your tags.
Read more about the custom event trigger - https://www.analyticsmania.com/post/google-tag-manager-custom-event-trigger/
Hey Julio, alright? I have some custom variables that are used for standard GA events ... For example:
window.dataLayer.push ({
'event': 'dataevent',
'mycategory': "Group",
'myaction': "Clik",
'mylabel': "button x"
});
Now in a single push I need to send multiple events at once.
Is that what I should do?
window.dataLayer.push({
'event': 'dataevent',
'mycategory': {[“Grupo”]}, // this is the string unique for all
'myaction': {[”Click one, Click two”]}, // these change
'mylabel': {[“button x, buton y”]} // these change
});
Thank you for your help
You should better send separate events, not everything at once. This means separating dataLayer.push as well. Category, action and label accept only strings, not arrays or objects.
Hi Julius and others.
The website I work for has a search field and the client needs the list of search queries, since the dev's do ajax call, we don't have track on the searches.
I tried the below-
<script>window.dataLayer = window.dataLayer || [];window.dataLayer.push({'searchQuery': 'value'});</script>
and created an event, whenever earch button is clicked, value from searchQuery will be sent to GA, but since the variable will be null, I cant track the searches correctly.
Now, how can I delay the tag and wait for the searchQuery variable to get the search value and then send the value to GA?
Thanks in Advance,
Thomas
You can use the following code:
<script>window.dataLayer = window.dataLayer ||[];
window.dataLayer.push({
'searchQuery': 'value',
'event' : 'searchComplete'
});</script>
Then create a custom event trigger that activates on "searchComplete" event and only then fire the tag.
Hi Julius,
Is there a way to use the info in a Data Layer variable set via website1, in a different portal(website2)?
The task: the user perform an action in website1 and as a result we set a value in a variable ("true"). We need to read that value in website2 before executing some code (via a GTM tag).
We can not use cookies for this, as apparently you can not (not allowed) to access cookies set in other websites.
Many thanks
You could try passing the variable via URL. When the visitor goes from website1 to website2, the URL should be decorated with the value of the variable.
Hi Julius,
Need a small help. I have created a custom event. The label has a variable which captures the search (a section search not internal site search) phrases. Used DLV type for creating a variable to capture the value.
Event is also firing perfectly. In preview mode, under tags, the label value is firing as undefined. However, under datalayer tab, I can see the value passing to DLV variable. But this data is not being pushed to analytics. Here is the code placed on website
window.dataLayer = window.dataLayer || [];
window.dataLayer.push
({
'event': 'Ideas Search'
‘dlv_ideas_search_term’: ‘value’
})
Kindly assist.
Regards,
Swapna
This means that your data layer variable is incorrect. Check the grammar error.
Swapna, I had the same problem. We had to change the trigger to Window Loaded rather than Page View because PV fired too early to actually capture the data.
Once we changed to WL, the data started making it into Analytics.
Good luck!
This will work is dataLayer.push occurs very late. If dataLayer.push was above the GTM container (in the code), then All Pages trigger would work well.
Hi,it seems my login event gets pushed after container event has loaded and as such the userId doesn't get sent to GA. I am pushing my dataLayer event as soon as the page renders.
I am not doing it above the GTM container in the code because I won't be able to access the userId I intend to push.
How can I fix this problem please
Hey! found a way to do it. Stored my userid in local storage, that way I could access it before the declaration of my container. Thanks!
I have one question regarding the push function. If I want to push my custom event before any gtm.start or load or error. How can I achieve that?
Place your code above GTM container.
Hi Julius,
I have read many of your tutorials but stuck in one common scenario. I have following data structure to push using dataLayer:
{
event: 'loginSuccess',
category: 'Login',
action: 'loginSuccess',
noninteraction: false, // Optional
loginType: 'Google',
userID: dataObj.user_id
userEmail: dataObj.user_email.
}
I have created the variables in GTM and while creating a loginSuccess event tag to send data to GA I am not able to figure out how to send all the other variables as most of the example show one variable that too they pass in the "label" mapping of GA in the GTM.
I need to send all the variables and track in GA this is one sample there are many such events with 4-5 data variables in each of them.
I am so confused as not able to figure out this small issue.
Thanks in advance.
You need to create datalayer variables for each data point. And then it's up to you how you can to send them. It can be event action, category, label, custom dimensions, etc.
Hello Julius,
how does the dataLayer object is sent to GTM?
when I use the push method the navigator behaves as if I'm just updating a local js array/object and the web browser dev tools doesn't show any network request. Using the push method shouldnt be generating some kind of network movement? (or maybe I'm just missunderstunding the datalayer behavior...)
Thanks!
Based on dataLayer.push,GTM updates its internal model stored in the google_tag_manager object
Great article👏I am confused about one thing, I am assuming that the data layer would be empty at first.
E.g. I am making a purchase event and I pass amount, this amount is moved to data layer, on a button click.
So what code should be present on the button? Should there be any code on the button?
Depends on how the website is coded. For example, a developer could write the listener that checks clicks of a particular button and then dispatches data to the dataLayer.
Can I push data into GTM/GA in code? Basically, I want to have the user submit an order then I'll wait for the response, when/if the response comes back as successful, I want to push the data into GTM/GA before sending the user to the Thank You page. I have having issues with the Thank You page so I'd like to capture the data sooner using this method.
Is it even possible?
Then do the dataLayer.push before the redirect
Thanks for article Julius.
I want to implement the
1.
window.dataLayer.push
({
'event': 'Apply Now Click'
})
2.
window.dataLayer.push
({
'event': 'Sign In Click'
})
Where should I put this script on the page?
You could just use the built-in click tracking in GTM https://www.analyticsmania.com/post/google-tag-manager-click-tracking/
Can you use the Custom HTML Tag in GTM to push missing ecommerce events into the data layer? (So a marketer can bypass the developer)
Yes, but do you know how to write JavaScript code so that your dataLayer.push would fetch the data dynamically from the website (a.k.a. scrape)? Often, copy pasting will not work.
If you don't know, then you need a developer.
Hi Julius,
I am facing a problem when triggering the 'view_item' event next to the view_item_list. The previous event's data is displayed in the data layer. I want only one item to appear in the 'view item' event. How can I manage this?
Before the view_item dataLayer.push, you could do another push where ecommerce : null
Hi Julius,
perhaps you or other can help me to clean my datalayer after submit. I have 2 forms in one page - order form and inquiry form. It can happen that someone submits one of them and later the other one. And it happens that the old data are submitted together with new event data.
Using WP and CF7. Can I for example have a tag of custom HTML in GTM that cleans variables of a fired tag? Is it even possible to flush all variables of a given event? Or should I do it different way?
Thanks in advance for any help.
Hi Julius,
If I push an event via custom html in the datalayer, like this:
dataLayer.push({
'event': 'test',
Will this actually fire an event in GA4 called test without additional tags added, or is this simply being added as a listening event that Tag Manager can use to listen? I.e. will need to add an event tag with a custom event trigger, which will then allow me to push into GA4?
Thanks!
It will not send event test to GA4. You still need a tag in GTM that fires on the "Test" event.
I am facing an issue with implementing the dataLayer in my Angular application. In my setup, I have a base dataLayer script in the index.html file, which is initialized as follows:
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
Business_Unit: "",
Location: "",
Designation: "",
});
When making an API call, I receive data for the above attributes (e.g., Business_Unit, Location, etc.). After receiving the data, I update or push the updated values to the dataLayer.
The issue arises with built-in Google Analytics events like page_view, page_reload, or scroll. I want these built-in events to trigger updates to the dataLayer with the new data. While this setup works perfectly for custom events, it does not seem to work with the built-in GA events.
Can you provide a solution to ensure that the window.dataLayer updates properly when built-in GA events are triggered?
Hii
i have a Question, i am using the universal tag and universal trigger
where tag is :<script>
// Make sure we only define this onc
(function () {
// Use a named handler so we can remove it if needed
function hcoGtmClickHandler(event) {
var targetElement = event.target.closest(".hco-gtm-event");
if (targetElement) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: targetElement.getAttribute("data-hco-event"),
eventCategory: targetElement.getAttribute("data-hco-event-category"),
eventAction: targetElement.getAttribute("data-hco-event-action"),
eventLabel: targetElement.getAttribute("data-hco-event-label")
});
console.log("GTM Event Fired:", targetElement.getAttribute("data-hco-event"));
}
}
// Only add the listener once
if (!window.hcoGtmListenerAttached) {
document.addEventListener("click", hcoGtmClickHandler);
window.hcoGtmListenerAttached = true;
}
})();
</script>
and trigger is:
click class contains hco-gtm-event
which i want to use for all events in my website so now when creating ga4 how can i use this universal trigger to track any particular event
Do I need to declare this each time if I am using multiple scripts to push to the datalayer
window.dataLayer = window.dataLayer || [];
??
For example, we have one to push the user_id:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({'user_id': 'XXX'});
</script>
and one to push a purchase event:
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event: "purchase",
ecommerce: { ... }
});
</script>
In this case, do we use window.dataLayer = window.dataLayer || []; each time? The instructions from Google on https://developers.google.com/analytics/devguides/collection/ga4/set-up-ecommerce are confusing and imply that we just use <script>window.dataLayer = window.dataLayer || [];</script> once in the then push to it with dataLayer.push but that does not seem to work at all. Thanks!