Unable to fetch enhanced ecommerce dataLayer values

I’m trying to translate GTM/UA enhanced ecommerce dataLayer values to dataLayer variables to build a Piwik-compatible ecommerce transaction tag. I’ve added the dataLayer variables to the tag manager, but the values are still ‘undefined’.

This is the content of my GTM/UA dataLayer after a successful donation:

{
  "event": "donatie",
  "ecommerce": {
    "purchase": {
      "actionField": {
        "id": 8015,
        "revenue": 50,
        "list": "Gift",
        "option": "Ideal",
        "tax": "0",
        "step": 4,
        "shipping": 0
      },
      "products": [
        {
          "name": "Fonds noodzakelijke hulp",
          "id": "MOST",
          "price": 50,
          "brand": "",
          "category": "Fondsgift",
          "variant": "One-time",
          "quantity": 1
        }
      ]
    }
  }
}

I added these two dataLayer variables to the Tag Manager:

For the order_id:

ecommerce.purchase.actionField.id

For the grand_total:

ecommerce.purchase.actionField.revenue

In the debugger I see this:
Screenshot 2022-02-07 120354

The tranaction is loaded into the dataLayer when an event is firing.

Hi, thanks for reaching out. Unfortunately, it’s not possible to refer to nested attributes of a datalayer object directly. You could use a PPTM datalayer variable, but you would need to fetch the whole ecommerce object and then iterate through on the custom HTML tag level. It would look roughly like this:

    var orderDetails = {{ ecommerce object }};
    var order_id = orderDetails.purchase.actionField.id
    var grand_total = orderDetails.purchase.actionField.revenue
 

{{ ecommerce object }} is a PPTM datalayer variable ecommerce.

Please see this thread for complete code snippet examples for similar data layer objects.

Hi @pslonina, thanks for helping me out here. Really appreciate it! :wink: I got this far:

<script>
    var _paq = _paq || [];
    var orderDetails = {{ ecommerce object }};
    var order_id = orderDetails.purchase.actionField.id;
    var grand_total = orderDetails.purchase.actionField.revenue;
    var tax = orderDetails.purchase.actionField.tax;
    var products = orderDetails.purchase.products;
    var product.id = orderDetails.purchase.products.sku;
    var product.name = orderDetails.purchase.products.name;
    var product.category = orderDetails.purchase.products.category;
    var product.price = orderDetails.purchase.products.price;
    var product.quantity = orderDetails.purchase.products.quantity;
    
    products.forEach(function(product){
    _paq.push(["addEcommerceItem", product.id, product.name, product.category, product.price, product.quantity])
  	});
    _paq.push(["trackEcommerceOrder",order_id, grand_total]);
  </script>

But I think I’m missing something here, because this results in a JS error:

Uncaught SyntaxError: Unexpected token '.'

Any idea what I might be doing wrong here?

I’ve allowed myself to add some tweaks here and there:

<script>
    var _paq = _paq || [];
    var orderDetails = {{ ecommerce object }};
    var products = orderDetails.purchase.products;
    var order_id = orderDetails.purchase.actionField.id;
    var grand_total = orderDetails.purchase.actionField.revenue;
	var tax = parseInt(orderDetails.purchase.actionField.tax);
	var shipping = orderDetails.purchase.actionField.shipping;
  	

    products.forEach(function(product){
      _paq.push(["addEcommerceItem",product.id.toString(), product.name, product.category, product.price, product.quantity])
  
  });
    _paq.push(["trackEcommerceOrder",order_id, grand_total,, tax, shipping,]);
  </script>

Please note:

  1. I’ve used parseInt() to change tax from string to number;
  2. You don’t need to capture product attributes since we are operating on the whole products objects.

Please give it a try and let me know if it works :slight_smile:

Great! Thanks, @pslonina! Works like a charm.

1 Like

Additional question on what you said:

The GA enhanced ecommerce dataLayer contains more details about the transaction. On a product level there’s brand and variant, on purchase level there’s list and option. We currently use these variables in our reporting. Is there any way I could capture these and use them as custom dimensions?

Hi @michiel , most definitely!
On the product level, you could utilize Category placeholder (please find more details here). I know that it’s not exactly the same as brand or variant, but it is an additional product-level attribute.

As for purchase level - custom dimensions in the scope of an event are the way to go. Please declare them first in Piwik PRO following this article. Once that’s done - please use the following method to set custom dimension value:

_paq.push(['setCustomDimensionValue', 1, 'dimensionValue']);

Please make sure to set custom dimension values before sending the e-commerce event.

1 Like

Hey @pslonina, I just ran into another challenge with ecommerce. We’re running a Woocommerce based webshop with the WooCommerce Google Analytics extension to track cart actions and purchases. I’m trying to translate this plugin’s dataLayer purchase event to Piwik, but I can’t get this to work. The dataLayer looks a bit different:

    {
        "0":"event",
        "1":"purchase",
        "2":{
            "transaction_id":"15780",
            "affiliation":"Compassion Cadeaus",
            "value":"90.00",
            "tax":"0",
            "shipping":"0",
            "currency":"EUR",
            "items":[
                {
                    "id":"14088",
                    "name":"Onderdak",
                    "category":"Noodhulp",
                    "price":"90",
                    "quantity":"1"
                }
            ]
        }
    }

I’m guessing the formatting declaring the event causes this? Is it possible to still use this dataLayer to make it work for Piwik PRO?

Hi @michiel ,
My apologies for the late reply. You are right - the issue is the formatting and there is no simple way of addressing it from Piwik PRO level.

Is it possible to configure the plugin so it sends a key-value pair "event": "purchase"? If not - maybe there are alternative plugins that would build dataLayer objects for WooCommerce?

Hey @pslonina,
I found another plugin (GTM4WP) that constructs dataLayer events in a correct way. I’m working on getting the add_to_cart event working, but I think I’m getting it wrong.

This is an example dataLayer for the add_to_cart event:

{
  "event": "add_to_cart",
  "ecommerce": {
    "currency": "EUR",
    "value": "8.95",
    "items": [
      {
        "item_id": "120730",
        "item_name": "Herbruikbare rietjes - Strawies®",
        "item_brand": "",
        "price": "8.95",
        "item_category": "Cadeautjes",
        "quantity": 1,
        "google_business_vertical": "retail",
        "id": "120730"
      }
    ]
  },
  "gtm.uniqueEventId": 24
}

And this is the tag I’m working with:

<script>
  var _paq = _paq || [];
  var orderDetails = {{ DLV | Ecommerce }}
  var products = orderDetails.items;
  
  products.forEach(function(product){
    _paq.push(['addEcommerceItem', product.id.toString(), product.name, product.category, product.price, product.quantity])
  });
</script>

Unfortunately, this results in a JavaScript error (Uncaught ReferenceError: ecommerce is not defined). I tried several other options, but none of them seems to work.

EDIT
I changed the tag a bit and resolved the JS error, but the add_to_cart event still isn’t pushed to Piwik correctly.

Hope you can point me in the right direction!

Hi @michiel,
Please use the following code:

<script>
    var _paq = _paq || [];
    var orderDetails = {{ ecommerce object }};
    var products = orderDetails.items;
    var grand_total = parseFloat(orderDetails.value);

    products.forEach(function(product){
      _paq.push(["addEcommerceItem",product.item_id, product.item_name, product.item_category, product.price, product.quantity])    
  	});
  
    _paq.push(["trackEcommerceCartUpdate", grand_total]);  
</script>

I’ve run a quick test and it looks good:

image

Please let me know if it worked for you too :slight_smile:

Thanks!
Piotr

Thanks, works like a charm! The only thing that doesn’t seem to work is updating the total cart value: adding a new item to the cart changes the value of the cart to the last added item:

I guess this has more to do with the dataLayer? The value in the dataLayer doesn’t calculate the sum of the price of the products added to the cart. Is there any way to make that calculation?

EDIT
The view_cart event does update the total cart value:
Screenshot 2022-03-08 091831

Hi @michiel,
please use this script instead of the last one:

<script>
    var _paq = _paq || [];
    var orderDetails = {{ ecommerce object }};
    var products = orderDetails.items;
	var total_price = 0
  	var prices = []
	products.forEach(function(product){
    	prices.push((product.price*product.quantity).toFixed(2));
	});

   for(var i=0; i < prices.length; i++){
        total_price += prices[i];  	
	}   
   
    products.forEach(function(product){
      _paq.push(["addEcommerceItem",product.item_id, product.item_name, product.item_category, product.price, product.quantity])
       
  });
  
       _paq.push(["trackEcommerceCartUpdate", total_price.toString()]);

  </script>

It will calculate the total value based on the prices of the items.

Please let me know if that helped.
Thanks,
Piotr

EDIT: I’ve tweaked the code above a bit.

Thanks for your help, @pslonina!

It’s strange, but I get mixed results with the add_to_cart event.

Product overview page
On the product overview page I can add a single product if the product doesn’t have any options to choose from. If I add such a product to the cart, I get a Cart update event in the tracker debugger with the correct product, quantity and price. From the overview page, I can only add 1 item to the cart.

Tracker debugger
Screenshot 2022-03-11 164704

Tag manager debugger add_to_cart event

Product detail page
If I add a product to the cart from a product detail page, I can see the add_to_cart tag fires, but it doesn’t register an event in the tracker debugger. I tested this with ánd without the option to prevent page reload in the tag manager debug mode.

In the tag manager debugger I still see the add_to_cart event, including the right details for the cart update. In the example below I added 4 chocolate bars to the cart with a total value of 26 EUR, which add the following to the dataLayer:

I’m kinda lost here… Any suggestions? :wink:

Hi @michiel,
Is it possible to take a look at the actual website?

Thanks,
Piotr

Hi @pslonina, sure! I linked the pages in the ‘subtitles’ of my last comment, but that was not really obvious… :wink:

You can find the webshop here.

Oh, it was right there for the whole time :smiley: Thanks!

I was able to pinpoint the problem. So the thing is that for Product overview page, product quantities are numbers while for Product detail page product quantities are string. Therefore you need to use parseFloat() in order to convert them to numbers. Please see the code below:

<script>
  var _paq = _paq || [];
  var orderDetails = {{ DLV | Ecommerce }};
  var products = orderDetails.items;
  var grand_total = parseFloat(orderDetails.value);
  
  products.forEach(function(product){
    _paq.push(["addEcommerceItem", product.item_id, product.item_name, product.item_category, product.price, parseFloat(product.quantity)])    
  	  });
    _paq.push(["trackEcommerceCartUpdate", grand_total]);
</script>

Please let me know did it go :wink:

Best,
Piotr

Yes, this works! Thanks!

A post was split to a new topic: Product scoped custom dimensions