Matomo Event Tracking with Tag Manager: A Complete Guide

Analytics & CRO

Matomo Tag Manager lets you capture the user behaviour data that drives product decisions — clicks, filter usage, form submissions, search interactions — without a development sprint for every new event. The key is a consistent dataLayer contract and naming taxonomy agreed with engineering upfront: get that foundation right, and new tracking becomes a Tag Manager task rather than a code change.

The problem isn’t tracking. It’s the gap between what you measure and what you actually decide. Pageviews tell you what was visited. Events tell you what users did — and that’s the data product decisions depend on.

This is a complete guide to Matomo event tracking with Tag Manager: the trackEvent syntax, the _mtm dataLayer pattern, a step-by-step container setup, and how to debug when events go quiet. With real code examples throughout.

Why event tracking breaks down in practice

Most analytics setups capture pageviews reliably. That’s useful for content performance. It doesn’t answer the questions that drive product reviews: did users engage with the new search feature? Did filter usage correlate with conversion? Did the CTA variant lift intent signals?

Those answers live in events. And if event tracking isn’t systematic — if it’s a patchwork of hardcoded scripts with inconsistent naming — product teams end up making gut calls and calling it data-driven.

I built the event tracking layer on a high-traffic travel booking platform using Matomo Tag Manager. What I’ll describe here is the setup that made it possible to trust the data in a product review, not just reference it.

What Matomo Tag Manager actually does

Matomo Tag Manager (MTM) is a container-based tag management system — similar in principle to Google Tag Manager, but built entirely within the Matomo ecosystem. A single JavaScript container snippet goes on your site once. Everything else — tags (what to fire), triggers (when to fire), variables (what data to pass) — is configured in the MTM interface and deployed as numbered container versions. No further engineering involvement required for most tracking changes.

The full feature set is documented in the official Matomo Tag Manager guide. What follows is how it works in practice on a live booking platform.

For a walkthrough of setting up your first MTM container from scratch, see Setting up your first Matomo Tag Manager container. This post focuses on what to do once the container is installed: building event tracking that holds up under scrutiny.

The four building blocks

Tags are the scripts you want to fire — a Matomo page view, a custom event, a conversion pixel.

Triggers define when a tag fires — on page load, on a specific click, on form submission, on scroll depth.

Variables store reusable values — your Matomo site ID, a dataLayer value, a page attribute — so you define them once and reference them everywhere.

Containers are the parent wrapper that holds everything. The container generates the code snippet that goes on your site — the one moment that requires engineering. After that, everything else happens in the interface.

The trackEvent call: syntax and parameters

All Matomo event tracking is built on one function. Understanding its four parameters is the prerequisite for building an event taxonomy that stays coherent over time.

_paq.push([
  'trackEvent',
  'Category',   // Groups related events — e.g. 'Booking Funnel'
  'Action',     // What happened — e.g. 'CTA Click'
  'Name',       // Optional: specific label — e.g. 'Book Now — Search Results'
  'Value'       // Optional: numeric — e.g. 1 for a click, or a revenue figure
]);

A working example from a travel booking site, tracking the primary CTA on search results:

_paq.push([
  'trackEvent',
  'Booking Funnel',
  'CTA Click',
  'Book Now — Search Results',
  1
]);

This fires in Matomo as an event in the Booking Funnel category, action CTA Click, label Book Now — Search Results, value 1. You can report on CTA clicks by location across the funnel, create a goal triggered by this specific event, or segment users who clicked it against those who didn’t.

Naming conventions matter more than the implementation. Before writing a single trackEvent call, agree on a consistent taxonomy: how categories are named, what constitutes an action versus a name, whether values are always integers or can be decimals. Inconsistent naming is the most common reason event data can’t be trusted in a product review — and it’s invisible until you need to query across events.

Custom events via the _mtm dataLayer

Hardcoding _paq.push calls directly in the codebase works for simple implementations. It breaks down at scale. When a product question requires a new event, you raise a ticket, wait for a sprint, and test a deployment — for what amounts to three lines of JavaScript. The measurement backlog grows faster than the codebase can support it.

The _mtm dataLayer solves this by decoupling event tracking from the codebase. The developer pushes structured data to the dataLayer at the relevant moments — no knowledge of Matomo required on their end. Matomo Tag Manager handles what to do with it.

// Developer adds this to the site at the relevant interaction point
// No Matomo dependency — just a plain JavaScript object push
window._mtm = window._mtm || [];
window._mtm.push({
  'event':        'bookingCTAClick',
  'ctaLocation':  'search-results',
  'resultCount':  14,
  'destination':  'DUB'
});

The developer’s responsibility ends there. The analytics or product team configures the corresponding tag in MTM — pulling in those dataLayer properties as variables — without touching the codebase again.

This is the separation of concerns that makes event tracking sustainable at scale. Engineering owns the dataLayer contract: what data is available, at what point in the user journey, in what format. Product owns what gets tracked and how it maps to reporting.

For more on structuring a dataLayer for custom web tracking, see Tailor-made web tracking through the dataLayer.

Setting up a custom event in Matomo Tag Manager: step by step

This walkthrough assumes the MTM container is already installed. If not, generate the container code from Matomo > Tag Manager > Containers > Install Code and add it immediately after the opening <body> tag on every page.

Step 1: Create a Variable for each dataLayer property

In Variables > New Variable, create a variable of type Data Layer. Set the variable name to match exactly what the developer pushes — for example, ctaLocation. The name is case-sensitive. Repeat for each property you need to capture.

Step 2: Create a Custom Event Trigger

In Triggers > New Trigger, select Custom Event as the trigger type. Set the event name to match the event property in the dataLayer push — in this example, bookingCTAClick. Matching is case-sensitive.

Step 3: Create a Matomo Analytics Tag

In Tags > New Tag, select Matomo Analytics as the tag type, then choose Custom Event as the tracking type. Map the fields to your variables:

  • Category: Booking Funnel — or use a variable if the category is dynamic
  • Action: CTA Click
  • Name: {{ctaLocation}} — the variable from Step 1, using MTM’s double-brace syntax
  • Value: leave blank, or map a numeric variable

Assign the Custom Event trigger from Step 2 to this tag.

Step 4: Test in Preview mode

Before publishing, activate Preview mode using the play icon in the container view. Open your site in the same browser. Trigger the event — click the CTA, submit the form, complete whatever the tracked interaction is. The MTM debug panel shows every dataLayer push, every trigger evaluation, and every tag that fired or didn’t. Verify the tag fires and the variable values are populated correctly.

Step 5: Verify in Matomo real-time

With Preview mode active, open Matomo > Visitors > Real-time. Find your test visit and confirm the event appears with the correct category, action, and name. This step matters: MTM firing is not the same as data reaching Matomo. The real-time log is the proof.

Step 6: Publish the container version

Once verified, click Publish in MTM and give the version a descriptive name — for example, v1.4 — Booking funnel CTA events. Container versions give you a rollback path: if something breaks after a publish, you can revert to any previous version immediately without touching the codebase.

Debugging: did my event actually fire?

Event tracking bugs are quiet. The tag doesn’t error — it simply doesn’t fire, or fires with the wrong data. These are the checks that catch issues before they corrupt reporting.

MTM Preview & Debug mode

This is your first line of diagnosis. The debug panel shows every dataLayer push, every trigger evaluation (including why a trigger didn’t match), and every tag execution. A trigger not matching is usually a typo in the event name or a condition that wasn’t met. The debug view shows you exactly which condition failed.

Browser console manual test

You can fire a Matomo event directly from the browser console to isolate whether the issue is in MTM or in the Matomo tracker itself:

// Fire a test event directly — bypasses MTM entirely
var tracker = window.Matomo.getAsyncTracker();
tracker.trackEvent('Debug Test', 'Manual Fire', 'Console Test', 1);

If this event appears in Matomo’s real-time log, the tracker is working. The issue is upstream — in MTM, the trigger logic, or the dataLayer push itself.

Common mistakes

  • Event name case mismatch: bookingCTAClick and BookingCTAClick are not the same. MTM event matching is case-sensitive.
  • Container not published: Changes in MTM only take effect after you publish. Preview mode uses an unpublished version — easy to forget when handing off to someone else to test.
  • _mtm initialised too late: If a dataLayer push fires before the MTM container loads, the event is lost. Always initialise with window._mtm = window._mtm || [] before any push, ideally in the page <head>.
  • Adblocker interference: Matomo’s tracker can be blocked by aggressive content blockers. This affects real users too — worth factoring in when interpreting event volumes and conversion rates.

On adblockers: Matomo can be configured as a first-party tracker on the same domain as your site, which significantly reduces blocking rates compared to third-party analytics. If you’re running Matomo on-premises and event completeness matters for product decisions, first-party configuration is worth the setup time.

Three operational mistakes worth avoiding

Tracking too much too soon. Unmaintained tags accumulate fast. A container full of tags nobody can explain becomes a liability. Start with the events that connect directly to conversion goals and expand deliberately.

Skipping documentation. A simple tag register — name, purpose, trigger, date added, owner — saves significant time six months later when nobody can remember why a specific event exists. A shared spreadsheet is sufficient.

Skipping parallel validation. If you’re migrating from hardcoded Matomo to Tag Manager, run both in parallel for two to four weeks and compare session counts. Discrepancies tell you something went wrong in the setup before it corrupts reporting history you can’t reconstruct.

From event data to product decisions

The technical implementation is the prerequisite, not the goal. The value is in what the data enables.

On the booking platform I work on, Matomo event tracking feeds directly into prioritisation decisions. When the proposal came to expand the search filter surface — adding more filter options to search results — the counterargument was that users don’t use existing filters. The event data told a different story: filter usage was significantly higher among users who converted than among those who didn’t. The question wasn’t whether to add filters. It was which filters to prioritise, based on the gap between what users were actively looking for and what the product offered.

That kind of argument doesn’t work with pageview data. It requires clean, trusted event tracking — the kind you can stand behind in a product review without having to caveat the data quality.

I chose Matomo for this not primarily for the privacy argument, though that matters on European sites subject to GDPR. I chose it because on-premises Matomo gives me an unsampled, first-party event stream that I control entirely. No sampling thresholds. No third-party processing delays. No “data may differ” warnings. When the data says something, I can trust it enough to defend a product decision with it.

Where to go from here

If you’re setting up Matomo event tracking for the first time: agree on a naming taxonomy before writing any code, implement the dataLayer contract with your engineering team, then build the tags in MTM. Get that foundation right and new tracking becomes a Tag Manager task, not a development sprint.

If you already have event tracking in place but don’t fully trust the data — the more common situation — start with the debugging steps. Verify one event end-to-end: dataLayer push, MTM trigger, Matomo real-time. If that chain is intact, you have a solid foundation to build on. If it isn’t, you’ve found the gap.

The measure of a good analytics setup isn’t how much data it produces. It’s whether you’d stake a product decision on it.

If you’re still evaluating whether Matomo is the right platform for your team, the Matomo vs GA4 comparison covers the practical differences — privacy, data ownership, cost, and what actually changes when you switch.

TL;DR

  • Matomo Tag Manager separates tracking logic from site code — once the container is published, new events are a Tag Manager task, not a development sprint
  • The foundation that makes it reliable: agree on a naming taxonomy (category/action/name) and a dataLayer contract with engineering before writing any tags
  • The debug workflow: MTM Preview mode to confirm the trigger fires, then Matomo real-time to confirm the event arrives — if either step fails, you’ve found the gap
  • The measure of a good analytics setup isn’t how much data it produces — it’s whether you’d stake a product decision on it

Delphine Ragazzi is a Product Owner with 20 years of experience across digital analytics, CRO, and product delivery. She writes about product decisions, data, and AI at douli.com.

Leave a Reply

Your email address will not be published. Required fields are marked *