This plugin, MatomoTracking, is designed for Traefik as middleware to handle the tracking of requests using the Matomo analytics platform. The plugin inspects incoming HTTP requests, checks if tracking is enabled for the requested domain, and sends tracking data to Matomo if required.
The main purpose of this plugin is to enhance the accuracy of visitor tracking by overcoming limitations associated with the traditional JavaScript-based tracking method used by Matomo. Standard tracking relies on JavaScript code running in the user's browser, which can be blocked by certain browser extensions or privacy tools. By capturing tracking data directly on the server side, this plugin ensures that visitor information is accurately recorded even when JavaScript is disabled or blocked, providing a more reliable and comprehensive analytics solution.
![]()
Config Struct
Purpose:
The Config struct represents the configuration settings for the entire Matomo Tracking plugin. It defines the global settings that apply to all domains and the specific configurations for each domain that needs tracking.
Fields:
MatomoURL
matomo.php file on the Matomo server, such as https://matomo.example.com/matomo.php."https://matomo.example.com/matomo.php"Domains:
map[string]DomainConfigstring) and the corresponding value is a DomainConfig struct. This allows you to define tracking rules for multiple domains individually.domains:"www3.example.com":trackingEnabled: trueidSite: 21excludedPaths:- "/admin/*"- "\\.\\w{1,5}(\\?.+)?$"includedPaths:- "\\.(php|aspx)(\\?.*)?$"pathOverrides:"/subdir":trackingEnabled: trueidSite: 24excludedPaths:- "/test"- "/test2""/subdir2":trackingEnabled: falseidSite: 24"test.de":trackingEnabled: falseidSite: 456
DomainConfig Struct
Purpose:
The DomainConfig struct defines the tracking settings for a specific domain. Each domain that should be tracked (or explicitly not tracked) has a corresponding DomainConfig entry.
Fields:
TrackingEnabled:
booltrue, the plugin will attempt to send tracking data to Matomo. If false, tracking is disabled for that domain.IdSite:
int21ExcludedPaths:
[]string (Slice of strings)excludedPaths:- "/admin/*"- "\\.\\w{1,5}(\\?.+)?$"
IncludedPaths:
[]string (Slice of strings)includedPaths:- "\\.(php|aspx)(\\?.*)?$"
PathOverrides:
map[string]PathConfig/api, /special) and its corresponding value is a PathConfig block. This feature allows more granular control over tracking behavior within a domain.
Path overrides support the same fields as the domain-level configuration: trackingEnabled, idSite, excludedPaths, and includedPaths. If a path override is defined, it will override the corresponding settings from the parent domain only for requests matching that path.
Matching is done using prefix matching with boundary awareness. This means:
/test matches /test and /test/something/test does not match /test2 or /testingLet's analyze how the configuration is used in the dynamic.yml file:
Example Configuration
matomo-tracking:plugin:matomoTracking:matomoURL: "https://matomo.example.com/matomo.php"domains:"www3.example.com":trackingEnabled: trueidSite: 21excludedPaths:- "/admin/*"- "\\.\\w{1,5}(\\?.+)?$"includedPaths:- "\\.(php|aspx)(\\?.*)?$"pathOverrides:"/subdir":trackingEnabled: trueidSite: 24excludedPaths:- "/test"- "/test2""/subdir2":trackingEnabled: falseidSite: 24"test.de":trackingEnabled: falseidSite: 456
Explanation:
matomo-tracking: This is the name of the plugin instance in Traefik.plugin: Denotes that the following configuration is for a plugin.matomoTracking: The name of your custom plugin. It references the code logic that you provided in your Go plugin implementation.matomoURL: Specifies the Matomo server's URL where the tracking data should be sent.domains: Contains specific tracking configurations for multiple domains:
"www3.example.com":
trackingEnabled: true: Enables tracking for www3.example.com.idSite: 21: Uses 21 as the Matomo site ID.excludedPaths: Specifies paths that should not be tracked. For example:
/admin/*: Excludes all paths under /admin.\\.\\w{1,5}(\\?.+)?$: Excludes files with extensions between 1 and 5 characters, and optionally followed by query parameters.includedPaths: Specifies paths that should be tracked, even if they are excluded.
For example:
\\.(php|aspx)(\\?.*)?$: Includes files with extensions .php and .aspx, and optionally followed by query parameterspathOverrides: The pathOverrides block allows you to define more specific tracking settings for particular path prefixes under the domain. These overrides take precedence over the domain-level settings, but only for requests that match the specified paths.
Matching is based on prefix matching with path boundary awareness, meaning:
/subdir matches /subdir and /subdir/test, but not /subdir2."/subdir":
trackingEnabled: true: Enables tracking for paths under /subdir, even if other paths are excluded.idSite: 24: Overrides the site ID used for this specific path.excludedPaths: Within /subdir, /subdir/test and /subdir/test2 are excluded from tracking."/subdir2":
trackingEnabled: false: Disables tracking entirely for any request under /subdir2.idSite: 24: Still defines an ID, but it is unused since tracking is disabled here."test.de":
trackingEnabled: false: Disables tracking for test.de.idSite: 456: Uses 456 as the Matomo site ID.Main logic of the middleware:
pathOverrides are defined, the middleware:
mergeConfigs.excludedPaths and includedPaths.Merges a domain-level configuration with a path-level override.
Sends a tracking request to Matomo asynchronously:
User-Agent and X-Forwarded-For headers to identify the client.Checks if a given path matches any of the exclusion patterns:
excludedPaths.false immediately, indicating the path is not excludedincludedPaths, the function returns false, indicating that the path should not be excluded, as it is explicitly included.Step 1: Load/import the plugin into traefik
Edit your Traefik static configuration file (e.g., traefik.yml or traefik.toml), and add the plugin's Github repository:
Example: traefik.yml:
experimental:plugins:matomoTracking:moduleName: "github.com/DIE-Bonn/MatomoTracking"version: "v1.1.0"
Ensure to use the current version tag.
Step 2: Configure Dynamic Configuration
Create a new or use an already existing dynamic configuration file (e.g., dynamic.yml) that defines how the plugin should behave:
Example dynamic.yml:
http:middlewares:matomo-tracking:plugin:matomoTracking:matomoURL: "https://matomo-staging.die-bonn.de/matomo.php"domains:"www3.die-bonn.de":trackingEnabled: trueidSite: 21excludedPaths:- "/admin/*"- "\\.\\w{1,5}(\\?.+)?$"includedPaths:- "\\.(php|aspx)(\\?.*)?$"pathOverrides:"/subdir":trackingEnabled: trueidSite: 24excludedPaths:- "/test"- "/test2""/subdir2":trackingEnabled: falseidSite: 24"kansas-suche.de":trackingEnabled: falseidSite: 456
matomo-tracking middleware, consisting of domain names with their individual tracking configuration.Step 3: Associate the middleware plugin to the entrypoint
Edit your Traefik static configuration file traefik.yml:
Example traefik.yml:
entryPoints:webinsecure:address: ":80"http:middlewares:- matomo-tracking@file
matomo-tracking plugin can analyze all incoming requests to decide which requests will be sent to the matomo server for tracking purposes.Step 4: Restart Traefik
Start or restart traefik to load the plugin and apply the new configuration
docker compose down && docker compose up -d