Skip to main content

Matomo

Web Source code Package Beta

Matomo is an open-source, privacy-focused web analytics platform that works self-hosted or in Matomo Cloud. This destination forwards walkerOS events to Matomo via the _paq command queue with support for page views, custom events, ecommerce, goals, site search, content tracking, and custom dimensions.

Where this fits

Matomo is a web destination in the walkerOS flow:

Installation

npm install @walkeros/web-destination-matomo
import { startFlow } from '@walkeros/collector';
import { destinationMatomo } from '@walkeros/web-destination-matomo';

await startFlow({
destinations: {
  matomo: {
    code: destinationMatomo,
    config: {
      loadScript: true,
      settings: {
        siteId: '1',
        url: 'https://analytics.example.com/',
      },
    },
  },
},
});

Configuration

This destination uses the standard destination config wrapper (consent, data, env, id, ...). For the shared fields see destination configuration. Package-specific fields live under config.settings and are listed below.

Settings

PropertyTypeDescriptionMore
siteId*stringMatomo Site ID
url*stringBase URL of your Matomo instance
disableCookiesbooleanDisable all tracking cookies for cookie-free analytics
enableLinkTrackingbooleanEnable automatic outlink and download tracking
enableHeartBeatTimerintegerEnable heart beat timer with interval in seconds for accurate time-on-page
customDimensionsRecord<string, string>Custom dimension ID to property path mapping applied to all events
* Required fields

Mapping

Per-event rules under config.mapping. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

PropertyTypeDescriptionMore
goalIdstringGoal ID to track a conversion alongside this event
goalValuestringProperty path for goal revenue value
siteSearchbooleanTrack as internal site search using trackSiteSearch
contentImpressionbooleanTrack as content impression using trackContentImpression
contentInteractionbooleanTrack as content interaction using trackContentInteraction
customDimensionsRecord<string, string>Per-event custom dimension ID to property path mapping

Examples

Custom event with goal

A promotion visible event fires Matomo trackEvent and then trackGoal to record a goal conversion.

Event
{
  "name": "promotion visible",
  "data": {
    "name": "Setting up tracking easily",
    "position": "hero"
  },
  "context": {
    "ab_test": [
      "engagement",
      0
    ]
  },
  "globals": {
    "pagegroup": "homepage"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "4c2f620fd8a630b3",
  "trigger": "visible",
  "entity": "promotion",
  "action": "visible",
  "timestamp": 1700000401,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "trackEvent",
  "settings": {
    "goalId": "goal_1"
  },
  "data": {
    "set": [
      "data.name",
      "data.position"
    ]
  }
}
Out
_paq.push([
  "trackEvent",
  "Setting up tracking easily",
  "hero"
]);

_paq.push([
  "trackGoal",
  "goal_1",
  null
])

Cart update

A cart view calls Matomo trackEcommerceCartUpdate with the nested product items and cart total.

Event
{
  "name": "cart view",
  "data": {
    "currency": "EUR",
    "value": 840
  },
  "context": {
    "shopping": [
      "cart",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420,
        "quantity": 2
      },
      "context": {
        "shopping": [
          "cart",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b74d3cc346dcef2f",
  "trigger": "load",
  "entity": "cart",
  "action": "view",
  "timestamp": 1700000403,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "trackEcommerceCartUpdate",
  "data": {
    "set": [
      {
        "loop": [
          "nested",
          {
            "condition": {
              "$code": "e=>v(e)&&\"product\"===e.entity"
            },
            "map": {
              "sku": "data.id",
              "name": "data.name",
              "category": {
                "value": ""
              },
              "price": "data.price",
              "quantity": {
                "value": 1
              }
            }
          }
        ]
      },
      "data.value"
    ]
  }
}
Out
_paq.push([
  "trackEcommerceCartUpdate",
  [
    {
      "sku": "ers",
      "name": "Everyday Ruck Snack",
      "category": "",
      "price": 420,
      "quantity": 1
    }
  ],
  840
])

Ecommerce order

A completed order calls Matomo trackEcommerceOrder with line items and order totals.

Event
{
  "name": "order complete",
  "data": {
    "id": "0rd3r1d",
    "currency": "EUR",
    "shipping": 5.22,
    "taxes": 73.76,
    "total": 555
  },
  "context": {
    "shopping": [
      "complete",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "product",
      "data": {
        "id": "ers",
        "name": "Everyday Ruck Snack",
        "color": "black",
        "size": "l",
        "price": 420
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "product",
      "data": {
        "id": "cc",
        "name": "Cool Cap",
        "size": "one size",
        "price": 42
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    },
    {
      "entity": "gift",
      "data": {
        "name": "Surprise"
      },
      "context": {
        "shopping": [
          "complete",
          0
        ]
      },
      "nested": []
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b938cace28c1e637",
  "trigger": "load",
  "entity": "order",
  "action": "complete",
  "timestamp": 1700000402,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "trackEcommerceOrder",
  "data": {
    "set": [
      {
        "loop": [
          "nested",
          {
            "condition": {
              "$code": "e=>v(e)&&\"product\"===e.entity"
            },
            "map": {
              "sku": "data.id",
              "name": "data.name",
              "category": {
                "value": ""
              },
              "price": "data.price",
              "quantity": {
                "value": 1
              }
            }
          }
        ]
      },
      {
        "map": {
          "orderId": "data.id",
          "grandTotal": "data.total",
          "tax": "data.taxes",
          "shipping": "data.shipping"
        }
      }
    ]
  }
}
Out
_paq.push([
  "trackEcommerceOrder",
  [
    {
      "sku": "ers",
      "name": "Everyday Ruck Snack",
      "category": "",
      "price": 420,
      "quantity": 1
    },
    {
      "sku": "cc",
      "name": "Cool Cap",
      "category": "",
      "price": 42,
      "quantity": 1
    }
  ],
  {
    "orderId": "0rd3r1d",
    "grandTotal": 555,
    "tax": 73.76,
    "shipping": 5.22
  }
])

Goal with value

A promotion event fires Matomo trackEvent and then trackGoal with a monetary goal value from event data.

Event
{
  "name": "promotion visible",
  "data": {
    "name": "Setting up tracking easily",
    "position": "hero",
    "value": 50
  },
  "context": {
    "ab_test": [
      "engagement",
      0
    ]
  },
  "globals": {
    "pagegroup": "homepage"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "b82cd875d48794cf",
  "trigger": "visible",
  "entity": "promotion",
  "action": "visible",
  "timestamp": 1700000406,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "trackEvent",
  "settings": {
    "goalId": "1",
    "goalValue": "data.value"
  },
  "data": {
    "set": [
      "data.name"
    ]
  }
}
Out
_paq.push([
  "trackEvent",
  "Setting up tracking easily"
]);

_paq.push([
  "trackGoal",
  "1",
  50
])

Initialization

Destination bootstrap loads the Matomo tracker script and configures the tracker URL and site id.

Event
{
  "loadScript": true,
  "settings": {
    "siteId": "1",
    "url": "https://analytics.example.com/"
  }
}
Out
_paq.push([
  "setTrackerUrl",
  "https://analytics.example.com/matomo.php"
]);

_paq.push([
  "setSiteId",
  "1"
]);

_paq.push([
  "enableLinkTracking"
])

Page view

A page view is tracked in Matomo via trackPageView with the page title from event data.

Event
{
  "name": "page view",
  "data": {
    "domain": "www.example.com",
    "title": "walkerOS documentation",
    "referrer": "https://www.walkeros.io/",
    "search": "?foo=bar",
    "hash": "#hash",
    "id": "/docs/"
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "pagegroup": "docs"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "78a1cf2ef71fcf5e",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000400,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "data": "data.title"
}
Out
_paq.push([
  "trackPageView",
  "walkerOS documentation"
])

Product detail view

A product view fires Matomo ecommerceProductDetailView with a single-product array.

Event
{
  "name": "product view",
  "data": {
    "id": "ers",
    "name": "Everyday Ruck Snack",
    "color": "black",
    "size": "l",
    "price": 420
  },
  "context": {
    "shopping": [
      "detail",
      0
    ]
  },
  "globals": {
    "pagegroup": "shop"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [],
  "consent": {
    "functional": true
  },
  "id": "72ab79295062a604",
  "trigger": "load",
  "entity": "product",
  "action": "view",
  "timestamp": 1700000404,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "ecommerceProductDetailView",
  "data": {
    "set": [
      {
        "set": [
          {
            "map": {
              "sku": "data.id",
              "name": "data.name",
              "price": "data.price",
              "quantity": {
                "value": 1
              }
            }
          }
        ]
      }
    ]
  }
}
Out
_paq.push([
  "ecommerceProductDetailView",
  [
    {
      "sku": "ers",
      "name": "Everyday Ruck Snack",
      "price": 420,
      "quantity": 1
    }
  ]
])

Site search

A search submit fires Matomo trackSiteSearch with the keyword, category, and number of results.

Event
{
  "name": "search submit",
  "data": {
    "query": "shoes",
    "category": "products",
    "resultsCount": 42
  },
  "context": {
    "dev": [
      "test",
      1
    ]
  },
  "globals": {
    "lang": "elb"
  },
  "custom": {
    "completely": "random"
  },
  "user": {
    "id": "us3r",
    "device": "c00k13",
    "session": "s3ss10n"
  },
  "nested": [
    {
      "entity": "child",
      "data": {
        "is": "subordinated"
      }
    }
  ],
  "consent": {
    "functional": true
  },
  "id": "fc66cf4067ff0c0b",
  "trigger": "test",
  "entity": "search",
  "action": "submit",
  "timestamp": 1700000405,
  "timing": 3.14,
  "source": {
    "count": 1,
    "trace": "0a1b2c3d4e5f60718293a4b5c6d7e8f9",
    "type": "collector",
    "schema": "4"
  }
}
Mapping
{
  "name": "trackSiteSearch",
  "settings": {
    "siteSearch": true
  },
  "data": {
    "set": [
      "data.query",
      "data.category",
      "data.resultsCount"
    ]
  }
}
Out
_paq.push([
  "trackSiteSearch",
  "shoes",
  "products",
  42
])
💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)