Matomo ecommerce tracking: The Complete Guide

Written by:  Photo de profil de Lucas Rollin Lucas Rollin

Updated: Saturday, December 30, 2023

Why implement Matomo e-commerce tracking?

E-commerce tracking is data collection of the entire visitor’s buying journey. Matomo Analytics is one of the web analysis tools offering advanced e-commerce tracking.

In Matomo, e-commerce tracking gives you access to the following data:

  1. Category view
  2. Product view
  3. Number of abandoned carts and their content
  4. Ordered products (by ID, name and category)
  5. Sales by :
    • referring sites
    • page
    • geographic location
    • browser
    • device type
    • channel (conversion attribution)
    • etc.
  6. Number of visits or days required to get a conversion
  7. User journey leading to purchase

Enable Matomo e-commerce reports

Go to Settings > Websites > Manage.

Then click on the Edit button on the website you wish to activate e-commerce reports.

Website editing in Matomo
Website editing in Matomo

Then scroll down to the e-commerce section and select E-commerce enabled.

Ecommerce enabled in Matomo
Ecommerce enabled in Matomo

This gives you access to the e-commerce reports available in the left-hand side menu:

Matomo e-commerce reports
Matomo e-commerce reports

Overview

The diagram below shows how Matomo e-commerce tracking works in general. In this article, we’ll look at what data Matomo expects for each interaction, so that you can feed your e-commerce reports correctly and make the most out of your data.

flowchart TD
    E[Matomo instance]
    subgraph Browser
        direction TB
        A["Products/categories view"]
        B["Add to cart"]
        C["Remove from cart"]
        F["Get cart content"]
        D((Matomo \n cart object))
        G["Delete from cart"]
        H(["trackEcommerceCartUpdate()"])
        I(["trackPageView()"])
        J(["trackEcommerceOrder()"])
    end
    B -- "addEcommerceItem()" --> D
    C -- "removeEcommerceItem()" --> D
    D -- "getEcommerceItems()" --> F
    G -- "clearEcommerceCart()" --> D
    D --> H
    H -- HTTP --> E
    D --> J
    J -- HTTP --> E
    A -- "setEcommerceView()" --> I
    I -- HTTP --> E

Category views

flowchart LR
    E[Matomo instance]
    subgraph Browser
        direction TB
        A["Products/categories view"]
        I(["trackPageView()"])
    end
    A -- "setEcommerceView()" --> I
    I -- HTTP --> E

setEcommerceView

ParameterValue typeValue example
Product categorySTRING OR Array(STRING)"Books" or ["Books", "Adventure"]
_paq.push(['setEcommerceView',
    false, // The product name must be false for a category view.
    false, // Product SKU must be false for a category view.
    "Books", // (Optional) Product category or an array of up to 5 categories.
]);

// You must call the trackPageView function to send the request to Matomo
_paq.push(['trackPageView']);

Product views

flowchart LR
    E[Matomo instance]
    subgraph Browser
        direction TB
        A["Products/categories view"]
        I(["trackPageView()"])
    end
    A -- "setEcommerceView()" --> I
    I -- HTTP --> E

setEcommerceView

ParameterValue typeRequiredExample value
Product identifier (SKU)STRINGYES"1234"
Product nameSTRINGNO"Percy Jackson"
Product categorySTRINGNO["Books", "Adventure"]
Product priceINTEGER OR FLOATNO9.99
_paq.push(['setEcommerceView',
    "1234", // (Required) Product identifier (SKU)
    "Percy Jackson", // (Optional) Product name
    ["Books", "Adventure"], // (Optional) Product category or an array of up to 5 categories.
    9.99 // (Optional) Product price
]);

// You need to call the trackPageView function to send the request to Matomo
_paq.push(['trackPageView']);

Add to cart

flowchart LR
    subgraph Browser
        direction LR
        B["Add to cart"]
        D((Matomo \n cart object))
    end
    B -- "addEcommerceItem()" --> D

Unlike Google Analytics 4, Matomo doesn’t add up the products added to cart - you have to provide it with the current cart state. Matomo uniquely identifies the products in the cart with their SKU.

If you add the same product (same SKU) twice, the quantity will not be added, but the product will be completely replaced.

At first glance, this may seem illogical, but it’s simply a different way of looking at things compared to GA4.

If you’re using GA4’s Data Layer, the current state of the cart may not be available at the time of the add_to_cart event. Before dealing with this, let’s take a look at how add to cart works with Matomo’s tracking code.

addEcommerceItem

This function updates the current state of the cart. Used on its own, it does not send any requests to Matomo. It creates a cart object locally in the user’s browser.

ParameterValue typeRequiredExample value
Product identifier (SKU)STRINGYES"1234"
Product nameSTRINGNO"Percy Jackson"
Product categorySTRINGNO["Books", "Adventure"]
Product priceINTEGER OR FLOATNO9.99
Product quantityINTEGERNO5
_paq.push(['addEcommerceItem',
    "1234", // (Required) Product identifier (SKU)
    "Percy Jackson", // (Optional) Product name
    ["Books", "Adventure"], // (Optional) Product category or an array of up to 5 categories.
    9.99, // (Optional) Product price
    5 // (Optional) Product quantity (default is 1)
]);

The cart object represents the current cart state according to Matomo. This object is accessible via the getEcommerceItems() method.

trackEcommerceCartUpdate

flowchart LR
    E[Matomo instance]
    subgraph Browser
        direction LR
        D((Matomo \n cart object))
        H(["trackEcommerceCartUpdate()"])
    end
    D --> H
    H -- HTTP --> E

This function enables Matomo’s abandoned cart feature. It sends a request to Matomo specifying the current cart value. This value is not dynamically calculated from the prices and quantities of the products you’ve added via addEcommerceItems(). To solve this problem, you must either have access to this data in the Data Layer or use the getMatomoTotalCartValue() function.

ParameterValue typeRequiredExample value
Basket valueINTEGER or FLOATYES49.95
_paq.push(['trackEcommerceCartUpdate', 49.95]); 

Remove from cart

This function takes in the identifier (SKU) of the product to be removed from the cart. Note that the product is completely removed from the Matomo cart object, regardless of its quantity.

No requests are sent to Matomo when this function is called.

ParameterValue typeValue example
Product identifier (SKU)INTEGER1234
_paq.push(["removeEcommerceItem", 1234]); 
// replace 1234 with the SKU of the product you 
// wish to remove from the cart object

Cart object content

flowchart LR
    subgraph Navigateur
        direction LR
        F["Get cart content"]
        D((Matomo \n cart object))
    end
    D -- "getEcommerceItems()" --> F

getEcommerceItems

This function returns a Javascript object of arrays in which each array corresponds to a product in the cart object.

Matomo.getAsyncTracker().getEcommerceItems();

Here’s an example of the result with two products previously added to the cart:

Return example of Matomo's getEcommerceItems function
Return example of Matomo's getEcommerceItems function

Delete cart object

clearEcommerceCart

This function takes no parameters and completely removes the cart object from Matomo.

_paq.push(["clearEcommerceCart"]);

Orders

flowchart LR
    E[Instance Matomo]
    subgraph Navigateur
        direction LR
        D((Matomo \n cart object))
        J(["trackEcommerceOrder()"])
    end
    D --> J
    J -- HTTP --> E

trackEcommerceOrder

This function sends order details to Matomo. It also calls the clearEcommerceCart() function, which resets the cart object at the same time.

ParameterValue typeRequiredExample value
Order idSTRINGYES"1234"
Total (revenue)INTEGER OR FLOATYES49.95
Sub-TotalINTEGER OR FLOATNO9.99
TaxINTEGER OR FLOATNO1.5
ShippingINTEGER OR FLOATNO1
DiscountINTEGER OR FLOATNO5
_paq.push(['trackEcommerceOrder',
    "1234", // (Required) Order id
    49.95, // (Required) Total (revenue)
    9.99, // (Optional) Subtotal
    1.5, // (optional) Tax
    1, // (optional) Shipping
    5 // (optional) Discount
]);

Utility functions

parseFloat

This native function lets you transform a STRING into a FLOAT.

parseFloat("9.99"); // => 9.99

getMatomoTotalCartValue

I’ve created the getMatomoTotalCartValue() function to get the cart object’s total without needing this data in the Data Layer and thus take advantage of Matomo’s abandoned cart feature with trackEcommerceCartUpdate().

function getMatomoTotalCartValue() {
    let cart = [];
    if(Matomo) {
        cart = Object.entries(Matomo.getAsyncTracker().getEcommerceItems());
    }
    var total = 0;
    cart.forEach(product => {
        total += product[1][3]*product[1][4];
    });
    return total;
}

_paq.push(['addEcommerceItem',
    "1234", // (Requuired) Product identifier (SKU)
    "Percy Jackson", // (Optional) Product name
    ["Books", "Adventure"], // (Optional) Product category or an array of up to 5 categories.
    9.99, // (Optional) Product price
    5 // (Optional) Product quantity (default is 1)
]);

_paq.push(['trackEcommerceCartUpdate', getMatomoTotalCartValue()]);