---
title: Integrating Google Analytics Enhanced Ecommerce
related:
  - https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/customizing-e-commerce-data-for-google-analytics.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

By using the Google Analytics Enhanced Ecommerce features, you can measure and analyze shopping activity on your website (product impressions, purchases, etc.). Xperience provides an API that helps get the data of products and purchases in a format suitable for logging via Google Analytics.

Visit the [Google Analytics website](http://www.google.com/analytics) to set up a Google Analytics account for the website that you wish to monitor.

## Adding Google Tag Manager

Before you can start measuring e-commerce activities, you need to add Google Tag Manager to the pages of your website. Copy the snippets from the [Google Tag Manager Quick Start Guide](https://developers.google.com/tag-manager/quickstart) into the appropriate sections of your MVC website's main layout (view).

You can then start collecting your site's e-commerce data and tracking events using Google Analytics. See the sections below for more information about setting up individual types of tracking.

## Collecting e-commerce data

We recommend using a [data layer](https://developers.google.com/tag-manager/devguide) to collect and send data to Google Analytics. For detailed information, see the [Enhanced Ecommerce (UA) Developer Guide](https://developers.google.com/tag-manager/enhanced-ecommerce).

The Xperience API provides methods that allow you to get suitable JSON data for [product](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/products.md) and [order](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/orders.md) objects, which you can push into the data layer. The following helper classes are available in the **CMS.Ecommerce** namespace of the standard Xperience API (provided by the _Kentico.Xperience.Libraries_ integration package).

**GtmProductHelper** class:

- **MapSku** – returns a _GtmData_ object containing the data of a specified product (_SkuInfo_ object). Provides the following data fields by default: _id_ (the product's _SKU_ value), _name_, _price_ and _brand_
- **MapShoppingCartItems** – returns an _IEnumerable_ collection containing the data of specified products in a shopping cart (_IEnumerable_ collection). By default, provides the same data fields as the _MapSku_ method and also adds the unit _quantity_ for each product.

**GtmOrderHelper** class:

- **MapPurchase** – returns a _GtmData_ object containing the overall purchase data for a specified order (_OrderInfo_ object). Provides the following data by default:
  - _actionField_ object representing the overall purchase, with the following fields:
    - _id_ (the integer ID of the Xperience order object)
    - _revenue_ (the order's _GrandTotal_ value, i.e. the final price including discounts, shipping, tax, and reductions from applied [gift cards](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/discounts/working-with-gift-cards.md))
    - _shipping_
    - _tax_
  - _products_ object containing all products within the order (the product data format is the same as provided by the _GtmProductHelper.MapShoppingCartItems_ method)
- **MapOrder** – returns a _GtmData_ object containing a summary of the specified order (_OrderInfo_ object). Provides the data fields described for the _actionField_ object within the data returned by the _MapPurchase_ method.
- **MapOrderItems** – returns an _IEnumerable_ collection containing the data of all products within the specified order (_OrderInfo_ object). Provides the same data as the _products_ object within the data returned by the _MapPurchase_ method.

**GtmDataHelper** class:

- **SerializeToJson** – serializes the _GtmData_ objects returned by the _GtmProductHelper_ or _GtmOrderHelper_ methods into JSON strings. Provides one overload for individual objects (_GtmData_ parameter) and another for collections of objects (_IEnumerable_ parameter).

> **Info:** **Adding custom data**
>
> When calling the methods of the _GtmProductHelper_ and _GtmOrderHelper_ classes, you can add custom data fields via the optional **additionalData** parameter. The methods merge the fields and values of the custom object into the returned _GtmData_ objects.
>
> ```csharp title="Example"
>
> GtmProductHelper.MapSKU(sku, new { category = "Apparel" })
>
> ```

Use the listed methods to create a Google Analytics implementation that suits the purposes of your website. Alternatively, you can compose the required JSON data manually using your own custom code. The following sections contain best practices for various types of e-commerce tracking on Xperience sites:

### Product impressions

To log impressions of products displayed to visitors (for example on [product listing pages](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/displaying-product-listings.md)):

1. Set up a view model class representing individual items in the product list:

   1. Add a property of the _GtmData_ type, which will store the product's Google Analytics data.
   2. Get the product's data by calling the **GtmProductHelper.MapSKU** method, and assign it to the new property.

      ```csharp

      using CMS.Ecommerce;

      public class ProductListItemViewModel
      {
          public readonly GtmData GtmSKUJson;
          ...

          // Constructor of the view model class representing items in product lists
          public ProductListItemViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail, string publicStatusName)
          {
              // Creates the Google Tag Manager data for the given product and assigns it to a property
              GtmSKUJson = GtmProductHelper.MapSKU(productPage.SKU);
              ...
          }
      }

      ```
2. Set up another view model class representing the overall product list:

   1. Add a property storing a collection of the listed products (represented by your list item view model class).
   2. Add a _string_ property, which will store the JSON data of all listed products.
   3. Create the product list JSON string by calling the **GtmDataHelper.SerializeToJson** method. Prepare an _IEnumerable_ collection containing the _GtmData_ values of individual products as the method's parameter. Assign the resulting string into the new property.

      ```csharp

      using System.Collections.Generic;
      using System.Linq;

      using CMS.Ecommerce;

      public class ProductListViewModel
      {
          public IEnumerable<ProductListItemViewModel> Products;
          public readonly string GtmProductsJsonString;

          // Constructor of the view model class representing the overall product list
          public ProductListViewModel(IEnumerable<ProductListItemViewModel> products)
          {
              Products = products;
              // Creates the Google Tag Manager JSON data for the product list and assigns it to a property
              GtmProductsJsonString = GtmDataHelper.SerializeToJson(Products.Select(product => product.GtmSKUJson));
          }
      }

      ```
3. Adjust your controller actions that display products to work with the view models. For example:

   ```csharp

   public ActionResult Index()
   {
       // Gets products of the product page type
       List<LearningProductType> products = pageRetriever.Retrieve<LearningProductType>(query => query
           .CombineWithDefaultCulture()
           .WhereTrue("SKUEnabled")
           .OrderByDescending("SKUInStoreFrom"))
           .ToList();

       // Prepares the view model for the listing page
       var model = new ProductListViewModel(products.Select(
           product => new ProductListItemViewModel(
               product,
               GetPrice(product.SKU, shoppingService.GetCurrentShoppingCart()),
               product.Product.PublicStatus?.PublicStatusDisplayName))
           );

       // Displays the action's view with an initialized view model
       return View(model);
   }

   ```
4. Edit the view representing your product list pages.
5. Run a script that pushes the JSON data from the product listing view model into the data layer.

   - You can either add a script tag directly into the view code or link an external JavaScript file.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp

     document.addEventListener("DOMContentLoaded", function (event) {
         dataLayer.push({
             "ecommerce": {
                 "impressions": @Html.Raw(Model.GtmProductsJsonString)
             }
         });
     });

     ```

### Product clicks

To log clicks of product links:

1. Edit the view model class that you use to display product links (for example on [product listing pages](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/displaying-product-listings.md)):

   1. Add a _string_ property, which will store the JSON data of the given product.
   2. Create a JSON string containing the product's data by calling the **GtmProductHelper.MapSKU** and **GtmDataHelper.SerializeToJson** methods, and assign the string to the new property.

      ```csharp

      using CMS.Ecommerce;

      public class ProductListItemViewModel
      {
          public readonly GtmData GtmSKUJson;
          public readonly string GtmSKUJsonString;
          ...

          // Constructor of the view model class representing items in product lists
          public ProductListItemViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail, string publicStatusName)
          {
              // Creates the Google Tag Manager data for the given product
              GtmSKUJson = GtmProductHelper.MapSKU(productPage.SKU);
              GtmSKUJsonString = GtmDataHelper.SerializeToJson(GtmSKUJson);
              ...
          }
      }

      ```
2. Define a JavaScript function for the pages containing product links (for example by adding a script tag to the corresponding views or by linking an external JavaScript file).

   - Within the function, push the data of the clicked product into the data layer. The function must have parameters containing the product JSON data and the URL of the clicked link.
   - Use the _eventCallback_ datalayer variable to perform redirection after the product data is sent to Google Analytics.

     ```js title="Function example"

     function productClick(productJson, link) {
         dataLayer.push({
             "event": "productClick",
             "ecommerce": {
                 "click": {
                     "actionField": {"list" : "Search Results"},
                     "products": [productJson]
                 }
             },
             "eventCallback": function () {
                 document.location.href = link;
             }
         });
     }

     ```
3. Add an **onclick** script to your product links and call the defined product click function.
   - Get the JSON data of the clicked product from the view model.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp title="View example"

     @model ProductListViewModel

     @foreach (ProductListItemViewModel product in Model.Products)
     {
         @* Creates a hyperlink to the product controller to display the product detail page *@
         string productDetailLink = Url.RouteUrl("Product", new { id = product.ProductPageID, productAlias = product.ProductPageAlias });
         <a href="@productDetailLink" onclick='productClick(@Html.Raw(product.GtmSKUJsonString), "@productDetailLink"); return false;'>
         ...
         </a>
     }

     ```

### Views of product details

To log data when visitors view your website's [product details pages](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/displaying-product-details.md):

1. Edit the view model class that you use to display product details.
2. Add a new _string_ property to the view model.
3. Create a JSON string containing the product's data by calling the **GtmProductHelper.MapSKU** and **GtmDataHelper.SerializeToJson** methods, and assign the string to the new property.

   ```csharp

   using CMS.Ecommerce;

   public class ProductViewModel
   {
       public readonly string GtmSKUJsonString;
       ...

       // Constructor of the view model class used to display product details
       public ProductViewModel(SKUTreeNode productPage, ProductCatalogPrices priceDetail)
       {
           // Creates the Google Tag Manager JSON data for the given product and assigns it to a property
           SKUInfo sku = productPage.SKU;
           GtmSKUJsonString = GtmDataHelper.SerializeToJson(GtmProductHelper.MapSKU(sku));
           ...
       }
   }

   ```
4. Edit the view representing your product detail pages.
5. Run a script that pushes the product JSON data from the view model into the data layer.

   - You can either add a script tag directly into the view code or link an external JavaScript file.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp

     document.addEventListener("DOMContentLoaded", function (event) {
         dataLayer.push({
             "ecommerce": {
                 "detail": {
                     "actionField": { "list": "Gallery" },
                     "products": [@Html.Raw(Model.GtmSKUJsonString)]
                 }
             }
         });
     });

     ```

### Additions and removals from a shopping cart

To log data when customers add or remove shopping cart items:

> **Info:** For more information about shopping cart management in general, see [Integrating the shopping cart](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/implementing-a-checkout-process/integrating-the-shopping-cart.md).

1. Edit the view model class that you use to display shopping cart content and add a _string_ property. The property will store JSON data for added or removed products.

   ```csharp

   public class ShoppingCartViewModel
   {
       // Property containing Google Tag Manager JSON data for added or removed products
       public string GtmAddOrRemoveCartItemJsonString { get; set; }
       ...
   }

   ```
2. Adjust the controller actions that you use to add or remove products to/from the shopping cart:

   - Create an object with an [Anonymous type](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types), and define the data fields that you wish to push into the Google Analytics data layer (see the [Enhanced Ecommerce (UA) Developer Guide](https://developers.google.com/tag-manager/enhanced-ecommerce#cart) for details).
   - Get the data of the added or removed product by calling the **GtmProductHelper.MapSKU** method. Use the method's optional _additionalData_ parameter to add the quantity of the added/removed product units into the data.
   - Serialize the anonymous type object into a JSON string (for example using the [Json.Encode](https://docs.microsoft.com/en-us/dotnet/api/system.web.helpers.json.encode) method) and assign the string into the corresponding property of the shopping cart view model. For example, you can use the [TempData](https://docs.microsoft.com/en-us/previous-versions/aspnet/dd394711\(v=vs.100\)) dictionary to pass the JSON string into another controller action that prepares the shopping cart view model.

     ```csharp title="Example - Action for adding items"

     [HttpPost]
     public ActionResult AddItem(int itemSkuId, int itemUnits)
     {
         // Adds the specified number of units of a given product to the current shopping cart
         shoppingService.AddItemToCart(itemSkuId, itemUnits);

         // Gets the current user's shopping cart
         ShoppingCartInfo currentCart = shoppingService.GetCurrentShoppingCart();

         // Creates an anonymous type object representing the Google Tag Manager JSON data for the product addition event
         var addToCartJson = new
         {
             @event = "addToCart",
             ecommerce = new
             {
                 currencyCode = currentCart.Currency.CurrencyCode,
                 add = new
                 {
                     products = new[]
                     {
                         GtmProductHelper.MapSKU(SKUInfo.Provider.Get(itemSkuId), new { quantity = itemUnits })
                     }
                 }
             }
         };

         // Serializes the Google Tag Manager JSON data of the product addition event into a string
         // Stores the string in the TempData dictionary, which is later used to prepare the shopping cart view model
         TempData["gtmAddOrRemoveCartItemJsonString"] = System.Web.Helpers.Json.Encode(addToCartJson);

         // Displays the shopping cart
         return RedirectToAction("ShoppingCart");
     }

     ```

     ```csharp title="Example - Action for removing items"

     [HttpPost]
     public ActionResult RemoveItem(int itemID)
     {
         // Gets the ShoppingCartItemInfo object representing the removed product
         // Note: Must be performed before calling the ShoppingService.RemoveItemFromCart method
         ShoppingCartItemInfo cartItem = ShoppingCartItemInfo.Provider.Get(itemID);

         // Creates an anonymous type object representing the Google Tag Manager JSON data for the product removal event
         var removeFromCartJson = new
         {
             @event = "removeFromCart",
             ecommerce = new
             {
                 remove = new
                 {
                     products = new[]
                     {
                         GtmProductHelper.MapSKU(cartItem.SKU, new { quantity = cartItem.CartItemUnits })
                     }
                 }
             }
         };

         // Removes a specified product from the shopping cart
         shoppingService.RemoveItemFromCart(itemID);

         // Serializes the Google Tag Manager JSON data of the product removal event into a string
         // Stores the string in the TempData dictionary, which is later used to prepare the shopping cart view model
         TempData["gtmAddOrRemoveCartItemJsonString"] = System.Web.Helpers.Json.Encode(removeFromCartJson);

         // Displays the shopping cart
         return RedirectToAction("ShoppingCart");
     }

     ```

     ```csharp title="Example - Updated action displaying the shopping cart"

     public ActionResult ShoppingCart()
     {
         // Gets the current user's shopping cart
         ShoppingCartInfo currentCart = shoppingService.GetCurrentShoppingCart();

         // Initializes the shopping cart model
         ShoppingCartViewModel model = new ShoppingCartViewModel(currentCart)
         {
             // Gets Google Tag Manager JSON data for product addition or removal events from the TempData dictionary                
             GtmAddOrRemoveCartItemJsonString = TempData["gtmAddOrRemoveCartItemJsonString"] as string
         };

         // Displays the shopping cart
         return View(model);
     }

     ```
3. Edit the view that you use to display shopping cart content.
4. Run a script that pushes the JSON string from the shopping cart view model into the data layer:

   - You can either add a script tag directly into the view code or link an external JavaScript file.
   - Wrap the script code into a condition that checks the JSON string for null or empty values. The condition ensures that the script only runs when displaying the shopping cart after a customer adds or removes products.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp title="View example"

     @model ShoppingCartViewModel

     ...

     @if (!String.IsNullOrEmpty(Model.GtmAddOrRemoveCartItemJsonString))
     {
         <script type="text/javascript">
             document.addEventListener("DOMContentLoaded", function (event) {
                 dataLayer.push(@Html.Raw(Model.GtmAddOrRemoveCartItemJsonString));
             });
         </script>
     }

     ```

### Checkout steps

To log progress of customers through the steps of your website's [checkout process](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/implementing-a-checkout-process.md):

1. Identify the first page in your checkout process where modifications of the shopping cart content are no longer allowed.
2. Edit the view model class that you use for the given checkout page and add a _string_ property. The property will store JSON data for the products in the shopping cart.

   ```csharp title="Example"

   public class DeliveryDetailsViewModel
   {
       public CustomerViewModel Customer { get; set; }
       public BillingAddressViewModel BillingAddress { get; set; }
       public ShippingOptionViewModel ShippingOption { get; set; }

       // Property containing Google Tag Manager JSON data for products in the shopping cart
       public string GtmCartItemsJsonString { get; set; }
   }

   ```
3. Adjust the controller actions that you use to display the given checkout page:

   - Get the JSON data for the products in the shopping cart by calling the **GtmProductHelper.MapShoppingCartItems** method.
   - Serialize the shopping cart product data into a JSON string by calling the **GtmDataHelper.SerializeToJson** method, and assign the string into the corresponding property of the view model.

     ```csharp title="Example - Action for displaying the delivery details page"

     public ActionResult DeliveryDetails()
     {
         // Gets the current user's shopping cart
         ShoppingCartInfo cart = shoppingService.GetCurrentShoppingCart();

         ...

         // Creates the Google Tag Manager JSON data for the products in the shopping cart
         string gtmCartItemsJsonString = GtmDataHelper.SerializeToJson(GtmProductHelper.MapShoppingCartItems(cart.CartProducts));

         DeliveryDetailsViewModel model = new DeliveryDetailsViewModel
         {
             Customer = new CustomerViewModel(shoppingService.GetCurrentCustomer()),
             BillingAddress = new BillingAddressViewModel(shoppingService.GetBillingAddress(), countries, null),
             ShippingOption = new ShippingOptionViewModel(ShippingOptionInfo.Provider.Get(shoppingService.GetShippingOption()), shippingOptions),
             GtmCartItemsJsonString = gtmCartItemsJsonString
         };

         // Displays the customer details step
         return View(model);
     }

     ```
4. Edit the view representing the appropriate checkout page:
   - Run a script that pushes the required checkout data into the data layer. Get the JSON data of the shopping cart's products from the view model.
   - You can either add a script tag directly into the view code or link an external JavaScript file.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp

     document.addEventListener("DOMContentLoaded", function(event) {
         dataLayer.push({
             "event": "checkout",
             "ecommerce": {
                 "checkout": {
                     "actionField": {"step": 1},
                     "products": @Html.Raw(Model.GtmCartItemsJsonString)
                 }
             }
         });
     });

     ```
5. Edit the views representing the pages used for the remaining steps in the checkout process.
   - For each step, run a script that pushes the required checkout data into the data layer, but without including the _products_ field. For example:

     ```csharp

     document.addEventListener("DOMContentLoaded", function (event) {
         dataLayer.push({
             "event": "checkout",
             "ecommerce": {
                 "checkout": {
                     "actionField": {
                         "step": 2,
                         "option": "@Model.ShippingOption.ShippingOptionDisplayName"
                     }
                 }
             }
         });
     });

     ```

### Purchases

To log purchases (i.e. completed [orders](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/orders.md)) on your website:

1. Identify the page that you display to customers after they successfully complete a purchase on your website (for example a "thank you" page).
2. Set up a view model class for this "thank you" page:
   - Add a _string_ property, which will store the JSON data for the purchase.
   - Create a JSON string containing the purchase data by calling the **GtmOrderHelper.MapPurchase** and **GtmDataHelper.SerializeToJson** methods, and assign the string to the property.

     ```csharp

     using CMS.Ecommerce;

     public class ThankYouViewModel
     {
         public readonly string GtmPurchaseJsonString;

         // Constructor of the view model class for the "thank you" page of the checkout process
         public ThankYouViewModel(OrderInfo order)
         {
             // Creates the Google Tag Manager JSON data for the purchased order
             GtmPurchaseJsonString = GtmDataHelper.SerializeToJson(GtmOrderHelper.MapPurchase(order));
         }
     }

     ```
3. Find an appropriate controller action to display the "thank you" view (for example an action that handles payments). Create an instance of the view model class for the related _CMS.Ecommerce.OrderInfo_ object. For more information about order processing, see [Building the order review step](https://docs.kentico.com/13/e-commerce-features/developing-on-line-stores/implementing-a-checkout-process/building-the-order-review-step.md).
4. Edit the view that you use to display the "thank you" page.
5. Run a script that pushes the purchase JSON data from the view model into the data layer:

   - You can either add a script tag directly into the view code or link an external JavaScript file.
   - Process the JSON string to ensure that the output is not HTML encoded (for example by calling the [HtmlHelper.Raw](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.htmlhelper.raw) method).

     ```csharp

     document.addEventListener("DOMContentLoaded", function(event) {
         dataLayer.push({
             "ecommerce": {
                 "purchase": @Html.Raw(Model.GtmPurchaseJsonString)
             }
         });
     });

     ```
