Manipulating the Data Layer: JavaScript variables and Enhanced Ecommerce

*This article is about Universal Analytics which will sunset on 1 July 2023 and be replaced with Google Analytics 4. You can find our GA4 content here.

This post sets out to solve a very specific problem: namely, how to balance the competing demands of a platform-agnostic Data Layer and the Enhanced Ecommerce plugin for Google Analytics.

This might sound niche, but you’d be surprised how many large ecommerce websites using Google Tag Manager eventually run into this challenge.

The Problem: Platform Agnosticism

Enhanced Ecommerce tracking is infinitely better than the standard Ecommerce plugin (ecommerce.js). It offers deep insight into your website’s customer journey, allowing you to measure product impressions, shopping cart behaviour, checkout abandonments, and so on.

enhanced-ecommerce

The most efficient way to implement Enhanced Ecommerce is with Google Tag Manager (GTM), and the bulk of the work necessary to do so is in configuring your site’s Data Layer (see Google’s Documentation). Once the relevant attributes and values are present on the page, enabling Enhanced Ecommerce in GTM is as simple as ticking a box.

However, in larger organisations – particularly those valuing data-led decision-making – the Data Layer often has multiple stakeholders and needs to serve multiple analytics platforms. For this reason, a degree of platform agnosticism is always encouraged; it minimizes the number of moving parts in your reporting setup and keeps things lean and DRY (don’t repeat yourself!).

Customisations to Enhanced Ecommerce tracking frequently require us to use proprietary, GA-specific syntax in our Data Layer. To illustrate the problem, I’ve created the following example based on a real problem I encountered with one of our Analytics clients:

<script>
  window.dataLayer = window.dataLayer || [];

  dataLayer.push({
    "ecommerce": {
      "purchase": {
        "actionField": {
          "id": "123456",
          "affiliation": "Outdoor Adventure Park",
          "revenue": "29.98",
          "location": "Bristol" // Our custom purchase attribute
        },
        "products": [{
          "name": "Quad Biking",
          "id": "15727899",
          "category": "Vehicle Track",
          "price": "14.99",
          "quantity": "1"
        },
        {
          "name": "Clay Pigeons",
          "id": "16682710",
          "category": "Shooting Range",
          "price": "14.99",
          "quantity": "1"
        }]
      }
    }
  });
</script>

Our (fictional) website allows users to make bookings at a number of outdoor activity centres. As you can see, the Data Layer above corresponds to our purchase page, and it shows that our customer has purchased two activities – clay pigeon shooting and quad biking – at the Bristol venue.

Our nice, platform-agnostic Data Layer includes the name of the venue in the actionField object, where it is available to all analytics platforms under the name location. Makes sense, right? Because users are asked to select a venue during the first step of the checkout process, location is a purchase-level attribute, rather than product-level: all transactions containing multiple items relate to a single location.

However… let’s say we want to push location to Google Analytics as a product-scoped custom dimension, so we can aggregate revenue by location. Doing so requires an arbitrary modification to each item in the products array:


"products": [{
  "name": "Quad Biking",
  "id": "15727899",
  "category": "Vehicle Track",
  "price": "14.99",
  "quantity": "1",
  "dimension3": "Bristol" // Setting a custom dimension
}]

For various (completely valid) reasons, our development team do not wish to make this change:

So, what do we do?

The Solution: A GTM JavaScript Variable

In the Ecommerce settings area of your GA tag, you can choose to use a GTM variable instead of grabbing the information directly from the Data Layer. This means we can fetch our platform-agnostic ecommerce payload, manipulate it with a custom JavaScript variable, and feed it back into our GA tag in precisely the required format.

First, we’ll create a Data Layer variable which fetches the ecommerce object. We’ll call it ‘dlv – ecommerce – full’. Be sure to select Version 1 of the Data Layer, since this will ensure that GTM only accesses the payload which was most recently pushed into the Data Layer – see this excellent primer on Data Layer versions by Simo Ahava.

What we want to do is copy the value of the location property in our ecommerce payload and add it to each item in the products array. To do this, we’ll create a Custom JavaScript variable which we’ll call ‘ecom – Purchase with Dimension’.

custom-javascript-variable

The script is quite simple – we access our original ecommerce Data Layer Variable under the name ecom, and get the value of its location property from actionField using dot notation. We then have a simple loop which iterates through each item in the products array and adds a dimension3 property to each, with the location as its value. Finally, we return the manipulated data as a new ecommerce object.

The last step is to open your Enhanced Ecommerce enabled GA tag and untick the box for ‘Use Data Layer’. Instead, reference your newly-created ecommerce object:

And that’s all you need to do. Assuming your product-scoped custom dimension in slot 3 is configured in your GA property, valuable data will start accumulating immediately.

The most important thing to remember is that your Custom JavaScript variable must return a correctly-formatted and valid ecommerce object, exactly as you might find in a GA-specific Data Layer. As long as it does, and you’ve referenced this variable in your GA tag, GTM will use your new version instead of the generic on-page version.

While I’ve used a product-scoped custom dimension as my example, you can really get quite imaginative with this – by combining your Custom JavaScript variable with other variable types such as DOM Elements and Lookup Tables, you can create a highly customised ecommerce payload for GA.

However, don’t get carried away. Ideally this technique should be used to avoid proprietary customisations to your Data Layer, rather than as a hack to sidestep any of its fundamental shortcomings. Don’t start screen scraping, or doing anything that will incur loads of development debt further down the line. In the words of esteemed GTM expert Uncle Ben, “with great power comes great responsibility”.

If you need assistance with an Enhanced Ecommerce implementation or would like to discuss your GTM setup with a consultant, you can reach our experts here.

Thanks for reading! Let me know what you think in the comments or on Twitter.

Join the Inner Circle

Industry leading insights direct to your inbox every month.