Skip to main content
Skip table of contents

GA - Enhanced eCommerce Bridge to JENTIS Data Layer

The Google Tag Managers Data Layer is a very common schema to make data available on a website. And within that the Enhanced Ecommerce data model plays a big role on many shop systems. Thus a best practice is needed to translate that data and make it conveniently accessible to JENTIS Tag Manager. Here comes a short breakdown of the requirements, goals and steps how to implement it in JENTIS.

Please make sure also to read the article on JENTIS Data Layer to understand the basic concept of our internal data layer in JENTIS Tag Manager.

Best Practice

Before you start - beware!

Before considering translating an asynchronous and not directly connected data object you should always check if a direct integration is possible. Thus providing data via _jts.push API method reliably and consistently. With nothin to consider in terms of events out of sync. So this guide is really only relevant, if this best practice of direct communication is not feasible. Only in those scenarios a translation is the second best option.

Data is pushed asynchronously into the data queue “Data Layer”. Where the object itself is an array of event-objects. Every event is pushed to the dataLayer array and the initiators of that push can be any application that are working asynchronously and often not orchestrated. Which is a good thing, as it enables multiple applications to work on the same objective abstractly. However, this asynchronous approach makes reading and organizing data in tracking a bit of a challenge.

Same applies when configuring a tracking with JENTIS. You have to have a concept on when to actually activate a tracking event, such as a “pageview”. Is it to be tracked when the JENTIS JS snippet is initiated? Or do you wan’t you wait for some ecommerce-data to be pushed to the dataLayer object?

That is more complex to answer. It always depends on the whole setup that you should overlook. With JENTIS there are two options to approach this scenario.

a) Create a JENTIS Data Layer when a particular event is pushed to the dataLayer

b) Use a JS Code snippet in JTM to activate the tracking via _jts API (ie. calling track:”submit” to activate the default “JENTIS Datalayer SEND”-State (JENTIS State)).

The option a) is covered in detail here: Data Layer Enhanced Ecommerce Bridge via JENTIS State

However this has one drawback: a new state created means, that you have to look into all individual default triggers and change those to your newly created state, if required.

To make life easier we can go with option b) – where we will just run a function and it will activate the default _jts API. Hence no triggers must be changed. Which we’d suggest is more convenient.

Detailed Description of Translation

This JS function creates a bridge from the global window.dataLayer object. Translating ecommerce data into the JENTIS data model (as defined in the reference: Ecommerce Tracking).

The following ecommerce actions will be translated accordingly from GTM enhanced ecommerce to JENTIS data model:

  • Product Impressions: product, productlist (productlist.name mapped to the first products list property)

  • Product Clicks: product, productlistclick (productlistclick.name mapped to actionField.list property)

  • Product Detail Impressions: product, productview

  • Add To Cart: product, addtocart

  • Remove From Cart: product, removefromcart

  • Promotion Impressions: Not Supported

  • Promotion Clicks: Not Supported

  • Checkout: product, checkout (checkout.step and checkout.option mapped to actionField step and option accordingly)

  • Purchase: product, order– mapping:

    • order.orderid: purchaes.actionField.id

    • order.brutto: purchase.actionField.revenue

    • order.shipping: purchase.actionField.shipping

    • order.vouchers (code): purchase.actionField.code

  • Refunds: Not Supported

The following mapping applies on product level:

  • product.name: products.name

  • product.id: products.id

  • product.group: products.category

  • product.brutto: products.price

  • product.brand: products.brand

  • product.quantity: products.quantity or default to 1 if not set

  • product.position: products.position

  • product.variant: products.variant

Where the product is read from the according enhanced ecommerce events array.

Ecommerce Code Snippet

With the following code snippet you can activate a translation of enhanced ecommerce data schema to the JENTIS data model.

This guide is following the Google Tag Manager enhanced ecommerce integration documentation.

So the foundation is a proper use of this data schema. Only in those situations the translation will work out of the box!

To add a code snippet to a JTM container you must navigate to the “Components” – “Codes” section and click the “+”-icon to add a new element. For details of this process please see the according manual: Code Snippets

In the JavaScript Function text input field you can copy paste the following section.

JS
//define events to listen to as single String values in array
//keep empty to listen to all events
var RELEVANT_EVENTS = ["ecommerce"];
var DISCOVERY_TYPE  = "parameter_key"; //either by event_name matching or existing parameter_key

var dl = window.dataLayer || [];
if(Array.isArray(dl) && dl.length && dl.length > 0) {
    dl.forEach(arrayItem => {
          if(DISCOVERY_TYPE == "event_name")
          initiateRelevantStates(arrayItem.event, arrayItem);
        else if(DISCOVERY_TYPE == "parameter_key")
          initiateRelevantStates(arrayItem[RELEVANT_EVENTS[0]] ? RELEVANT_EVENTS[0] : undefined, arrayItem);
    })
}

var originalPush = dl.push;
dl.push = function(args){
    originalPush.call(window["dataLayer"], args);
    if(DISCOVERY_TYPE == "event_name")
      initiateRelevantStates(args.event, args);
    else if(DISCOVERY_TYPE == "parameter_key")
      initiateRelevantStates(args[RELEVANT_EVENTS[0]] ? RELEVANT_EVENTS[0] : undefined, args);
}
window.dataLayer = dl;

function initiateRelevantStates(match_key, eec_object){
    if(Array.isArray(RELEVANT_EVENTS) && 
       RELEVANT_EVENTS.length > 0 &&
       typeof match_key != "undefined" &&
       typeof eec_object != "undefined"){
        if(RELEVANT_EVENTS.includes(match_key)){
            try{
                dl_eec_transform(eec_object);
            } catch(e){console.log(e);}
        } else {
          }
      } else if(typeof event_name != "undefined" &&
              typeof eec_object != "undefined"){
        try{
            dl_eec_transform(eec_object);
        } catch(e){console.log(e);}
    }
}

//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.name  = "";
        jtsProds          = dl_eec.ecommerce.impressions;
        if(Array.isArray(dl_eec.ecommerce.impressions) && dl_eec.ecommerce.impressions[0].list)
            jtsTrackObj.name = dl_eec.ecommerce.impressions[0].list;
    }
    else if(checkObject(dl_eec,["ecommerce","click", "products"])){
        jtsTrackObj.track = "productlistclick";
        jtsTrackObj.name  = "";
        jtsProds          = dl_eec.ecommerce.click.products;
        if(dl_eec.ecommerce.click.actionField && dl_eec.ecommerce.click.actionField.list)
            jtsTrackObj.name = dl_eec.ecommerce.click.actionField.list;
    }
    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;
        jtsProds             = dl_eec.ecommerce.checkout.products;

    }
    else if(checkObject(dl_eec,["ecommerce","purchase","actionField"])){
        jtsTrackObj.track    = "order";
        jtsTrackObj.vouchers = [{"code": dl_eec.ecommerce.purchase.actionField.coupon}];
        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 ? product.quantity : 1,
                "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);
  
    _jts.push({"track":"submit"})
}

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;
        }
    }
}

The JENTIS Data Layer is our data schema to describe all events and objects that you can use to enhance your onsite intelligence systems and advertising. The schema of the data layer describes the context, structure and organization of the data contained on site and its items (ie. products). For instance, the data layer can include information about the page, user, session, or any specific event information like product details in an eCommerce transaction. Learn more here: JENTIS Data Layer

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.