• Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login
  • Courses
    • Courses
    • Course bundles
  • Blog
  • Resources
    • Youtube channel
    • E-books and Guides
    • GTM Recipes
    • View All Resources
    • GTM Community
    • GA4 community
  • Services
  • About
    • About
    • Contact
  • Login

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.

datalayer.push

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:

  1. 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.
  2. 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:

  1. 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>
  2. 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”.

 

 

Julius Fedorovicius
In Google Tag Manager Tips
40 COMMENTS
Steve
  • Jun 20 2018
  • Reply

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?

    Julius Fed (Fedorovicius)
    • Jun 20 2018
    • Reply

    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

Badhan
  • Mar 7 2019
  • Reply

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!

    Julius Fedorovicius
    • Mar 11 2019
    • Reply

    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.

David Martin
  • Mar 26 2019
  • Reply

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(';')});

    Julius Fedorovicius
    • Mar 27 2019
    • Reply

    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/

Andre
  • Apr 16 2019
  • Reply

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

    Julius Fedorovicius
    • May 17 2019
    • Reply

    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.

Thomas
  • Aug 28 2019
  • Reply

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

    Julius Fedorovicius
    • Aug 28 2019
    • Reply

    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.

Sergiu
  • Sep 10 2019
  • Reply

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

    Julius Fedorovicius
    • Sep 19 2019
    • Reply

    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.

Swapna
  • Feb 4 2020
  • Reply

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

    Julius
    • Feb 14 2020
    • Reply

    This means that your data layer variable is incorrect. Check the grammar error.

    T. Cooper
    • Feb 14 2020
    • Reply

    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!

      Julius
      • Feb 14 2020
      • Reply

      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.

        Emmanuella
        • May 19 2023
        • Reply

        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

          Emmanuella
          • May 19 2023

          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!

Jhalak Shah
  • Mar 16 2020
  • Reply

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?

    Julius
    • Mar 16 2020
    • Reply

    Place your code above GTM container.

Niranjan Prajapati
  • Oct 15 2020
  • Reply

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.

    Julius Fedorovicius
    • Oct 19 2020
    • Reply

    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.

Antonio
  • Jun 14 2021
  • Reply

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!

    Julius
    • Jun 14 2021
    • Reply

    Based on dataLayer.push,GTM updates its internal model stored in the google_tag_manager object

syed yaseen shabir ahamed
  • Nov 3 2021
  • Reply

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?

    Julius Fedorovicius
    • Nov 5 2021
    • Reply

    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.

Chris
  • Oct 19 2022
  • Reply

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?

    Julius Fedorovicius
    • Oct 26 2022
    • Reply

    Then do the dataLayer.push before the redirect

Tej
  • Dec 15 2022
  • Reply

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?

    Julius Fedorovicius
    • Dec 15 2022
    • Reply

    You could just use the built-in click tracking in GTM https://www.analyticsmania.com/post/google-tag-manager-click-tracking/

Gabriel
  • Aug 24 2023
  • Reply

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)

    Julius Fedorovicius
    • Aug 31 2023
    • Reply

    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.

haris
  • Apr 13 2024
  • Reply

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?

    Julius Fedorovicius
    • Sep 13 2024
    • Reply

    Before the view_item dataLayer.push, you could do another push where ecommerce : null

Petr Beloch
  • Apr 19 2024
  • Reply

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.

Rob
  • Nov 1 2024
  • Reply

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!

    Julius Fedorovicius
    • Nov 1 2024
    • Reply

    It will not send event test to GA4. You still need a tag in GTM that fires on the "Test" event.

Adii
  • Jan 22 2025
  • Reply

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?

divya
  • May 12 2025
  • Reply

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

Alex
  • May 12 2025
  • Reply

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!

Leave a comment Cancel reply

Your email address will not be published. Required fields are marked *


 

Hi, I'm Julius Fedorovicius and I'm here to help you learn Google Tag Manager and Google Analytics. Join thousands of other digital marketers and digital analysts in this exciting journey. Read more
Analytics Mania
  • Google Tag Manager Courses
  • Google Tag Manager Recipes
  • Google Tag Manager Resources
  • Google Tag Manager Community
  • Login to courses
Follow Analytics Mania
  • Subscribe to newsletter
Recent Posts
  • Conversion rate in Google Analytics 4
  • Google Tag Manager Data Layer Explained
  • Cross-domain tracking in Google Analytics 4
Analytics Mania - Google Tag Manager and Google Analytics Blog | Privacy Policy
Manage Cookie Settings