---
title: Customizing e-commerce data for Google Analytics
related:
  - https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce.md
  - https://docs.kentico.com/13/custom-development/customizing-providers.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).

Google Analytics allow tracking of shopping activity on e-commerce websites. To help you set up this functionality in Xperience, the system provides methods in the API that return JSON data for products and orders in a suitable format. For more information, see [Integrating Google Analytics Enhanced Ecommerce](https://docs.kentico.com/13/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce.md).

By default, the system's methods do not set all of the optional data fields that can be processed by Google Analytics. If you wish to extend or completely change how the system creates e-commerce data for the purposes of Google Analytics, use the following customization approach:

1. Prepare an assembly (_Class Library_ project) with class discovery enabled in your Xperience solution (or use an existing one). See [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md).
   - Reference the project from both your live site and Xperience administration (_CMSApp_) projects.
2. Create a custom class that inherits from one of the [Google Analytics data helper classes](#google-analytics-data-helper-classes).
3. Override the methods of the helper class according to your custom requirements.
4. [Register](https://docs.kentico.com/13/custom-development/customizing-providers/registering-providers-using-assembly-attributes.md) your helper implementation using the **RegisterCustomHelper** assembly attribute.

When you reload the website, the system creates e-commerce JSON data using the custom implementations that you registered.

## Google Analytics data helper classes

> **Info:** You can find the following helper classes in the **CMS.Ecommerce** namespace of the Xperience API.

### GtmProductHelper

Provides the following methods that you can override:

- **MapSKUInternal** – creates data for a specified product (_SKUInfo_).

  - Must return a _GtmData_ object containing the required keys (JSON field names) and values.
  - Customize this method to change the output of the helper's _MapSKU_ method, and the data of products returned by the _MapShoppingCartItems_ method.
- **MapShoppingCartItemsInternal** – creates data for a collection of products representing shopping cart content (_IEnumerable_).

  - Must return an _IEnumerable_ collection of _GtmData_ objects, each containing the required keys (JSON field names) and values.
  - Customize this method to change the output of the helper's _MapShoppingCartItems_ method.

### GtmOrderHelper

Creates data for completed orders (purchases). Customize the methods in this class to change the output of the corresponding _GtmOrderHelper_ methods without the _Internal_ suffix.

Provides the following methods that you can override:

- **MapPurchaseInternal** – creates the overall purchase data for a specified order (_OrderInfo_).

  - Must return a _GtmData_ object containing the required keys (JSON field names) and values.
  - By default calls _MapOrderInternal_ to create the data of the _actionField_ field, and _MapOrderItemsInternal_ to create the data of the _products_ field.
- **MapOrderInternal** – creates data representing a summary of the specified order (_OrderInfo_), including values such as the total revenue, tax, shipping, etc.
  - Must return a _GtmData_ object containing the required keys (JSON field names) and values.
- **MapOrderItemsInternal** – creates data representing all products within the specified order (_OrderInfo_).
  - Must return an _IEnumerable_ collection of _GtmData_ objects, each containing the required keys (JSON field names) and values.

### GtmDataHelper

Performs general serialization of _GtmData_ objects into JSON strings. Affects the final output of methods from both the _GtmProductHelper_ and _GtmOrderHelper_ classes.

You can override the **SerializeToJsonInternal** method – one overload for individual objects (_GtmData_ parameter) and another for collections of objects (_IEnumerable_ parameter).

Customize the _GtmDataHelper_ if you wish to replace or modify the default JSON serialization, which utilizes the _JsonConvert.SerializeObject_ method provided by the _Newtonsoft.Json_ library.

## Creating conditional customizations

If you wish to return different JSON data for specific scenarios, you can use the **purpose** parameter, which is available for all methods of the [Google Analytics data helper classes](#google-analytics-data-helper-classes).

When calling the corresponding methods on your website, set the optional _purpose_ parameter. For example:

```csharp

GtmProductHelper.MapSKU(sku, null, "searchImpressions")

```

You can then evaluate the _purpose_ parameter within the method overrides in your custom helper classes, and branch your code according to the specified purpose.

## Example – Adding coupon data for orders

The following example demonstrates how to customize the Google Analytics JSON data that the system creates for purchases (completed orders). The customization adds the **coupon** field to the _actionField_ object in the purchase data, and sets the value to a comma-separated string containing all [coupon codes](https://docs.kentico.com/13/e-commerce-features/managing-on-line-stores/discounts/working-with-coupon-codes.md) applied to the order.

Prepare an assembly (_Class Library_ project) with class discovery enabled in your Xperience solution (or use an existing one). See [Adding custom assemblies](https://docs.kentico.com/13/custom-development/adding-custom-assemblies.md).

- Reference the project from both your live site and Xperience administration (_CMSApp_) projects.

Continue by creating a custom implementation of the _GtmOrderHelper_ class:

1. Add a new class under the custom project.
2. Make the class inherit from **GtmOrderHelper**.
3. Register the class using the **RegisterCustomHelper** assembly attribute.
4. Override the class's **MapOrderInternal** method and return a **GtmData** object containing data according to your custom requirements:

   ```csharp

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

   using CMS;
   using CMS.Ecommerce;

   // Registers the CustomGtmOrderHelper class to replace the default GtmOrderHelper
   [assembly: RegisterCustomHelper(typeof(CustomGtmOrderHelper))]

   public class CustomGtmOrderHelper : GtmOrderHelper
   {
       /// <summary>
       /// Maps the specified OrderInfo object to a GtmData object, containing data suitable for Google Analytics.
       /// The GtmData object is then serialized into a JSON string, which is returned by the appropriate API method.
       /// </summary>   
       protected override GtmData MapOrderInternal(OrderInfo order, object additionalData = null, string purpose = null)
       {
           if (order == null)
           {
               throw new ArgumentNullException(nameof(order));
           }

           // Adds the default order data
           var customOrderData = new GtmData();
           customOrderData.Add("id", order.OrderID);
           customOrderData.Add("revenue", order.OrderGrandTotal);
           customOrderData.Add("tax", order.OrderTotalTax);
           customOrderData.Add("shipping", order.OrderTotalShipping);

           // Parses the order's coupon code data
           CouponCodeCollection orderCouponCodes = CouponCodeCollection.Deserialize(order.OrderCouponCodes);

           if (orderCouponCodes != null)
           {
               // Gets all coupon codes applied to the order        
               IEnumerable<ICouponCode> appliedCouponCodes = orderCouponCodes.AllAppliedCodes;

               // Creates a comma separated string containing the coupon codes
               string couponString = String.Join(",", appliedCouponCodes.Select(coupon => coupon.Code));

               // Adds the coupon field to the order data
               customOrderData.Add("coupon", couponString);
           }        

           // Merges the custom data with any additional JSON data provided by the additionalData parameter
           customOrderData = GtmPropertiesMerger.Merge(customOrderData, additionalData);

           return customOrderData;
       }
   }

   ```

   > **Tip:** **Calling the base method**
   >
   > The example above fully overrides the default implementation of the _MapOrderInternal_ method. If you only wish to extend the default functionality, you can simplify the customization by calling the base method to create the initial _GtmData_.
   >
   > ```csharp
   >
   > GtmData customOrderData = base.MapOrderInternal(order, additionalData);
   > customOrderData.Add("customField", "customValue");
   >
   > ```
5. Save all changes and **Rebuild** the solution.

The customization ensures that the system sets the **coupon** field when creating the purchase JSON data for orders that contain at least one coupon code. For example, the **GtmOrderHelper.MapPurchase** method could now produce the following JSON output:

```js

{
  "actionField": {
    "coupon": "CouponCode1,CouponCode2",
    "id": 123,
    "revenue": 46.99,
    "shipping": 3,
    "tax": 4
  },
  ... 

```
