IntegrationsAnalyticsMatomo Analytics

Matomo Analytics

Datafly Signal delivers events to Matomo Analytics server-to-server using the Tracking HTTP API. Matomo is the open-source, self-hostable analytics platform of choice for organisations that need full data sovereignty — popular with EU regulators, public-sector bodies, and privacy-led brands.

⚠️

Alpha integration. Tracking API delivery is operational with a default Retail preset covering page, product, and ecommerce events. Custom dimensions and goal conversions can be added through field mappings. Contact your account team for help wiring custom dimensions to Matomo slot IDs.

Prerequisites

Before configuring Matomo in Signal you need:

  • A Matomo instance. Either:
    • Matomo Cloud: your tenant base URL, e.g. https://yourcompany.matomo.cloud.
    • Self-hosted Matomo: the public base URL of your deployed instance.
  • The Site ID of the Matomo site you want events delivered to.
  • An auth token (token_auth). Required for server-side tracking — without it Matomo will not let you override visitor IP, set custom visitor IDs, or stamp historical timestamps.

Get your credentials

Step 1: Note your Matomo instance URL

This is the base URL where you log into Matomo. Strip any trailing slash. Examples:

  • Matomo Cloud: https://acme.matomo.cloud
  • Self-hosted: https://analytics.example.com

Signal will POST events to {matomo_url}/matomo.php.

Step 2: Find your Site ID

  1. Log into Matomo.
  2. Go to Administration (cog icon) > Websites > Manage.
  3. Find the site you want Signal to track and note the ID column. It is a small integer (1, 2, 3, …).

Step 3: Generate a token_auth

  1. In Matomo, click your username (top right) > Security.
  2. Scroll to Auth tokens and click Create new token.
  3. Give it a name (e.g. Datafly Signal).
  4. Confirm with your password.
  5. Copy the token.
⚠️

Store this token as a secret. Anyone holding it has the same write access to your Matomo data that you do. Generate a per-environment token (one for staging, one for production) so revocation is granular.

Configure in Signal

Configuration fields

FieldRequiredDescription
matomo_urlYesBase URL of your Matomo instance, no trailing slash (e.g. https://analytics.example.com).
site_idYesNumeric Matomo Site ID from the Websites admin page.
token_authYesMatomo auth token (32-character hex). Stored as a secret.

Management UI setup

  1. Go to Integrations > Add Integration > Matomo Analytics.
  2. Enter the matomo_url, site_id, and token_auth.
  3. Select the Retail preset (the default — covers page, product, cart, and order events).
  4. Set consent categories to analytics.
  5. Click Save.

Management API setup

curl -X POST http://localhost:8084/v1/admin/integrations \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "source_id": "src_abc123",
    "vendor": "matomo",
    "name": "Matomo Production",
    "enabled": true,
    "config": {
      "matomo_url": "https://analytics.example.com",
      "site_id": "1",
      "token_auth": "0123456789abcdef0123456789abcdef"
    },
    "consent_categories": ["analytics"]
  }'

API endpoint

POST {matomo_url}/matomo.php
Content-Type: application/x-www-form-urlencoded

Matomo’s tracker uses form-encoded key=value pairs, not JSON. Signal handles encoding automatically.

Event mapping

Retail preset

Signal eventMatomo actionMatomo fields populated
pagePageviewaction_name, url, urlref
Product ViewedEcommerce product viewidgoal=view, _pks, _pkn, _pkc, _pkp
Product AddedCart updateidgoal=0, _pks, _pkn, _pkc, _pkp, _pkq
Order CompletedEcommerce orderidgoal=0, ec_id, revenue, ec_tx, ec_sh, ec_dt

All events also carry these global fields:

Matomo fieldSource
idsitefrom integration config
recstatic 1 (required by Matomo)
token_authfrom integration config
cipvisitor IP
uavisitor User-Agent
_id16-char hex visitor ID derived from the Signal anonymous identifier
uidauthenticated user ID (when identified)
urlpage URL of the event

Example: Order Completed

Datafly.js call:

datafly.track("Order Completed", {
  order_id: "ORD-001",
  revenue: 129.99,
  tax: 21.66,
  shipping: 4.99,
  currency: "USD",
  url: "https://example.com/checkout/confirmation"
});

Matomo payload (form-encoded) sent by Signal:

idsite=1
&rec=1
&token_auth=01234...
&cip=203.0.113.50
&ua=Mozilla/5.0%20...
&_id=a1b2c3d4e5f60718
&url=https%3A%2F%2Fexample.com%2Fcheckout%2Fconfirmation
&idgoal=0
&ec_id=ORD-001
&revenue=129.99
&ec_tx=21.66
&ec_sh=4.99

Matomo records this as an ecommerce order against site 1 attributed to visitor a1b2c3d4e5f60718.

Custom dimensions and goals

To populate Matomo custom dimensions or goal conversions, add field mappings to the integration:

  • Custom visit dimensions: target dimension{slot_id} where slot_id is the dimension slot configured in Matomo (1-50).
  • Custom action dimensions: target dimension{slot_id} on the relevant event.
  • Goals: target idgoal with the numeric goal ID.

Identity

Signal sends the following identity signals to Matomo:

Matomo fieldSignal sourceDescription
_idFirst 16 hex chars of the Signal anonymous_idMatomo’s visitor identifier. Must be a 16-character hex string per the Tracking API spec. Stable across sessions for the same visitor.
uiduser_idMatomo’s user ID — set once the visitor authenticates. Allows merging anonymous and identified visit history in Matomo.
cipVisitor IP forwarded from the original browser requestDrives Matomo’s GeoIP lookup. Requires token_auth.
uaVisitor User-Agent forwarded from the original browser requestDrives Matomo’s browser, OS, and device detection. Requires token_auth.

No PII hashing is needed — Matomo’s privacy posture handles IP anonymisation at its own boundary (configurable in Matomo under Privacy > Anonymise data). Signal forwards the raw values; Matomo decides how much of each octet to retain.

Call datafly.identify() to populate uid

datafly.identify("user-123");

Subsequent events carry uid=user-123 to Matomo. Anonymous events fired before identify still map to the same _id so Matomo stitches the visit together.

The default consent category is analytics. Matomo is a first-party analytics destination and respects the visitor’s analytics consent state — events drop silently when consent has been withdrawn.

If you have configured Matomo’s opt-out feature on your site, the Tracking API request honours it through the standard Matomo logic (Signal forwards the relevant headers).

Verify it’s working

Step 1: Trigger a test pageview

From a page running Datafly.js:

datafly.page({
  url: window.location.href,
  title: document.title
});

Step 2: Check Matomo’s Visitor Log

  1. In Matomo, go to Visitors > Visits Log.
  2. Filter on Today.
  3. Your test visit should appear within a few seconds, with Source = Direct Entry (or the appropriate referrer) and the page title you sent.

Step 3: Inspect the Signal event debugger

In the Signal Management UI, open the Matomo integration’s Recent Events tab. You should see the event with a 204 response (Matomo’s success code) and the form-encoded payload.

Step 4: Verify ecommerce tracking

Fire an Order Completed event and confirm it appears in Matomo under Ecommerce > Overview with the correct revenue and order ID.

Troubleshooting

ProblemSolution
Events arrive but cip and _id are not honouredThe token_auth is missing, invalid, or its account lacks write access to the site. Regenerate a token under an admin user.
Geo location is blankMatomo’s GeoIP database is not configured. Install GeoIP under Administration > Geolocation. Signal sends the IP correctly.
Events return 200 but do not appear in reportsCheck idsite matches the target site. If Matomo’s opt-out or Do Not Track setting is enabled, events for opted-out visitors are intentionally dropped.
Ecommerce orders missingidgoal=0 is required for orders, plus ec_id for the order ID. Verify both are mapped. Also ensure ecommerce tracking is enabled on the Matomo site under Administration > Websites > Manage > Enable Ecommerce.
Slow page rendering in Matomo reportsMatomo is self-hosted on under-provisioned infrastructure. This is a Matomo-side performance question, not a Signal delivery question.
Visitor identity churns across sessionsVerify _id is being populated. If it is empty, Matomo treats every request as a new visitor. Check the Signal anonymous identifier is being generated and forwarded.

See also