Measure

Matomo Tag Manager: containers, tags, triggers and variables

Matomo Tag Manager controls which code runs on your website and when: the Matomo tracker, events and goals, and services from other providers if you want them. It is part of Matomo, and the container file comes from your own instance. Here is how the pieces fit together and how to bring changes live safely.

A tag manager separates two things: the website only loads a container, and what happens inside it is defined in Matomo. New events, a goal or a changed privacy switch no longer need a change to the source code. Matomo Tag Manager covers much of what you know from Google Tag Manager. The difference: it runs in your Matomo instance, and the data stays there.

The four building blocks

Building block Question Example
Container Where? one website, one file container_AbC123xY.js
Tag What happens? Matomo counts a page view or an event
Trigger When? page view, click on a download, form submit
Variable With which values? page URL, click text, a value from the data layer

A tag fires as soon as one of its triggers applies. Variables supply the values a tag needs and narrow down triggers, for example “All Links Click when the Click Destination URL contains /contact/”. In the form you refer to a variable with double curly braces, for example {{PageUrl}}.

One variable is special: Matomo Configuration. It holds the address of your instance, the site ID and all settings on cookies and consent. Every tag of type Matomo Analytics uses it. Which switches matter there for cookies is described under Matomo cookies.

Embedding the container

Under Install Code, Matomo shows the embed code for each environment. It belongs as high up as possible in the <head> of every page:

<!-- Matomo Tag Manager -->
<script>
  var _mtm = window._mtm = window._mtm || [];
  _mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'});
  (function() {
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.async=true; g.src='https://matomo.example.com/js/container_AbC123xY.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<!-- End Matomo Tag Manager -->

Matomo writes the container file into its js/ directory when you publish. It needs write access there, and the system check reports it if that is missing. For Live the file is called container_ID.js. For other environments Matomo adds a random part, so that nobody can guess the address of the staging version.

When you switch, remove the previous Matomo tracking code. If both run, every page view counts twice.

Triggers: when a tag fires

Matomo groups the triggers into four sets: clicks, the page view in three stages, user engagement such as scroll depth, the visibility of an element or a form submit, and others such as timer, JavaScript errors and custom events from the data layer.

Matomo Tag Manager, choosing a trigger type: groups Click, Pageview, User Engagement and Others with triggers such as All Downloads Click, DOM Ready, Element Visibility, Form Submit, Scroll Reach, Custom Event, JavaScript Error and Timer
The trigger types in Matomo Tag Manager, shown in Matomo 6 on our test instance.
Click the image: fit or full sizeTap the image: full size
Matomo Tag Manager, choosing a trigger type: groups Click, Pageview, User Engagement and Others with triggers such as All Downloads Click, DOM Ready, Element Visibility, Form Submit, Scroll Reach, Custom Event, JavaScript Error and Timer

The trigger types in Matomo Tag Manager, shown in Matomo 6 on our test instance.

For the page view, the difference matters: Pageview fires as soon as the container runs, DOM Ready when the HTML is complete, Window Loaded only after all images. For the Matomo tag, Pageview is enough. Tags that access elements of the page are better off waiting for DOM Ready.

Click triggers on CSS classes are quick to build and break at the next relaunch. For everything that counts, such as a sent enquiry or a purchase, the data layer is more robust.

Variables

Dozens of variables are preconfigured, for example Page URL, Click Text or scroll depth. Your own variables read cookies, URL parameters, meta tags, elements of the page or the data layer. In a tag you always refer to the name the variable has in the Tag Manager, for example {{Order revenue}}.

The data layer

A data layer is a hand-over tray between your website and the Tag Manager. The website puts down what it knows: what kind of page is being shown, what the visitor has just done and which values belong to it. The Tag Manager reads from it and decides what happens. Technically it is a JavaScript array; in Matomo Tag Manager it is called _mtm, in Google Tag Manager dataLayer.

The gain is the division of labour: development defines once which information the website reports. What of it ends up in Matomo, as an event, goal or dimension, you decide afterwards in the Tag Manager, without a new release of the website.

The division of labour, using an enquiry as the example: after a successful submission, the website writes an entry into the data layer. In the Tag Manager, the trigger reacts to the event name, the variable reads the value, and the tag sends the event with this value to Matomo.
What you want to measure Without a data layer With a data layer
Enquiry sent click on “Send”, even if the form reports an error event only after a successful submission
Revenue of an order read from the text of the confirmation page handed over as a number
Type of page guessed from the URL set by the CMS, for example “product” or “guide”
After a relaunch selectors and texts no longer match measurement keeps working as long as the website writes the same entries

How it works

  • Every entry is an object of names and values: { pagetype: 'product' }.
  • An entry with event is an event. Triggers of type Custom Event react to this name. Entries without event only set values.
  • New values replace old ones. If the page writes the same name again later, the new value applies, for an object the whole new object.
  • Nested values are read with a dot. If the data layer holds { order: { revenue: 129.9 } }, a variable of type Data-Layer with the name order.revenue reads the amount.
  • Nothing is lost just because the container loads later. What the page writes into _mtm beforehand, the container processes as soon as it is there.
  • It only lives as long as the page. On the next page view it starts empty. It sends nothing by itself: only a tag determines which value goes to Matomo.
One page view over time, with the content of the data layer on the right: what the page writes before the container exists waits and is processed as soon as the container is there. On the next page view the data layer starts empty again.

Personal data does not belong in it, so no names, email addresses or customer numbers. Every script on the page can read the data layer, including that of a chat or advertising service.

Example 1: information about the page

The CMS writes on every page what kind of page it is, before the embed code of the container:

<script>
  window._mtm = window._mtm || [];
  window._mtm.push({ pagetype: 'product', section: 'outdoor', loggedin: 'yes' });
</script>
<!-- followed by the embed code of Matomo Tag Manager -->

In the Tag Manager you create a variable of type Data-Layer with the name pagetype and add it in the Matomo Analytics tag under Custom Dimensions, together with the index of a dimension you created in Matomo beforehand. Matomo then shows, for example, how many visits come through guides and how many through product pages.

Example 2: enquiry sent successfully

The contact form only reports once the server has accepted the enquiry:

window._mtm = window._mtm || [];
window._mtm.push({ event: 'enquiry-sent', form: 'contact' });

In the Tag Manager you set up three things:

  1. A trigger Custom Event with the event name enquiry-sent.
  2. A variable of type Data-Layer that reads the value form. Call it “Form”, for example.
  3. A tag Matomo Analytics with the tracking type Event, category Form, action sent and {{Form}} as the name. If the enquiry should count as a goal, choose the tracking type Goal instead.

If the website has several forms, the same setup is enough: each one writes its own name into form.

Example 3: purchase with revenue

The shop’s confirmation page reports the order:

window._mtm = window._mtm || [];
window._mtm.push({
  event: 'purchase',
  order: { revenue: 129.9, payment: 'invoice', newcustomer: true }
});

A variable of type Data-Layer with the name order.revenue is called “Order revenue” in the Tag Manager. The Matomo Analytics tag with the tracking type Goal enters {{Order revenue}} as the revenue. The format matters: a number with a decimal point, without currency sign and without thousands separator.

That way a purchase counts as a goal with revenue. For full ecommerce tracking with cart, items and order number, the Matomo tag has no tracking type of its own. For that, the ecommerce functions of the tracker are called, also with values from the data layer. That is best defined in the tracking concept.

Example 4: page changes in a web app

If an application loads new content without reloading the page, Matomo at first only sees the first view. The trigger History Change detects when the URL changes. It gets more precise when the app itself reports as soon as content and title are in place:

window._mtm = window._mtm || [];
window._mtm.push({ event: 'page-change', page: { path: '/pricing/', title: 'Pricing' } });

A trigger Custom Event on page-change starts a Matomo Analytics tag with the tracking type Pageview. Under Custom URL and Custom Title you enter the variables for page.path and page.title.

Preview, versions and environments

Changes go into the draft first. Nothing goes live before you publish a version. The way there:

  1. Switch on Preview / Debug. Enter the address of the page you want to test. Matomo opens it with the parameter mtmSetDebugFlag=1. It sets a cookie in this browser for seven days: the website then loads the draft instead of the live version and shows a debug window with tags, triggers and variables. All other visitors keep seeing the live version. mtmSetDebugFlag=0 removes the cookie again.
  2. Create a version. A version freezes the state. Briefly describe what changes, and publish it to staging or dev first if you have such environments.
  3. Publish to Live. If something goes wrong, simply publish the previous version to Live again.

Two things are worth knowing: according to Matomo, the names of tags are publicly visible while the preview is on. And the preview file has no random part in its name. Internal abbreviations, customer names or even keys therefore do not belong in a container.

Super users add further environments under Administration > General Settings. Versions can also be exported as JSON and imported again, for example as a backup or to move a container to another Matomo instance.

How often a tag fires

In a tag’s advanced settings you define how often and when it may fire:

  • Fire limit: Unlimited, Once per pageview, Once per 24 hours or Once in lifetime.
  • Fire delay in milliseconds, so that a tag does not get cut off when the page redirects right away.
  • Priority: the lower the number, the earlier a tag fires when several are due at the same time. The default is 999.
  • Start date and End date, for example for a pixel that should only run during a campaign.
Matomo Tag Manager, advanced settings of a tag: Fire limit with Unlimited, Once per pageview, Once per 24 hours and Once in lifetime, then Fire delay 0, Priority 999, Start date and End date, each with an explanation
The advanced settings of a tag, shown in Matomo 6 on our test instance.
Click the image: fit or full sizeTap the image: full size
Matomo Tag Manager, advanced settings of a tag: Fire limit with Unlimited, Once per pageview, Once per 24 hours and Once in lifetime, then Fire delay 0, Priority 999, Start date and End date, each with an explanation

The advanced settings of a tag, shown in Matomo 6 on our test instance.

“Once per 24 hours” and “Once in lifetime” work because the Tag Manager remembers in the browser’s local storage that a tag has already fired. That is an access to the device, even without a cookie. Clarify with your data protection adviser whether that is acceptable without consent. With “Unlimited” and “Once per pageview”, the Tag Manager stores nothing for this.

Consent concerns two levels. For Matomo itself, you control in the Matomo Configuration variable whether, without consent, it measures without cookies or not at all. As soon as your consent tool reports consent, you call rememberCookieConsentGiven or rememberConsentGiven, as Matomo describes in the help for these fields.

For services from other providers, your tag only fires once consent is there. The cleanest way to build that is through the data layer. On consent, the consent tool writes an event, for example consent-marketing, and only this trigger starts the tags concerned. For Axeptio, CookieYes, Cookiebot and OneTrust, the Tag Manager comes with templates that embed the respective tool, plus one for Google’s consent mode.

Permissions: who may do what

Users with write access to the website can use the Tag Manager. Two capabilities cover the sensitive parts:

  • Publish Live Container: only site admins and users with this capability may publish to Live. That way others can prepare drafts and test them in staging without going live.
  • Use Custom Templates: Custom HTML and variables with your own JavaScript run arbitrary code on your website. Matomo itself warns that this can be misused, for example to steal sensitive data. Under Restrict usage of custom templates, super users can limit them to admins or super users or switch them off entirely.

Moving from Google Tag Manager

Matomo does not take over a container from Google Tag Manager automatically. That is less bad than it sounds: a move is the opportunity to sort out old tags and name everything consistently. What can stay is your data layer. By default, Matomo Tag Manager also reads the values that are already in the Google Tag Manager data layer. Since Matomo 5.2 there is also the option Actively synchronise from the Google Tag Manager data layer: then entries written to dataLayer later also arrive. If you do not want that, switch on Ignore Google Tag Manager data layer. Both containers can run in parallel for a while until the numbers match. How I support such a move is described under Matomo Tag Manager.

Sources

As of 11 November 2026

FAQ

Frequently asked questions

Is the Tag Manager included in Matomo?

Yes. It ships with Matomo On-Premise and, like Matomo itself, is licensed under the GPL. If it is not active on your instance, activate it in the plugin management.

What is a data layer?

A JavaScript array into which your website writes information for the Tag Manager; in Matomo Tag Manager it is called _mtm. The website reports, for example, the type of page or that an enquiry was sent, and in the Tag Manager you decide what of it goes to Matomo. That is more robust than reading clicks and texts from the page.

Do I also need the regular Matomo tracking code?

No. The Matomo Analytics tag in the container loads the tracker and counts the page view. If the old tracking code stays on the page as well, Matomo counts every page view twice.

Can I import a container from Google Tag Manager?

Not directly. Matomo Tag Manager only imports versions exported from Matomo. Tags, triggers and variables from Google Tag Manager are created anew. Matomo Tag Manager can, however, read your existing data layer.

Does the Tag Manager work with a Content Security Policy?

Yes. The container does not need eval. You allow the domain of your Matomo instance and the embed code, by hash or nonce. Custom HTML takes over the nonce if a script on the page carries one.

Who may bring changes live?

You control that with permissions: site admins and users with the capability “Publish Live Container” may publish to live. Custom HTML and JavaScript have a capability of their own, which super users can also switch off entirely.

Questions about your setup?

In an intro call we'll look at your situation together.

Book an intro call

Newsletter

Matomo know-how, once a month.

Practical tips on tracking, privacy settings and performance, plus notes on important Matomo updates. No spam, unsubscribe any time.