Skip to main content

Configuration

Configuration lives in one file, config/matomo-analytics.php, published by matomo:install. This page explains how that file behaves and what each block is for. For the exhaustive key-by-key table, see the configuration reference.

You do not have to publish it

The package merges its own configuration underneath yours, and every value is read through a small typed accessor that carries an explicit default. Two consequences worth knowing:

  • No published file is needed. Set MATOMO_HOST and MATOMO_SITE_ID and the package works on its shipped defaults.
  • A key missing from your published file does not become null. It falls back to the default the code reads it with, which is the value shipped in the package's own config file.

That second point is what makes an upgrade safe: a release that adds a new setting does not require you to re-publish the config file before your application boots again.

What the merge does and does not do

Since 0.19.0 the merge recurses into nested sections. A block you published is no longer a ceiling: a key you never mentioned arrives with its shipped default, while every value you did set still wins. Before that release the merge was Laravel's flat one, so a published block replaced the shipped block whole and a subkey added by a later version was simply absent — privacy.redact.query_params answering [] is URL redaction quietly doing nothing.

Lists are deliberately not merged. A map is a namespace and gets merged key by key; a list is a value and is taken exactly as you wrote it, including when you emptied it. That is the whole point: merging lists by index would hand back entries you deleted on purpose, and for a privacy or bot list that means switching a setting back on behind your back.

One situation is still outside all of this, and it is worth stating plainly:

php artisan config:cache freezes the resolved configuration, and the framework skips merging for a cached config by design. Rebuilding the cache (php artisan config:cache) after an upgrade re-runs the merge and picks up everything added since — that rebuild is the fix, not re-publishing the file. Until then the only values that exist are the ones frozen in the cache, so the published file is not a complete picture of the effective configuration. The configuration reference is.

Environment variables or the file?

A setting with an environment variable can be set either way. A setting without one is a structure — a list, a map, a class-string — and belongs in the file.

Keep in .env: the connection (MATOMO_HOST, MATOMO_SITE_ID, MATOMO_TOKEN), the transmission mode (MATOMO_MODE) and its driver, and the per-environment switches (MATOMO_ENABLED, MATOMO_SPA).

Keep in the file: tracking.except_routes, tracking.except_ips, tracking.except_abilities, privacy.redact.query_params, privacy.redact.patterns, reporting.segments, js.custom_dimensions, bots.allow, bots.deny and every callable extension point.

Callables must be class-strings if you cache config

Two settings accept your own logic: tracking.gate and bots.detector. Both take either a closure or an invokable class-string. A closure in a config file cannot be serialized, so config:cache fails on it — prefer an invokable class-string:

'tracking' => [
'gate' => \App\Analytics\OnlyPayingCustomers::class,
],

The package resolves a class-string through the container, so the class can take constructor dependencies.

The blocks

BlockCoversPage
enabled, host, site_id, token, timeoutThe master switch and the connection.Installation
mode, queue, batchHow hits leave your application.Transmission modes
resilienceRetry, alerting and throttling behavior.Reliability
reportingThe read-side client, its cache and named segments.Reporting
visitor, anonymize_ip, ip_headerHow a visitor is identified and which IP is used.Server-side tracking
trackingWho gets tracked at all.The tracking gate
privacyConsent posture, opt-out cookie, URL redaction.Consent and redaction
botsBot and AI-crawler detection.Bots and AI crawlers
ai_chatbotsServer-side AI-assistant fetch telemetry.AI assistants
middlewareThe automatic page-view middleware.Server-side tracking
jsThe client-side snippet.Client-side tracking
spaVirtual page views on soft navigation.SPA and soft navigation
web_vitalsThe Core Web Vitals ingest route.Web Vitals
annotationsDeploy markers on the reports timeline.Release annotations
eventsWhether the package fires Laravel events.Events

The master switch

'enabled' => env('MATOMO_ENABLED', false),

It ships off. Installing the package tracks nobody until you set MATOMO_ENABLED=true — dormancy is the shipped state, not a side effect of an unset host. Once it is on, tracking.environments is the finer instrument, because it keeps the package live in production and inert elsewhere without a per-environment variable:

'tracking' => [
'environments' => ['production'], // null = every environment
],

Missing connection settings are a second belt: an environment without MATOMO_HOST is inert whatever the switch says.