Referencing The dataLayer In Custom JavaScript Variables – Data Layer Best Practices Pt 3



We’ve collected a series of technical best practices designed to help you successfully interoperate with the Google Tag Manager Data Layer. These best practices are designed to help eliminate some of the peskier and harder-to-debug issues we run into when working with clients. This part covers when and how to reference the dataLayer within Custom JavaScript Variables.

Referencing the Data Layer within Custom JavaScript Variables

Let me say to start, Variables should always, always, always just return a value. That’s it. They should only return something. Seriously, if you’re thinking of doing anything else, stop right now. You want examples? Okay, fine; Variables should never:

  1. Call a globally declared function that does something other than return a value**
  2. Declare a function or variable globally
  3. Push something to the dataLayer
  4. Modify the DOM in any way (including #1)
  5. Redefine the values of other Data Layer Variables
  6. Change window.location or any stateful value
  7. Set a cookie
  8. Ad nauseum

To that end, you should never reference the Data Layer within your Custom JavaScript Variable. To “aid” in this pattern of thinking, Google actually injects an empty array into all Custom JS Variables named dataLayer, rendering calls to dataLayer.push() functionally neutered, no doubt to confuse and discourage you from this behavior. If you need to do any of the above, what you need is a Custom HTML tag with a script inside of it.


There is one edge case where you would need to push to the dataLayer – when you’re returning a function that you will later invoke in a Custom HTML Script/non-Variable context. Some examples of this include:

  • hitCallback functions
  • Our Custom JavaScript Error Catcher, detailed here
  • Any function that you want to reuse, like a timestamp converter

The key to these exceptions is there is a second step that has to occur before anything is invoked/pushed to, usually within a Custom HMTL Tag script. In those cases, it’s okay to put a dataLayer.push(); however, due to the injected fake dataLayer, you’ll need to explicitly reference window.dataLayer.push(), e.g.:

To recap, you should never do anything other than return a value from a Variable. If you feel the need to do more, you should instead use a Custom HTML Tag with a script inside of it. For more best practices, check out parts 1 and 2 of our series, covering proper dataLayer instantiation and pushing to the dataLayer within Custom HTML Tags, respectively. Keep binging in of our series on Data Layer Best Practices and check out Part 4, where you’ll learn about how to remove or reset values in the dataLayer.

**Things like _.extend or $('selector') are fine, as long as they’re simply returning a value. Just be sure to couch your code in checks for your dependencies!

Are you interacting with the dataLayer within your Custom JS Variables? Tell me how in the comments below.

Dan Wilkerson is a former LunaMetrician and contributor to our blog.

  • rwapple8236

    Funny that I just saw your post today, if I had saw it earlier, I probably would have gotten my issue resolved.
    I was using GTM variable to make an API call and create a cookie on the site (since it’s almost impossible to squeeze my request into dev team’s queue), but it only works in preview mode. After back and forth discussion with Google, they recommend to move the function to be a HTML tag rather a GTM variable, because in preview mode Google forces every single variable to run, but in production variables only get executed if referenced.

  • ប៉ាន់ វ៉ាន់ដេត

    Hi thank for your article.
    Please help!
    I want to track link when click any link on the website and push it’s link (href) value to dataLayer.
    Help me with this!!!

Contact Us.

Follow Us



We'll get back to you
in ONE business day.
Our Locations
THE FOUNDRY [map] LunaMetrics

24 S. 18th Street
Suite 100

Pittsburgh, PA 15203


4115 N. Ravenswood
Suite 101
Chicago, IL 60613


2100 Manchester Rd.
Building C, Suite 1750
Wheaton, IL 60187