Useful Custom JavaScript Variables for Google Tag Manager

This post shows some useful Custom JavaScript Variables for Google Tag Manager. #2 and #3 require modification for your own site, while the others can be plugged in directly.

Add Custom JavaScript Variables by navigating to Variables > New > Custom JavaScript.

#1 Value of the Closest Parent ID
#2 Text of the Closest Specific Parent Class
#3 Up and Down the DOM
#4 Hit Timestamp
#5 Visitor IP Address
#6 GA Client ID
#7 List of SKUs
#8 Full URL

11/2019 update: Access several more Custom JS scripts for working with an Enhanced Ecommerce data layer here: Leverage Enhanced Ecommerce Data Layer for Marketing Pixels


Check out my new API Connector Add-on to import data from thousands of platforms (e.g. Shopify, Harvest, Mailchimp, ActiveCampaign, VWO, YouTube, etc.) directly into Google Sheets.

#1 Value of the Closest Parent ID

A common use case for Google Tag Manager involves tracking clicks on some type of content block and tying them into the right category. Often there's a title or some other text on the block, but it may also contain clickable images. This means you can't rely on GTM's built-in Click Text Variable, since it will return null when there's no text to grab. It also may be too specific, in cases where you want to get the title of the entire block, rather than just the clicked element itself. In those cases, you can look up the DOM for an ID value that describes the entire block.

This screenshot shows an example of the above, with a list of products and images contained in a section labeled 'Our Drinks'. In this example, you might be interested in capturing that the user clicked in the 'Our Drinks' block, instead of (or in addition to) capturing that the user clicked 'Beer and Wine'.


This script will return the attribute value of the closest parent ID. Copy and paste it into a Custom JavaScript Variable, and you'll be able to access that parent value every time you click on any part of your site.

❓ Note: The script above (and the following 2 scripts) use the element.closest method, which returns the current element if it matches the given selector, or else the closest ancestor element that matches the given selector, or else null. The element.closest method is a relatively new feature of JS, but is currently supported by most browsers

#2 Closest Specific Class

The above script works if your desired text lies in the closest parent ID. This might not be the case for your site structure, though, so this is a variation on the above to show how you'd modify the script if you wanted to return the text associated with a specific class. This script will search up your DOM and return the text of the class named 'section-title'. Since we're looking for a specific value, you'll need to modify this script to match your own site structure. Substitute 'section-title' for the class name you're interested in.

The easiest way to find your class value is to just right-click > Inspect and view the page source in developer tools. This will show you the HTML of the element you're inspecting, and reveal which classes, IDs, and other elements of the DOM you'll want to capture for your analytics tracking.

#3 Up and Down the DOM

The 2 examples above took you up the DOM to find the attribute value of the closest ID, and the inner text of a specific class. This third example follows the same general structure, but elaborates slightly by first crawling up the DOM to the first class named "product_list". If that value exists, the script then crawls down from there and looks for the class "header h4". Finally it returns the inner text of that element.

As with #2, this requires that you modify the values '.product_list' and 'header h4' to match the HTML structure of your own site. See this post for a detailed example of how to use this method: DOM Scraping into Data Layer & Custom JS Variables

#4 Hit Timestamp

This script will attach an exact timestamp to every hit you collect. It's useful if you want to see exactly when something happened, since by default GA only breaks it down by the minute. It will return a value like '2019-01-24T03:46:51.427Z', and will be available as a secondary dimension in all reports.

See this post for how to use hit timestamps combined with visitor IDs to create a clickstream table: Quickstart Guide to Google Analytics Clickstream Data

#5 Visitor IP Address

This one is a little different from the others as it requires pasting into a Custom HTML Tag instead of a Custom JavaScript Variable. This is the script:

See this post for step-by-step implementation details: Get Visitor IP Address with Google Tag Manager

#6 GA Client ID

Google Analytics keeps track of individual users with an ID known as the GA Client ID. However, this ID isn't surfaced anywhere in GA except the User Explorer report (located in the Audience section of GA), and by default it can't be exported or associated with other data. To address this, you can capture the GA Client ID with the following script, and then push it into a custom dimension, where it can then be accessed and reported on like any other dimension.

#7 List of SKUs

If you're using GA to track transactions on your site, your developers have most likely already collected all the transaction-related information into a data layer using GA's required format. Other marketing and analytics tools often require the same data, but in *their* own format. Rather than sending your site devs out to collect and report the data all over again, you can do it yourself by taking the information you need from the existing data layer.

The following script will produce a comma separated list of all SKUs in a single transaction. First, create a Data Layer Variable to contain the entire ecommerce object, named 'ecommerce'. Next, paste the following script into a custom JS variable.

See this post for more details on the above, as well as the syntax to extract transaction ID, revenue, and other e-commerce related values into Data Layer Variables: Collect Enhanced Ecommerce Values into GTM Variables

#8 Full URL

GA's built in 'Page URL' Variable won't return values in the URL after a hash (#). The following script will return the entire URL, including the protocol ('http'), hostname, path, query parameters, and any hash fragment.


  1. Hi
    I need to use a custom js variable to change the name of a data layer product impression variable from ‘style’ to ‘variant’. I also need to add a new variable that is the first 3 characters of another existing variable. I’m trying to work out the JS to write to accomplish these 2 goals.

    1. Hi Rebbret,
      To get the first three characters of a variable you can make a custom JS variable like this:
      var str = {{your variable}};
      var strFirstThree = str.substring(0,3);
      return strFirstThree;

      I’m not totally sure what you mean about changing the name of the data layer variable. Please clarify with a sample of your code and what you’d like to happen, and I’ll be happy to help further.

  2. Again! This is an amazing post. I’ll link to it in one of my upcoming post on GTM. I am not sure what you can do with the hit timestamp? Can it tell me exactly when a specific tag was fired? If yes, where do you find the information afterwards?

    1. You’re too kind! Yep, the hit timestamp shows exactly when any tag fired. You would see it in a custom dimension later. So for example you could look at the All Pages report, then pull down Secondary Dimension = timestamp, and see exactly when each pageview occurred. It’s a way to disaggregate the standard GA reports.

  3. Hi guys, stupid question but I need to create a custom js variable that calculates revenue minus shipping, Do you know how to write it?
    huge thanks

    1. Hey, it’s not a stupid question. Do you already have variables set up that contain transaction revenue and shipping? If so, your new custom JS variable would look like this (just edit the variable names to match the names you’ve used in your container):
      return {{revenue}} - {{shipping}};

      If you don’t have revenue and shipping variables already set up, you can check this post for how to grab those values from an enhanced ecommerce data layer: Collect Enhanced Ecommerce Values into GTM Variables. If you’re using standard ecommerce let me know as the syntax will be a bit different.

Leave a Reply

Your email address will not be published.