As you might know, Enhanced eCommerce requires a special kind of implementation.

It goes way beyond your basic transaction tracking, and it would take a lot longer to implement, but the depth of the data would be definitely worth it.

Start off right

First and foremost, you have to enable Enhanced Ecommerce reporting for your Google Analytics view.

If you already have set up Analytics tracking on your site and you want to move to Tag Manager, we suggest creating a new GA property for testing purposes. Having both tracking codes on the site might lead to counting the data twice for the same property. To avoid this, you want to remove the standard GA tracking precisely at the moment when you add the GTM one.

Also, you want to thoroughly test the Tag Manager implementation before you put it live.

There is a debugging section towards the end of the article, which I am sure that will be useful.

For now, let’s go ahead with the core Tag Manager set up.

After you create an account and a container at tagmanager.google.com, it’s time to add the GTM code to the site.

There are three main elements which you need to add to every web page (in the following order):

the dataLayer variable declaration -> in the <head> section the javascript part of the code -> in the <head> section as well the noscript part of the code -> immediately after the opening tag

To start sending data to Google Analytics, we need to set up a basic pageview tag in GTM.

Make sure you don’t forget to enable the Enhanced Ecommerce Features!

Now, off to the exciting part.

To make it easy for the development team, we are going to break it down by page type.

The order of the implementation can be anything you want it to be. This way feels more comfortable to us, but there are other recommendations of how to do it. It’s up to you to choose the most suitable one.

Listing pages

These can include category pages, brand listings, search results, custom taxonomies, and so on. Pretty much, every page that contains a list of products.

The most important details to track here are product impressions and clicks.

The first step is to populate the dataLayer with the Enhanced Ecommerce data.

Tracking product impressions

For these to work, you need to push the details to the dataLayer when the page loads.

There are two common ways of sending product impressions:

populating the dataLayer before the GTM JS code is loaded

before the GTM JS code is loaded attaching an event to the dataLayer object

It should be enough just to have the code on the page for the tracking to work.

If you are working with an infinite scroll type of load, you could add the impression code dynamically as the products are revealed. In this case you should be using an event to send the data.

Here is a code sample (page load interaction):

dataLayer.push({ "ecommerce": { "currencyCode":"USD", "impressions": [ //the array of products present within the listing { "id":"9bf1d", //internal id or SKU "name":"Boss T-Shirt", //you should have at least Name and ID set up "price":"44.00", //use only xxxx.xx formatting "brand":"Bvlgari", //manufacturer or designer "category":"Men/Clothing/T-Shirts", //can be hierarchical up to 5 levels; separated by"/" "position":0, //position within the list "variant":"Blue", //optional,if you need more differentiation "list":"Category page" //custom name for the list of products }, { //second product "id":"j6be7", "name":"Comverges T-Shirt", "price":"32.45", "brand":"Comverges", "category":"T-Shirts", "position":1, "list":"Category page" }, ... { "id":"2u3gy", "name":"Kiosk T-Shirt", "price":"56.70", "brand":"Kiosk", "category":"T-Shirts", "position":1, "list":"Category recommendations" //you could even include a separate list of products on the category page like a custom recommendation section } ] } });

To check if it’s working, we need the help of the browser console.

There are three quick things you need to inspect:

the dataLayer variable just by typing it in the console; if the result shows something similar to the image below, the dataLayer is populated correctly (this just means that the data is going into Tag Manager, not into Google Analytics) if the dataLayer is populated before the “Page View” occurs (only for non-event interactions) using an extension like Google Analytics Debugger to output the data that is being sent to Google Analytics into the browser console; for the impressions to work, it should look something like this:

To see how an event interaction would work, check the product clicks section below.

Advanced tip

Keep in mind that Google Analytics has a limit of 8kb of text that can be sent in a request (~8000 characters).

If you have a lot of products per listing, you might want to split the push into multiple requests.

Savio’s method is a good way of doing that. Here is a slightly modified version of the code that does it:

if (product.length >0) { //product is an array that contains all the product impression details var maxProducts = 35; //max objects that will be sent with 1 hit while (product.length) { var p = product.splice( 0 , maxProducts); //separate the product array into ones of maximum 35 objects dataLayer.push({ 'ecommerce': { 'currencyCode':'USD', //add your own currency 'impressions': p }, 'event': 'productImpressions', //we are using an event to send the impression data }); }; };

Or we can send them one by one. But, it will require the use of javascript code on the site to populate the dataLayer.

Here is an example jQuery code that does it (keep in mind that you will have to pull out the data for each product from the page code):

//prepare the dataLayer ecommerce object dataLayer[0 ]['ecommerce' ] = {}; dataLayer[0 ]['ecommerce' ]['impressions' ] = []; dataLayer[0 ]['ecommerce' ]['currencyCode' ] ='USD'; var productdata; //create an empty variable $('.product-item-class' ).each( function (i) { //for each product item on the page productdata = jQuery(this ); //populate the product data with the current product details //push the details to the dataLayer for each product (we are assuming that every product item has the details set up in "data-*" attributes) dataLayer[ i ]['ecommerce' ]['impressions' ].push({ 'name': productdata.data('product_name' ), 'id': productdata.data('product_id' ), 'price': productdata.data('product_price' ), 'category': productdata.data('product_cat' ), 'position': productdata.data('productlist_position' ), 'list': productdata.data('productlist_name' ) }); });

To see the results of this good amount of work in Google Analytics check the Conversions > Ecommerce > Product List Performance report.

Going further!

Tracking product clicks

The dataLayer push is a bit similar to the impression one. The main difference comes from the way it’s triggered.

The most common implementation is to use a custom event that occurs whenever a product is clicked.

Here is a sample dataLayer code:

dataLayer. push ({ "event":"EEproductClick", "ecommerce": { "currencyCode":"USD", "click": { "actionField": {"list":"category" }, "products": [{ "id":"9bf1d", "name":"Boss T-Shirt", "price":"37.00", "brand":"Converse", "category":"Men/Clothing/T-Shirts", "position":"2" }] } } });

Now we need to grab the data in GTM.

Tag Manager Configuration to capture the event

First, the trigger: a custom event having the same name as the one from dataLayer; make sure it’s unique throughout the container.

Secondly, the tag: send the event to GA using the trigger we created; check to use Data Layer.

To make sure that GTM is tracking the event you can either do the good ol’ click-and-escape on a product or you can try the GTM sonar Chrome extension to block the default behavior of clicks (we explain how it works in the Debugging section of the article).

The click event should look something like this in the preview window:

To make sure it goes to GA, have a look at the Real Time > Events report to see if “eCommerce – Product List Click” shows up after you click on a product.

[Video Tutorial] capture dataLayer events in Tag Manager

Analytics: The data is in the same report as the impressions: Product List Performance.

See the “Product list clicks” metric. It’s also used to calculate Product List CTR (list clicks/impressions).

If you have the “Add to Cart” button on listing pages, you will have to implement the events as in the section below (Product page > Tracking adds to cart).

Advanced tip

There is a way to send the click data to Tag Manager without using an event. You could use the GTM auto-event tracking feature (“click” in this case).

You will need to provide the data for the ecommerce object for each product somewhere in the web page code (using one or more “data-*” attributes for example). After that, you need to capture the ecommerce data into a GTM variable.

After you get all the details into a variable, you need the same trigger and tag setup to send the event data to Google Analytics.

In this case, you want to trigger the clicks only for products in listings, and the tag won’t be using the dataLayer to send the data to Google Analytics, but the custom variable you created.

A bit more complicated, but not by far.

Moving on!

Product page

Tracking product detail views

The most important element to track on this page is the product detail view. Similar to the product list impressions push, you can track the detail view just by loading the code for this pageview.

Code sample for the dataLayer:

dataLayer.push({ "ecommerce": { "currencyCode":"USD", "detail": { "actionField": {"list":"Boss Clothing"}, //optional list property "products": [{ "id":"gkj62", "name":"Boss T-Shirt", "price":"26.10", "brand":"Boss", "category":"Men/Clothing/T-Shirts", "variant":"black" }] } } });

Analytics With the product detail views, we start to get into the great looking reports, Ecommerce > Shopping Behaviour in this case.

If related products like cross-sells or up-sells are present on the product page (most likely they are) you will have to track the impressions for these as we did in the previous section. The good news is that you can combine impressions and detail within the same ecommerce object. Keep in mind the 8Kb limit!

Advanced tip – AJAX loading variations

If your store contains products that have different sizes, colors, materials, etc. set up as variants, you might want to consider tracking detail views for each one.

Tracking adds to cart

The way to track adding products to the cart is by using a custom event.

Below is a code sample for the dataLayer push. You will notice it’s a bit similar to the product click event.

It’s important to mention that quantity comes into play in the ecommerce object (a user could add more than one item to the cart).

dataLayer.push({ "event":"EEaddToCart", "ecommerce": { "currencyCode":"USD", "add": { "products": [{ "id":"gkj62", "name":"Boss T-Shirt", "price":"26.10", "brand":"Boss", "category":"Men/Clothing/T-Shirts", "variant":"black", //optional, if there is a variant of the product "quantity":1 }] } } });

The Tag Manager setup is very similar to the one we used for the product click (see above): a trigger that captures the custom event (named “EEaddToCart” in this case) and a Universal Analytics event tag to send the dataLayer details.

If everything goes well (fingers crossed!) the GA debug console should print something like this:

Analytics reports

The add to cart event is quite the pillar metric for Enhanced Ecommerce, and it’s used across multiple reports from the Conversions > Ecommerce section:

as a funnel step in the Shopping Behaviour report, we talked about in the Product Detail Views section

Product Performance: used for the Cart-to-detail Rate metric (product adds to cart/product detail views)

metric (product adds to cart/product detail views) Product List Performance: viewing product adds to cart by list name, list position, product name, SKU

Cart page

This might come as a surprise, but the cart page is not always a page per se.

It could be a dropdown widget or even a section on the checkout page.

On each of these sections, you will want to track if a product is removed from the cart or if a quantity increase/decrease interaction occurs.

Tracking removes from cart

The remove from cart is very similar to add to cart. Instead of the “add” object, you have the “remove” one.

dataLayer.push({ "event":"EEremoveFromCart", "ecommerce": { "currencyCode":"USD", "remove": { "products": [{ "id":"gkj62", "name":"Boss T-Shirt", "price":"26.10", "brand":"Boss", "category":"Men/Clothing/T-Shirts", "variant":"black", //optional, if there is a variant of the product "quantity":1 }] } } });

Tracking quantity change in cart

The quantity increase should be treated as an add to cart and the quantity decrease like a remove from cart.

As simple as that!

Advanced tip

In Google Analytics no default report offers details about removes from cart, but you can create a custom report to see the data:

Checkout page

Remember how in the first section of the article we set up some custom checkout steps when we enabled Enhanced Ecommerce in Google Analytics?

Now, it’s time to map out the steps in the dataLayer.

Keep in mind that the thank you page is NOT a checkout step. We will deal with it in the next section of the article.

Tracking the first step

The most comfortable way to track the checkout is by using an event for all the steps (see the Tracking product clicks section for details on how to set up a trigger and tag in GTM that sends the data to GA).

Here is the dataLayer code sample push for the first step:

dataLayer.push({ "event":"EEcheckout", "ecommerce": { "checkout": { "actionField": {"step":1,"option":"Free delivery" }, "products": [{ "id":"98adsh", "name":"Converse T-Shirt", "price":"12.50", "brand":"Converse", "category":"Men/Clothing/T-Shirts", "variant":"red", "position":0, //it could prove insightful to send the product position within the cart in the checkout process, although not mandatory "quantity":2 }, { "id":"m3g45", "name":"Boss Pants", "price":"38.00", "brand":"Boss", "category":"Men/Clothing/Pants", "variant":"blue", "position":1, "quantity":1 }] } } });

Notice the actionField object: it will map to the first step you set up as checkout option in GA (“Cart page” in our case). You could also consider the Cart page as a step in the checkout process.

Another element you might find useful is the checkout option. You could track stuff like billing, delivery, payment options or whatever you can think of.

It is a bit tricky because you might not have these details before the user submits the checkout form or before he moves to a next step.

So you can send an event that occurs when the user does the action (moving to a next step or hits the submit order button), or you could use the checkout_option object to update the value for a previous step.

Tracking secondary steps

The most important aspect to remember is that you should use the same event name across the checkout steps (“EEcheckout” in our case).

For the subsequent steps, it’s not mandatory to add the products Array to the dataLayer. It’s enough to send them for the first step.

Code sample, please!

dataLayer.push({ "event":"EEcheckout", "ecommerce": { "checkout_option": { "actionField": {"step":1,"option":"Free delivery"} //optional - setting the checkout_option for the previous step }, "checkout": { "actionField": {"step":2 } } } });

Since we set up the GTM tag and trigger on the first step, no further action is required for the secondary ones.

One step checkouts

It might seem easier to track them as a single step, but you might want to add more depth to the data.

Event though you have all the details on one single page, these are almost always grouped into sections like Billing, Shipping, Delivery, Payment.

Now depending on your coding skills, you could track each of these sections as a different step in the checkout process.

Analytics reports

– in the Product List Performance, you can analyze the Product Checkouts metric

– the Checkout Behaviour funnel is one of the most insightful reports provided by Enhanced Ecommerce

Thank you page

Here we have to send the purchase confirmation event. We have to capture it in GTM using the same tag and trigger type of setup we used for product clicks, add to cart, etc.

Code sample:

dataLayer.push({ "event":"EEtransaction", "ecommerce": { "purchase": { "actionField": { "id":"kut23e8r27", //transaction ID - mandatory "affiliation":"Online Store", "revenue":68, //total including tax and shipping "tax":"12.60", "shipping":5, "coupon":"CANO25" //if a coupon code was used for this order }, "products": [{ "id":"98adsh", "name":"Converse T-Shirt", "price":"12.50", "brand":"Converse", "category":"Men/Clothing/T-Shirts", "variant":"red", "position":0, "quantity":2 }, { "id":"m3g45", "name":"Boss Pants", "price":"38.00", "brand":"Boss", "category":"Men/Clothing/Pants", "variant":"blue", "position":1, "quantity":1 }] } } });

The actionField element stands out since it contains a bit more information than we have seen for the other dataLayer pushes.

The products object is again mandatory at this point.

On the confirmation page, we should pay close attention, so that duplicate orders are not being sent to GA.

Even though there are ways to do that in GTM, the easier and safer route would be to do it on your end.

Mainly, you want to avoid loading the transaction code more than once. You could very easily implement this by inserting an entry in the database once the transaction code is loaded the first time.

In Google Analytics the Enhanced Ecommerce transaction offers pretty much the same information as the basic one, except for a few more details like coupons, hierarchical product categories, product variants.

Other stuff to track

Promo views and clicks

These can occur on any page. So if you want to check the performance of your banners/promotions, you will have to push the data to the dataLayer on whatever page they are displayed.

The good news is that you can group them within the main ecommerce object.

Views

These should be tracked when the page loads, with no further action required in GTM.

dataLayer.push({ "ecommerce": { "promoView": { "promotions": [{ "id":"banner123", "name":"Summer sale", "creative":"HOME banner", "position":"top" }, { "name":"Free Shipping", "id":"FREE_SHIPPING", "creative":"Free shipping offer", "position":"Sidebar" }] } } });

Clicks

Promotion clicks should be pushed using a dataLayer event. See the product clicks section for the GTM setup.

Here is the sample code:

dataLayer.push({ "event":"EEpromotionClick", "ecommerce": { "promoClick": { "promotions": [{ "id":"banner123", "name":"Summer sale", "creative":"HOME banner", "position":"top" }] } } });

To check the performance in Google Analytics, go to the Ecommerce > Marketing > Internal Promotion report.

Tracking refunds

If the users can refund products on their own by completing a process on the website, you could track them using the dataLayer approach.

Just make sure to match the ID of the original order.

dataLayer.push({ "ecommerce": { "refund": { "actionField": {"id":"kut23e8r27" } } } });

Partial refunds

To set up partial refunds, you have to add a products array with the refunded products’ IDs and returned quantity.

dataLayer.push({ "ecommerce": { "refund": { "actionField": {"id":"kut23e8r27" }, //the transaction ID "products": [{"id":"ds78g","quantity":2 }, //product ID and refunded quantity {"id":"89ahs","quantity":3 }] } } });

If the refunds don’t happen within a user interaction process, the easiest way to send them to GA is by doing an import from a spreadsheet.

The data import happens at the property level. It can be done by manually uploading a spreadsheet from time to time or by using the management API.

You could also use GA’s measurement protocol to track the refunds, but it’s a bit more advanced technique.

In Analytics, you can see the refunded amount for each transaction in the Ecommerce > Sales Performance report:

Also, for each product in Ecommerce > Product Performance:

Debugging

This part is crucial since a lot of things can go wrong if you are not careful. Honing your troubleshooting skills would make your life a lot easier at this point.

Looking at interactions by type

Before getting into the tools that make our life easier, we should take a moment to think about an important distinction between interactions: those that take place when the page loads and those that happen when the user clicks on a particular element.

Interactions can:

occur at page load (something is being viewed on the page)

impressions detail views promotion views

occur at click interactions

product clicks promotion clicks

fit into any of the two categories (depending on the website)

add to cart (mostly user interaction based) remove from cart (mostly user interaction based) checkout steps (AJAX – mostly user interaction, non-AJAX checkout – mostly on page load) purchase (mostly page load)



Consistency

Another thing to keep in mind when looking for issues is, you guessed it, consistency.

You want to make sure that the essential elements like product names, IDs, etc., are the same across all dataLayer variables from every page.

For example, if you are using SKUs instead of product IDs, make sure they are the same every step of the tracking.

Aside from the major help the Tag Manager Preview brings, you might find some of the following very useful.

Google Tag Assistant

An uncomplicated and helpful Chrome extension that lets you know if tags like Google Tag Manager, Analytics, Adwords Remarketing or Conversion Tracking, etc., are working as they should do.

Once you start recording, you can navigate through multiple pages and get a summary for all of them.

There is also an option to turn on the Google Analytics debug mode. It’s useful if you don’t want to add one more extension like the Google Analytics Debugger of which we will talk about next.

Google Analytics Debugger

The simplest of Chrome extensions: just click on the icon and it turns on the debug mode of Google Analytics.

You will get the tracking data in the console. We’ve seen it’s major utility when we implemented product impressions and wanted to see if Google Analytics records them.

dataLayer Inspector+

A very handy Chrome extension that outputs the dataLayer interactions in the order they occur.

For us, it has been very helpful in revealing validation errors. You might not notice them just by looking at the code.

GTM sonar

It’s designed to block the default behavior of clicks and form submissions. This way you can easily use the other tools to debug events.

Other tools such as dataSlayer or Omnibug record the activity (live pageviews and events) across all the pages you visit.

This way, you could avoid the hassle of blocking the default behaviors of clicks or form submissions.

Tag injector

This one is useful if the website for which you are trying to configure Tag Manager doesn’t have the code in place.

This way you can do your Tag Manager configuration, without having to wait for the development team to implement the GTM code and the dataLayer

WASP

A bit more advanced tool that reveals how scripts and tags are deployed on your website.

You can also have a look at the Analytics collect calls and what triggered them.

Browser developer tools

More of a utility than a tool, it’s the place where you will spend a lot of time looking at:

the Elements tab: if you want to have a look at the Tag Manager code

the Console check Javascript errors and what caused them the GA debug mode check the dataLayer or any other variables (you can even interact with the dataLayer on your own)

the Network tab: see the collect Google Analytics calls (used to send data into GA)

custom tabs generated by browser extensions like WASP, dataSlayer, Omnibug, etc.

Problems within the platform

The best way to start digging into issues caused by the website is to look at the server logs.

First, you have to get your hands on the visitor’s IP address.

If he/she has placed an order, almost every eCommerce platform will display the IP in the admin area.

If the user didn’t manage to place the order, you would have to become a bit more creative to get it.

Just keep in mind that Google Analytics doesn’t show the IP address anywhere because of legal matters.

But once you get your hands on it, you can filter the access and error logs to display the activity for a certain user. This information will help you track down a lof of problems.

See the command we usually use on Linux machines to get the user data into a CSV file (replace 123.123.123.123 with the visitor IP):

grep -n "123.123.123.123 " access.log > user_123.csv

Conclusion and bonus

You might notice that the Enhanced Ecommerce implementation is not as simple as pressing a button.

Not even close!

But with the amount of new data you have the ability to take an eCommerce business to a whole new level.

The truth is that the hard work begins after the implementation. Putting the information to work is the real value!

Bonus

1. The tag manager setup/recipe we used along with this article. You can get the JSON configuration file from this link.

Get it into your Tag Manager container just by hitting import from the container settings menu.

To avoid any issues, we recommend merging the details to your current container, not to overwrite it.

2. A Google Analytics Custom Report for Product Performance Data: you can get it from the Solutions Gallery.

It offers an excellent overview of the most important details Enhanced Ecommerce has to offer for each product: