Matomo Tag Manager for GLPI: analytics on every page, no code changes
GLPI tells you nothing about how your teams actually use it: which pages get traffic, where time is spent, what never gets opened. Matomo Tag Manager answers that — but only if you can inject its container into every page. Our plugin does exactly that without editing a single template, straight from GLPI’s admin panel. Here’s how it’s built, and why we kept it small.
The need
We want to measure GLPI usage with a privacy-respecting, self-hostable solution (Matomo), without:
- editing core templates (which break on every upgrade);
- adding yet another database table to maintain;
- exposing new configuration surface beyond what GLPI already protects.
The plugin boils down to one idea: one container URL, pasted once, loaded everywhere.
How it works
On every request, the plugin hooks into GLPI’s native header hook ($PLUGIN_HOOKS) and outputs a <script> tag pointing at a tiny static loader (public/js/mtm-loader.js). That loader in turn loads your Matomo container URL. Loading is asynchronous — no perceptible overhead.
The container is injected on every page — authenticated screens and the login screen — so you can follow the full journey, starting at login.
The container URL is read from GLPI’s core configuration store:
Config::getConfigurationValues('plugin:matomo', ['container_url']);
No plugin table is created, no per-asset data is stored. The setting lives in the plugin:matomo configuration context, and that’s it.
Security
A plugin that injects JavaScript into every page — login included — has to be airtight. Our guardrails:
- the container URL is validated: it must start with
https://before it’s saved; - output is escaped (
htmlspecialchars,ENT_QUOTES) when rendered into the page; - the configuration page is gated by the core
config: UPDATEright (typically the super-admin profile) — the same right that protects GLPI’s general setup; - the plugin is
csrf_compliant: the form posts through GLPI 11’s CSRF-protected controller; - no custom right is registered, and the plugin writes only to GLPI’s configuration store — it touches no core or third-party tables.
Requirements
| Item | Version |
|---|---|
| GLPI | 10.x or 11.x |
| PHP | ≥ 8.1 |
| Matomo | a reachable Tag Manager container URL |
Installation
Grab the latest release archive (or install it straight from git with our Git Plugin Installer plugin), then:
# extract into plugins/ so the path is plugins/matomo/
sudo -u apache php bin/console plugin:install matomo
sudo -u apache php bin/console plugin:activate matomo
sudo -u apache php bin/console cache:clear
Getting started
- Setup → Matomo Tag Manager.
- Paste your Matomo Container URL (e.g.
https://stats.example.com/js/container_XXXXXXXX.js). - Save — the container is injected on the next page load, tracking starts immediately.
Why so minimal
The plugin does one thing and does it well. No table, no custom right, no patched template: less surface, less breakage on upgrades, and a review that takes minutes. That’s our line across the whole GLPI ecosystem we publish.
Stable release 1.0.0, licensed GPL v2.0-or-later.
→ Code, releases and issues: https://github.com/FathiBenNasr/glpi-matomo
This post is part of our series on open-source GLPI plugins — see also the open-source announcement for this plugin. Need a custom plugin, managed operations or GLPI hardening? Let’s talk.