---
title: Customizing e-commerce data for Google Analytics
related:
  - https://docs.kentico.com/k12sp/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce-on-mvc-sites.md
  - https://docs.kentico.com/k12sp/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce.md
  - https://docs.kentico.com/k12sp/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 Kentico, the system provides methods in the API, macros and transformations that return JSON data for products and orders in a suitable format. For more information, see [Integrating Google Analytics Enhanced Ecommerce on MVC sites](https://docs.kentico.com/k12sp/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce-on-mvc-sites.md) or [Integrating Google Analytics Enhanced Ecommerce](https://docs.kentico.com/k12sp/e-commerce-features/customizing-on-line-stores/integrating-google-analytics-enhanced-ecommerce.md) (for Portal Engine sites).

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. Open your Kentico project in Visual Studio.
2. Create a custom class that inherits from one of the [Google Analytics data helper classes](#google-analytics-data-helper-classes).

   > **Tip:** **Class location**
   >
   > We recommend adding custom classes as part of a new assembly (Class library project) in your Kentico solution. You need to add the appropriate references to both the assembly and the main Kentico web project.
3. Override the methods of the helper class according to your custom requirements.
4. [Register](https://docs.kentico.com/k12sp/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 Kentico 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 _GetGtmProductJson_ macro and transformation method, and the data of products returned by the _GetGtmShoppingCartItemsJson_ macro method.
- **MapShoppingCartItemsInternal** – creates data for a collection of products representing shopping cart content (_IEnumerable\<ShoppingCartItemInfo>_).

  - 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 _GetGtmShoppingCartItemsJson_ macro method.

### GtmOrderHelper

Creates data for completed orders (purchases). Customize the methods in this class to change the output of the _GetGtmPurchaseJson_ macro method.

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\<GtmData>_ 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 macro or transformation methods on your website, set the optional _purpose_ parameter. For example:

```csharp

{% GetGtmProductJson(SKUID, "", "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/k12sp/e-commerce-features/managing-on-line-stores/discounts/working-with-coupon-codes.md) applied to the order.

Start by preparing a separate project for custom classes in your Kentico solution:

1. Open your Kentico solution in Visual Studio.
2. Create a new _Class Library_ project in the Kentico solution  (or reuse an existing custom project).
3. Add references to the required Kentico libraries (DLLs) for the new project:

   1. Right-click the project and select **Add -> Reference**.
   2. Select the **Browse** tab of the **Reference manager** dialog, click **Browse** and navigate to the  _**Lib**_  folder of your Kentico web project.
   3. Add references to the following libraries (and any others that you may need in your custom code):

      - **CMS.Base.dll**
      - **CMS.Core.dll**
      - **CMS.DataEngine.dll**
      - **CMS.Ecommerce.dll**
4. Reference the custom project from the Kentico web project _(CMSApp_ or _CMS)_.
5. Edit the custom project's **AssemblyInfo.cs** file (in the _Properties_ folder).
6. Add the **AssemblyDiscoverable** assembly attribute:

   ```csharp

   using CMS;

   [assembly:AssemblyDiscoverable]

   ```

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 macro or 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 **Build** the custom project.

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 **GetGtmPurchaseJson** macro method could now produce the following JSON output:

```js

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

```
