In this blog post I demonstrates how you can split an Google Analytics Enhanced Ecommerce Transaction on a product level (scope) using Google Tag Manager, create new and modified transactions based on the original transaction, and send the modified Ecommerce data to different Google Analytics Properties.
The story behind Splitting the Enhanced Ecommerce Transaction
Imagine that the diagram below is your ecommerce store:
- 1 website
- 2 or more business areas/departments have their “home” on the site, with their own products and brands
- Here illustrated as Sub Store A and Sub Store B, and I will use this wording in the rest of the blog post
- All Sub Stores uses the same checkout
- Purchases (transactions) can contain products from all Sub Stores in the same Transaction
The Challenge
But, then someone tells you that they also needs to analyze each Sub Store as an independent ecommerce store, since they are independent business areas.
- In Google Analytics you should be able to analyze and report data for the complete ecommerce store
- In Google Analytics you should be able to analyze and report data only for Sub Store A
- In Google Analytics you should be able to analyze and report data only for Sub Store B
This means that your Google Analytics tracking has to be something like this.
“OK, then I will have to implement some information to the site that tells me which Sub Store the visitor is browsing, and which Sub Stores that are in the transaction”, perhaps you think.
“Then I will filter on Sub Stores in Google Analytics, and create different Google Analytics Views per Sub Store using this setup”.
- 1 Google Analytics View that contains all data
- 1 filtered Google Analytics View that only contains data for Sub Store A
- 1 filtered Google Analytics View that only contains data for Sub Store B
Easy!
Or maybe not…
The problem is that transactions can’t be filtered on a product level (product scope), which means that the filtered view for Sub Store A will contain products belonging to Sub Store B, and vice a versa. Sessions, traffic source and number of transactions will be correct though, but products, ROAS, revenue and tax will be wrong.
However, if you create a filtered Custom Product Report in Google Analytics, it can tell a good story about products and revenue per Sub Store.
If this story isn’t good enough, prepare for Google Tag Manager lift off.
The Solution
The solution is to build a Google Tag Manager Rocket. You also have to use Google Analytics Enhanced Ecommerce, and each Sub Store will be tracked in it’s own Google Analytics Property.
Since we are going to build a rocket, make sure you have a very good engineer (programmer) on your team. Even if this isn’t rocket sience, it requires accurate implementation, if not the rocket will malfunction.
The Google Tag Manager Rocket
The Google Tag Manager Rocket works as a regular rocket. The main engine starts the liftoff, and after that different events ignites new stages. The only difference is that this rocket is without flames. You don’t want to see flames!
- Customer completes the transaction, and the Google Tag Manager Purchase script starts the liftoff.
- The complete transaction is sent to the Google Analytics Property that contains all data.
- Google Tag Manager identifies which Sub Stores that are in the transaction.
- Each unique identified Sub Store ignites a new stage.
- Google Tag Manager then creates a Google Tag Manager Purchase script that only contains data for that particular Sub Store. The script also calculates revenue and tax especially for that Sub Store.
- Transactions are sent to corresponding Sub Store Properties in Google Analytics.
The Google Analytics Rocket Setup
Google Analytics Properties
To be able to make this work, you have to create 1 Google Analytics Property for each Sub Store, in addition to the MyMainSite.com property. In this example this means that we have to create 3 Google Analytics Properties.
Google Analytics Tracking ID | Contains data for |
---|---|
UA-XXXXXX-1 | MyMainSite.com - Total |
UA-XXXXXX-2 | Sub Store A |
UA-XXXXXX-3 | Sub Store B |
Custom Dimensions
In each Google Analytics Property you have to create 2 Custom Dimensions for Sub Store tracking. Sub Stores have to be tracked both on Hit Scope and Product Scope.
Custom Dimension Name | Index | Scope |
---|---|---|
P: Sub Store | 1 | Product |
H: Sub Store | 2 | Hit |
Implement Google Tag Manager Purchase Script
Imagine that MyMainSite.com contains 2 different departments:
- Department 1 is called Sub Store A, and is selling clothes.
- Department 2 is called Sub Store B, and is selling shoes.
In the same order, you buy Sandals and Slim Fit Jeans, which means that you bought from both departments. Then a simplified Google Tag Manager Purchase script will look like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<script> dataLayer.push({ 'event': 'purchase', // GTM Event Trigger 'ecommerce': { 'purchase': { 'actionField': { 'id': '12345', 'revenue': '800.00', // Revenue ex. Tax and Shipping 'tax':'200.00', 'shipping': '39.00' }, 'products': [ { // Product 1 - Bought from Sub Store B 'name': 'Sandal', 'id': '123', 'price': '320.00', // Product Price ex. Tax 'brand': 'Famous Brand', 'category': 'Men/Shoes', 'variant': 'Cognac', 'quantity': '1', 'dimension1': 'Sub Store B' // Sub Store Dimension }, { // Product 2 - Bought from Sub Store A 'name': 'Slim Fit Jeans', 'id': '456', 'price': '480.00', // Product Price ex. Tax 'brand': 'Another Famous Brand', 'category': 'Men/Jeans', 'variant': 'Dark Blue', 'quantity': '1', 'dimension1': 'Sub Store A' // Sub Store Dimension } ] } } }); </script> |
- We must use a GTM Event as a trigger. In this example, the GTM Event is called purchase.
- In this example, revenue equals sum of products. This is important to be aware of, since there can be situations where this isn’t true. For example, rebate is added to the transaction and can’t be added to individual products.
- In these cases, sum of revenue in Google Analytics Sub Store Properties will differ from revenue in MyMainSite.com – Total Google Analytics Property.
- Sub Stores are tracked using Product Scope in dimension1. Change this Custom Dimension to reflect your Google Analytics setup.
- I have skipped tracking like affiliation, coupons and currency code since it isn’t relevant for the example.
Google Tag Manager Rocket Setup
Google Tag Manager Variables
Variable Name | Variable Type | Value | Comment |
---|---|---|---|
ecommerce | Data Layer | ecommerce | GTM Ecommerce Object |
GA ID - SubStore - Ecommerce | Lookup Table | For connecting the correct Google Analytics ID to correct Sub Store | |
subStore | Data Layer | subStore | |
subStore - D - Index | Constant | 2 | Google Analytics Dimension Index |
subStoreInPurchase | Custom Javascript | Get unique sub stores from the purchase object. |
Some of the Variables are further explained below.
Variable: ecommerce
This Data Layer Variable returns the “ecommerce” payload. Data Layer should be Version 1. See Enhanced Ecommerce With A Custom JavaScript Variable for more information.
Variable: GA ID – SubStore – Ecommerce
This is a Lookup Table that will match Sub Stores to the corresponding Google Analytics Tracking ID. It’s important that the value in the Input Field exactly matches the name of the Sub Store in your implementation.
Variable: subStoreInPurchase
This is a Custom Javascript Variable that will identify unique Sub Stores from the ecommerce object. Replace dimension1 in the script with your Product Scope Dimension.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function() { try { var array = {{ecommerce}}.purchase.products var unique = {}; var distinct = []; for(var i in array){ if(typeof(unique[array[i].dimension1) == 'undefined'){ // Replace dimension1 with your Product Scope Dimension distinct.push(array[i].dimension1); // Replace dimension1 with your Product Scope Dimension } unique[array[i].dimension1] = 0; // Replace dimension1 with your Product Scope Dimension } return distinct } catch(e) {} } |
Google Tag Manager Triggers
To be able to get lift off for this Google Tag Manager Rocket, we need 3 Event Triggers.
Trigger Name | Event Name | Trigger Fires On | Comment |
---|---|---|---|
purchase | purchase | All Custom Events | Purchase trigger. This can be compared to the first step in a rocket launch, where the main engine ignites and liftoff occurs. |
purchaseSubStore | purchaseSubStore | Some Custom Events | GA ID - SubStore - Ecommerce does not equal undefined |
purchaseSubStoreUnique | purchaseSubStoreUnique | All Custom Events | Purchase trigger for sub store. |
Trigger: purchaseSubStore
This is the only trigger that requires some more explanation, since it only triggers on Some Custom Events. This is the trigger that sends the transaction to the correct Sub Store.
Notice This trigger fires on, and the use of undefined in the rule. Undefined can often be your best Google Tag Manager Trigger friend.
Google Tag Manager Tags
We need 4 Tags for this tracking.
Tag Name | Tag Type | Trigger | Comment |
---|---|---|---|
GA - Event - Purchase - Main | Universal Analytics | purchase | GA Purchase Tag that tracks all Transactions. |
GA - PageView - Purchase - SubStore | Universal Analytics | purchaseSubStore | GA Purchase Tag that tracks Transactions for Sub Stores. |
EE - SubStore - Purchase - Unique SubStore | Custom HTML | purchase | Javascript that create a Trigger for each unique Sub Store |
EE - SubStore - Purchase - Script | Custom HTML | purchaseSubStoreUnique | Enhanced Ecommerce Purchase Script that splits the transaction per Sub Store. |
Tag: EE – SubStore – Purchase – Unique SubStore
This is a Custom HTML Tag, and it will loop through the {{subStoreInPurchase}} variable. For each identified Sub Store, this script will generate an GTM Event called purchaseSubStoreUnique.
The trigger for this Tag is purchase.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<script> (function() { try { var stringSubStore = {{subStoreInPurchase}}; var arrayLength = stringSubStore.length; var subStore; for (var i = 0; i < arrayLength; i++) { subStore = stringSubStore[i] dataLayer.push({'event':'purchaseSubStoreUnique', 'subStore':subStore}) } } catch(e) { // Uncomment line below for error tracking. This is not described in this blog post. //dataLayer.push({'event':'error', 'errorType': 'Purchase Unique SubStore', 'errorMsg':e}); } })(); </script> |
Tag: EE – SubStore – Purchase – Script
This is a Custom HTML Tag that contains a Google Tag Manager Enhanced Ecommerce Purchase script. This script loops through Sub Stores in the transaction, and generates 1 Ecommerce Purchase object per Sub Store.
The trigger for this Tag is purchaseSubStoreUnique.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<script> (function() { try { var ecom = {{ecommerce}}.purchase; var products = ecom.products; if (products.length > 0) { var subStore; var revenue = 0; var items = []; var taxCalc = ecom.actionField.tax/ecom.actionField.revenue; // Find Tax Percent. for(var i = 0; i < products.length; i++){ subStore = products[i].dimension1.replace(/\s/g, '').toLowerCase(); if (subStore.indexOf({{subStore}}.replace(/\s/g, '').toLowerCase()) > -1 ){ // Generate 1 Purchase Script per Sub Store var item = { 'name': products[i].name, 'id': products[i].id, 'variant': products[i].variant, 'brand': products[i].brand, 'category': products[i].category, 'price': products[i].price, 'quantity': products[i].quantity, 'dimension1': products[i].dimension1 // Replace dimension1 with your Sub Store Product Scope Dimension. }; var rev = Number(products[i].price*products[i].quantity); // Calculate Revenue based on sum of product prices revenue = revenue+rev; items.push(item); } } var tax = revenue*taxCalc; // Calculate Tax for Sub Store tax = tax.toFixed(2); if (items.length > 0){ dataLayer.push({ 'event': 'purchaseSubStore', // GTM Event Trigger 'subStore': {{subStore}}, // Save Sub Store to Hit Scope Dimension 'ecommerce': { 'purchase': { 'actionField': { 'id': ecom.actionField.id, 'revenue': revenue.toString(), 'tax':tax.toString(), 'shipping': ecom.actionField.shipping }, 'products': items } } }); } } } catch(e) { // Uncomment line below for error tracking. This is not described in this blog post. //dataLayer.push({'event':'error', 'errorType': 'Purchase Script', 'errorMsg':e}); } })(); </script> |
- var taxCalc in the script above is finding the tax percent. You may have to change this calculation method.
- Sub Stores are tracked in dimension1 on Product Scope. Change this Custom Dimension to reflect your Google Analytics setup.
- I have skipped tracking like affiliation, coupons and currency code since it isn’t relevant for the example.
Tag: GA – Event – Purchase – Main
This is a Universal Analytics Tag, and tracks the complete transaction. I use a Google Analytics Event as a “helper” for sending the transaction to Google Analytics.
Notice that I track {{subStoreInPurchase}} in my H: Sub Store Dimension. Sub Stores in the transaction will be returned as a comma separated string in this dimension.
The trigger for this Tag is purchase.
Tag: GA – PageView – Purchase – SubStore
This is a Universal Analytics Tag, and tracks Sub Store Transactions. Notice that I’m using Google Analytics PageView for sending the transaction to Google Analytics. This is because I’m blocking the regular Google Analytics PageView Tag on the checkout page and confirmation page in my Sub Store tracking.
Notice that I track {{subStore}} in my H: Sub Store Dimension. The Sub Store in the transaction will be tracked in this dimension.
The trigger for this Tag is purchaseSubStore.
Congratulations, you have built an Google Tag Manager Enhanced Ecommerce Rocket!
Some final words
In this blog post I have demonstrated how you can split an Google Analytics Enhanced Ecommerce Transaction using Google Tag Manager, but I haven’t mentioned how to track rest of the site. If you are going for complete Enhanced Ecommerce implementation, here is the short version:
- You have to build a Google Tag Manager Rocket also for the checkout.
- Sub Store Product Scope Dimension must be implemented for all products (Checkout, Add to Cart, Remove from Cart, Product Click and Product Impression). Hint: undefined will be your best friend in this GTM setup as well.
- You have to implement a global Sub Store Hit Scope Dimension. You need that one for a include Sub Store filter in Google Analytics.
- You also have to track traffic to the different Sub Stores using a Google Analytics Pageview Tag.
- You have to track all pages to all properties, and then use include filter for the Sub Store properties. In this example it means that on every page, there will be 3 pageview trackers.
Although it is possible to do this, and I have shared how I did it, this requires a lot of work.
I know I’m not the only one who have come across a case like this, but I haven’t seen any similar solutions shared, and therefor I wrote this blog post. If you have done something similar, or think the solution could be improved, feel free to add a comment.
I am trying to implement this for a single substore where I only report a certain type of product. Everything seems to be working well except for my products that are reported to my my main and substore on my main it reports double.
I have a setup similar to the Google Tag Rocket Manager.
I have made changes as I have to report all sales to my Main store and a particular type of sale to a single SubStore,.The set up is pretty much as the blog says except I have modified it for one SubStore.
If I make a purchase of my item that has to go to my Main and Substore. The item appears to double the sale in my main store. Eg I buy 2 tickets for my main and substore. They appear as 4 tickets on my main store but report correctly 2 tickets in my substore.
Thanks in advance for the help.