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 Software Engineer at LunaMetrics. He is passionate about web technology, measurement, and analysis. Dan is the winner of the 1999 Forge Road Elementary School Science Fair for his groundbreaking report on how magnets work. (ICP, take note.) Dan has worked at LunaMetrics in social media, as our marketing manager, and now in our analytics department.

  • 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.

Contact Us.


24 S. 18th Street, Suite 100,
Pittsburgh, PA 15203

Follow Us



We'll get back to you
in ONE business day.