Google Analytics and the Enhanced Ecommerce (EEC) Data Model are both very common in the online marketing world. Therefore we created this guide to quickly migrate an existing EEC implementation to the Jentis data model. With this you will be able to be up and running in short time.

Prerequisites: you have a website where the data related to product detail view, add to cart, purchase, etc. information is implemented to a Data Layer object following the official guide. As documented here: https://developers.google.com/tag-manager/enhanced-ecommerce

This plug&play solution will translate the following EEC interactions:

  • product list impressions

  • product list clicks

  • product details

  • add to basket

  • remove from basket

  • checkout

  • purchase

The steps to create this plug&play solution are:

  1. Create a custom JTM State to listen to all window.dataLayer events that contain EEC data.

  2. Update and customize server side Tags and Triggers if required.

Data Layer EEC Data to JTM States

The most important part is to listen to all events pushed into a Data Layer queue. Every time a relevant event is pushed with EEC data the JTM needs to react. Meaning a translation operation from the EEC data model to the Jentis data model (see reference here: https://my.jentis.com/integration/E-Commerce-Tracking.721073.html ).

To add this State to your JTM account navigate to Components > States.

Now add a new State object with the following configuration.

Custom State Name: DataLayer Ecommerce Event States

Customize this part of the code:

  • line 4: Add here String values of the event names as used in your setup, ie. if the product detail information is added with a “eec.detailimpression” event push dataLayer.push({event:'eec.detailimpression'}); )

With this code you will have all EEC interactions that exist and follow the EEC standard (as defined above) it will automatically translate into the Jentis Data Model. Now you only will need to adjust your tags triggers and are good to go, see the next steps below.

function(initState){
  	//define events to listen to as single String values in array
	//keep empty to listen to all events
	var RELEVANT_EVENTS = ["eec.detailimpression",
                           "eec.addtocart",
                           "eec.purchase"]; 
  
	var dl = window.dataLayer || [];
	if(Array.isArray(dl) && dl.length && dl.length > 0) {
		dl.forEach(arrayItem => {
			initiateRelevantStates(arrayItem.event, arrayItem);
		})
	}

	var originalPush = dl.push;
	dl.push = function(args){
		initiateRelevantStates(args.event, args);
		originalPush.call(window["dataLayer"], args);
	}
    window.dataLayer = dl;

	function initiateRelevantStates(event_name, eec_object){
		if(Array.isArray(RELEVANT_EVENTS) && 
		   RELEVANT_EVENTS.length > 0 &&
		   typeof event_name != "undefined" &&
		   typeof eec_object != "undefined")
			if(RELEVANT_EVENTS.includes(event_name))
				dl_eec_transform(eec_object);
      		else
                console.log("JTM Data Layer Event States: non relevant event - no state initialized");
		else if(typeof event_name != "undefined" &&
				typeof eec_object != "undefined")
			dl_eec_transform(eec_object);
	}


	//JTS DataLayer Ecommerce Transformer
	function dl_eec_transform(dl_eec) {
		var jtsTrackObj = {};
		var jtsProds    = [];
		if(checkObject(dl_eec,["ecommerce","add"])){
			jtsTrackObj.track = "addtocart";
			jtsProds          = dl_eec.ecommerce.add.products;
		}
		else if(checkObject(dl_eec,["ecommerce","remove"])){
			jtsTrackObj.track = "removefromcart";
			jtsProds          = dl_eec.ecommerce.remove.products;
		}
		else if(checkObject(dl_eec,["ecommerce","detail"])){
			jtsTrackObj.track = "productview";
			jtsProds          = dl_eec.ecommerce.detail.products;
		}
		else if(checkObject(dl_eec,["ecommerce","impressions"])){
			jtsTrackObj.track = "productlist";
			jtsTrackObj.listname = "";
			jtsProds          = dl_eec.ecommerce.impressions;
		}
		else if(checkObject(dl_eec,["ecommerce","click"])){
			jtsTrackObj.track = "click";
			jtsProds          = [];
		}
		else if(checkObject(dl_eec,["ecommerce","checkout","actionField"])){
			jtsTrackObj.track    = "checkout";
			jtsTrackObj.step     = dl_eec.ecommerce.checkout.actionField.step;
			jtsTrackObj.option   = dl_eec.ecommerce.checkout.actionField.option;

		}
		else if(checkObject(dl_eec,["ecommerce","purchase","actionField"])){
			jtsTrackObj.track    = "order";
			jtsTrackObj.orderid  = dl_eec.ecommerce.purchase.actionField.id;
			jtsTrackObj.brutto   = dl_eec.ecommerce.purchase.actionField.revenue;
			jtsTrackObj.shipping = dl_eec.ecommerce.purchase.actionField.shipping;
			jtsProds             = dl_eec.ecommerce.purchase.products;

		}

		//transform products
		if(jtsProds && Array.isArray(jtsProds))
			jtsProds.forEach(function(product){
              var jts_product = {
					"track"		:   "product",
					"type"		:   jtsTrackObj.track,
					"id"        :   product.id,
					"name"      :   product.name,
					"group"     :   [product.category],
					"brutto"    :   product.price,
					"brand"     :   product.brand,
					"quantity"  :   product.quantity,
					"position"  :   product.position,
                    "variant"   :   product.variant
				};
              for(var i = 1; i <= 200; i++)
                if(product["dimension"+i])
                  jts_product["dimension"+i] = product["dimension"+i];
              
              _jts.push(jts_product);
			})

		_jts.push(jtsTrackObj);

		if(jtsTrackObj.track)
			initState();
	}

	function checkObject(object,aSplit,counter) {
		if(typeof counter === "undefined") {
			counter = 0;
		}

		if(aSplit.length === counter) {
			return object;
		} else {
			if(typeof object[aSplit[counter]] !== "undefined") {
				return checkObject(object[aSplit[counter]],aSplit,++counter);
			} else {
				return null;
			}
		}
	}
}
JS

Configure Tags and Triggers

The State created in the previous step will activate the data tracking on the frontend. On the server side you can use all existing Backend Variables to configure the usage of the values as you need them. Because this approach will leverage the existing Jentis data model you don’t need to create any special variable in the JTM setup. All is setup by default.

Now we will go ahead and use this pieces of the puzzle to complete the tracking with Google Analytics tags. To have it as simple as possible we simply take the default GA tags that are installed automatically when the GA tracker object is created in a JTM account. But first we need to create triggers that are based on our custom State (from the previous step).

Navigate to the Server Tag Manager > Trigger section and duplicate an existing trigger matching your interaction, ie. “AddToCart” default trigger from JTM. Edit the copy of the trigger to listen to the new State (from DataLayer event).

You only need to change the “State” to the new State from the previous step and save it.

Now let's setup the according ‘addToCart’ tag. Navigate to Server Tag Manager > Tags area and select the GA tag for this interaction.

Change the trigger of the tag to the one created in the step before. Save the changes and you are good to go.

Apply this logic to all EEC interactions (detail view, purchase, etc):

  • copy existing trigger and change the State to the new Data Layer Event State

  • adjust the according tag to activate with the new trigger

You are now ready to preview all this parts. Make sure to check if all data appears as expected with the preview monitor.