# Enhanced E-Commerce Data Layer Bridge (GTM to JENTIS)

## Enhanced Ecommerce Data Layer Bridge (GTM to JENTIS)

Many websites already use the Google Tag Manager (GTM) Data Layer with the Enhanced Ecommerce schema. This article provides a best practice guide for translating GTM Enhanced Ecommerce data into the JENTIS Data Layer model.

> ⚠️ **Important:** Direct integration via `_jts.push` is always preferred. Only use this bridge if direct integration is not feasible.

### Use Case

Enhanced Ecommerce data is often pushed asynchronously into the `window.dataLayer` object. However, tracking based on such data requires special handling since the data appears at unpredictable times.

To bridge this gap, JENTIS allows you to convert GTM’s Enhanced Ecommerce schema to its own structured data layer format.

### Translation Options

There are two ways to handle event tracking in JENTIS based on GTM's `dataLayer`:

#### Option A: Use a Custom JENTIS State

* Create a new **State** in JENTIS Tag Manager.
* Trigger this state when a specific event appears in `dataLayer`.
* Drawback: You must update all triggers using this state.

#### ✅ Option B: Use a JS Code Snippet (Recommended)

* Add a JS snippet in the "Codes" section in JENTIS.
* It listens to `dataLayer.push` events and automatically triggers `_jts.push()` with the translated data.
* No need to update any triggers.

### Supported Translations

#### Ecommerce Actions

| GTM Enhanced Ecommerce Event   | JENTIS Equivalent             |
| ------------------------------ | ----------------------------- |
| `impressions`                  | `product`, `productlist`      |
| `click`                        | `product`, `productlistclick` |
| `detail`                       | `product`, `productview`      |
| `add`                          | `product`, `addtocart`        |
| `remove`                       | `product`, `removefromcart`   |
| `checkout`                     | `product`, `checkout`         |
| `purchase`                     | `product`, `order`            |
| `promotion` (impression/click) | ❌ Not supported               |
| `refund`                       | ❌ Not supported               |

#### Product Field Mapping

| GTM Field  | JENTIS Field |
| ---------- | ------------ |
| `id`       | `id`         |
| `name`     | `name`       |
| `category` | `group`      |
| `price`    | `brutto`     |
| `brand`    | `brand`      |
| `quantity` | `quantity`   |
| `position` | `position`   |
| `variant`  | `variant`    |

Purchase metadata (from `actionField`) is also mapped accordingly (e.g., `id`, `revenue`, `shipping`, `coupon`).

***

### Installation Steps

#### Step 1: Add a Code Snippet in JENTIS

1. Go to **Components > Codes** in the JENTIS Tag Manager.
2. Click `+` to add a new JavaScript function.
3. Paste the complete code snippet provided in this article.
4. Save and publish.

### Code Snippet

```javascript
//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;
        }
    }
}
```

(For brevity, see the full implementation in the downloadable JS file or copy it directly from the docs.)

### Notes

* This bridge activates JENTIS tracking via `_jts.push()` and triggers a `track: "submit"` automatically.
* The script ensures compatibility with most Enhanced Ecommerce implementations.
* To support custom fields (e.g., `dimension1` to `dimension200`), the script copies these if present.

***

### Further Reading

* [Set Up JENTIS Data Layer](/data-capture/web-tracking-setup/set-up-jentis-data-layer.md)
* [E-Commerce Tracking](/data-capture/web-tracking-setup/set-up-jentis-data-layer/e-commerce-tracking.md)
* [Codes](/jentis-dcp-elements/codes.md)

***

### Product Statement

This Enhanced Ecommerce bridge script is a JENTIS-built compatibility layer to support existing GTM-based implementations. While JENTIS recommends a native `_jts.push` approach for maximum performance, this solution allows seamless migration and enhanced flexibility for complex or legacy tracking environments.

Use this feature to accelerate adoption of the JENTIS Tag Manager while maintaining consistency with your existing GTM structure.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.jentis.com/data-capture/web-tracking-setup/set-up-gtm-data-layer/enhanced-e-commerce-data-layer-bridge-gtm-to-jentis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
