Skip to main content

Configuration reference

Every key, its environment variable and the value shipped in the package. This page — not your published config/matomo-analytics.php — is the authoritative list, because a key your file does not contain still has its default. See configuration for why.

A key with an environment variable can be set either way. A key without one is a structure, and is edited in the file.

Connection and master switch​

KeyEnvDefaultMeaning
enabledMATOMO_ENABLEDfalseMaster switch. Installing the package tracks nobody until you set this to true.
hostMATOMO_HOST—Base URL of your Matomo. Everything else is derived from it.
site_idMATOMO_SITE_ID—The Matomo site id.
site_id_resolver—nullfn(): ?int — an invokable class-string or closure that may name the site for the hit being built. A positive int names the site, and so does a string of digits, the form a site id takes in configuration; null, or anything else, falls back to site_id. For multi-tenant applications; see below.
require_tlsMATOMO_REQUIRE_TLSfalseRefuse to track over a plaintext host. With it on, an http:// host counts as unconfigured and nothing is tracked — the same no-op a missing host takes, never an exception. Off by default because Matomo on a private network without TLS is a legitimate deployment. What it protects: token_auth travels in the request body on every server-side hit.
tokenMATOMO_TOKEN—token_auth, server-side only. Needed for the real client IP, the time of a hit delivered more than a day late, and the read side.
tracker_pathMATOMO_TRACKER_PATHmatomo.phpPath to the tracking endpoint, relative to host.
js_pathMATOMO_JS_PATHmatomo.jsPath to the JavaScript tracker.
timeoutMATOMO_TIMEOUT5Request timeout in seconds for tracking calls.
http_options—[]Extra Guzzle request options for every tracking call, single and bulk, for an application whose HTTP middleware reads an option of its own. The sender's own options win over one of the same name: the timeouts, HTTP/1.1 and the refusal to follow a redirect. The Reporting API does not take them.

Tracking is a no-op while host or site_id is missing. See installation.

One site id per request​

site_id_resolver is the seam for an application that tracks each tenant into its own Matomo site. It is called while the hit's payload is built, so it decides per hit rather than per process:

'site_id_resolver' => fn (): ?int => Tenant::current()?->matomo_site_id,

It takes no arguments on purpose — the tenant is a property of your own request context, which the callback already has.

A buffered batch may therefore carry hits for several sites, and that is fine. Each buffered hit holds its own idsite, and Matomo's Bulk endpoint accepts a mixed batch. This is why the seam is a resolver rather than a per-request connection: rebuilding the connection would not fix the buffer, and this does.

Anything other than a positive int falls back to site_id — null, a string, a negative, and a resolver that throws. Tracking never breaks the caller, and that has to include an extension point the package cannot see.

These seven values are read once and then held for the life of the process. In an ordinary request that is invisible, because the process ends with the response. In a long-lived one — a queue:work or matomo:work worker, or Octane — the values the process resolved first are the values it keeps, and changing the configuration underneath it does nothing until it restarts.

It matters in one shape: an application that repoints this package per request or per tenant, so that each tenant tracks into its own Matomo site. There the worker sends every tenant's hits to whichever site it saw first. The way to do it is a tracking gate plus custom dimensions, which read live configuration on every hit — not by swapping the connection under a running worker, which does not work for the reason the Octane guide sets out.

Transmission​

KeyEnvDefaultMeaning
modeMATOMO_MODEqueuequeue, sync or batch.
schedule.run_in_backgroundMATOMO_SCHEDULE_BACKGROUNDtrueRuns both scheduled commands off your scheduler, so a slow Matomo never delays another task. Costs you the failure report: from Laravel 12.11 on, Laravel raises a scheduled command's non-zero exit only in the foreground, so a background one reaches neither ScheduledTaskFailed nor your exception handler. Set it to false when that report matters more than the wait, or attach onFailure() through configureSchedule(), which sees a failed run on every supported version.
queue.connectionMATOMO_QUEUE_CONNECTIONnullQueue connection; null uses the default.
queue.queueMATOMO_QUEUEmatomoQueue name. Your worker must serve it.
queue.triesMATOMO_QUEUE_TRIES5Delivery attempts before the batch is dead-lettered. A value that is not a whole number of at least 1 keeps 5.
queue.backoff—[30, 120, 300, 900]Seconds between retries, escalating.
queue.retry_until_minutesMATOMO_QUEUE_RETRY_UNTIL_MINUTES1440Outer bound on retrying. queue.tries normally ends the loop first. A value that is not a whole number of at least 1 keeps 1440.

See transmission modes.

Batch buffer​

KeyEnvDefaultMeaning
batch.driverMATOMO_BATCH_DRIVERdatabaseBuffer store: database, redis, file or array.
batch.sizeMATOMO_BATCH_SIZE200Hits per Bulk request, and therefore how many requests a backlog costs — 2000 hits against a Matomo answering in 20ms take 1021ms at 50, 276ms at 200 and 125ms at 500. It is also the memory knob: a claimed batch is held at roughly 2.3 KB per hit.
batch.flush_intervalMATOMO_BATCH_INTERVAL60Seconds between passes of the matomo:work daemon.
batch.max_per_flushMATOMO_BATCH_MAX_PER_FLUSH2000Cap on hits moved by a single flush pass.
batch.stale_after_minutesMATOMO_BATCH_STALE_AFTER_MINUTES15Reclaim a claimed-but-unacknowledged batch after this long. Floored at one minute: at zero every claim expires the moment it is made, and at-least-once delivery becomes guaranteed double delivery.
batch.redis_connectionMATOMO_BATCH_REDISdefaultRedis connection for the redis driver.
batch.table—matomo_tracking_bufferTable for the database driver.
batch.pathMATOMO_BATCH_PATHnullSpool directory for the file driver; unset means storage/app/matomo-analytics.
batch.max_attemptsMATOMO_BATCH_MAX_ATTEMPTS25Consecutive failed flushes before a stuck batch is dead-lettered.
batch.dead_letter.enabled—trueMove undeliverable batches to the dead-letter store.
batch.dead_letter.retention_daysMATOMO_DEAD_LETTER_RETENTION_DAYS30Days a dead letter is kept before the daily prune deletes it. 0 keeps them forever; a negative value, or one that is not a whole number, keeps 30.
batch.dead_letter.table—matomo_dead_lettersDead-letter table.

The max_attempts counter lives in the cache and therefore needs a persistent cache store — see reliability.

Resilience and alerting​

KeyEnvDefaultMeaning
resilience.never_throw—trueTracking errors never bubble into the application.
resilience.connect_timeoutMATOMO_CONNECT_TIMEOUT2Connection timeout in seconds.
resilience.reporting.report_after_attemptsMATOMO_REPORT_AFTER_ATTEMPTS3Report only after this many failures.
resilience.reporting.channelMATOMO_REPORT_CHANNELreportreport (exception handler plus log), log, or silent.
resilience.reporting.level—warningLog level for a reported failure.
resilience.reporting.transient_level—nullLog level for each retry; null logs none.
resilience.reporting.throttle_minutesMATOMO_REPORT_THROTTLE_MINUTES15Throttle window per error signature. 0 disables throttling.

Reporting (read side)​

KeyEnvDefaultMeaning
reporting.pathMATOMO_REPORTING_PATHindex.phpPath to the Reporting API.
reporting.timeoutMATOMO_REPORTING_TIMEOUT10Request timeout in seconds for report calls.
reporting.default_periodMATOMO_REPORTING_PERIODdayPeriod used when a call omits one.
reporting.default_dateMATOMO_REPORTING_DATEtodayDate used when a call omits one.
reporting.segments—[]Named-segment registry: key to Matomo segment definition.
reporting.cache.enabled—trueCache report responses.
reporting.cache.storeMATOMO_REPORTING_CACHE_STOREnullCache store; null uses the default.
reporting.cache.prefix—matomo-analytics:reportCache key prefix.
reporting.cache.ttl.live—60Seconds for realtime counters.
reporting.cache.ttl.today—300Seconds for a span that reaches today: today, lastN, the current week, month or year, a range ending today.
reporting.cache.ttl.recent—900Seconds for a span that ended yesterday, and for previousN.
reporting.cache.ttl.historical—3600Seconds for fully archived past periods.

See reporting and queries and segments.

Visitor identity​

KeyEnvDefaultMeaning
visitor.rotate—dailyCookieless salt rotation: daily, weekly or never.
visitor.user_id—nullauth attaches the authenticated user id as the Matomo User ID; null attaches none.
anonymize_ip—trueTruncate the client IP before sending it: an IPv4 address to its first three octets (a /24), an IPv6 address to its first 48 bits.
ip_headerMATOMO_IP_HEADERnullForwarding header carrying the real client IP, read from the right of the chain. Trusted without verification — read the warning.
ip_header_trusted_hopsMATOMO_IP_HEADER_TRUSTED_HOPS1How many trusted proxies append to ip_header; the client is that many entries from the right.

Tracking gate​

KeyEnvDefaultMeaning
tracking.environments—nullRestrict tracking to these environments; null or [] means all. @matomoScript follows it as well.
tracking.track_authenticated—trueTrack logged-in users.
tracking.skip_prefetch—trueRefuse every hit of a request the browser announced as speculative, an event or a page view your application sends while rendering it included. See Prefetched and prerendered pages.
tracking.except_abilities—[]Skip users who pass any of these Gate abilities.
tracking.except_ips—[]Skip these client IPs or CIDR ranges.
tracking.except_routes—['horizon*', 'telescope*', 'nova*', 'up', 'health*', 'livewire/*', 'livewire-*/*']Skip these request-path patterns. A hit from a Livewire component action is matched by the page it was sent from. @matomoScript renders nothing on a matching page.
tracking.gate—nullInvokable class-string or closure for full control.

See the tracking gate.

Privacy​

KeyEnvDefaultMeaning
privacy.honor_dnt—trueSkip tracking on DNT: 1 or Sec-GPC: 1.
privacy.cookieless—truePush disableCookies in the client snippet.
privacy.consent—noneClient consent posture: none, cookie or full. Any other value is read as full.
privacy.opt_out.respect—trueHonor the first-party opt-out cookie.
privacy.opt_out.cookie—matomo_opt_outName of that cookie.
privacy.redact.enabled—trueStrip secrets and PII from tracked URLs.
privacy.redact.replacement—REDACTEDValue a redacted parameter is replaced with.
privacy.redact.query_params—A list of token, password, secret, signature and session parameter names, and the signature and credentials of a presigned S3 or GCS URLParameters whose value is replaced; the key is kept. Matched case-insensitively.
privacy.redact.path_params—['token']Route parameters whose value is a secret in a path. Every registered route whose URI names one has that segment redacted; the password-reset link is covered whatever the list says.
privacy.redact.patterns—[]Regular expressions applied to the URL. One PCRE cannot compile is refused with its own wording. One the URL makes fail, on bytes that are no UTF-8 under /u or past a backtracking limit, sends the replacement in place of the whole URL.
privacy.redact.keys—['url', 'urlref', 'link', 'download', 'c_t', 'c_p']Which payload fields are redacted. urlref covers _ref as well, the referrer matomo.js keeps for conversion attribution.

See consent and redaction for the full shipped parameter list and how to extend it.

Bots​

KeyEnvDefaultMeaning
bots.track—falseRecord bots and crawlers instead of excluding them.
bots.detect_ai_crawlers—trueUse the maintained AI/LLM crawler token list.
bots.detect_generic—trueUse the generic crawler signals.
bots.allow—[]User-Agent tokens always treated as human. Overrides every other layer.
bots.deny—[]User-Agent tokens always treated as bots.
bots.detector—nullExtra invokable class-string or closure, consulted last.

See bots and AI crawlers.

AI chatbot telemetry​

KeyEnvDefaultMeaning
ai_chatbots.track—falseMaster switch for AI-chatbot telemetry.
ai_chatbots.auto—falseAuto-register the matomo.chatbots middleware on the web group.
ai_chatbots.rec_mode—11 records bots only (Matomo discards non-bots); 2 lets Matomo decide.
ai_chatbots.source—LaravelLabel identifying this collector.
ai_chatbots.user_agents—nullRecognized fetchers; null uses the built-in on-demand list.

See AI assistants.

Page-view middleware​

KeyEnvDefaultMeaning
middleware.auto—falseAuto-register the page-view middleware on the web group.
middleware.only_get—trueTrack GET requests only.
middleware.only_successful—trueTrack delivered pages only: 2xx and 304.
middleware.only_html—trueTrack pages only: an HTML response or an Inertia visit, not JSON, a file, an image, a feed or a download.
middleware.skip_livewire—trueSkip Livewire update requests.
middleware.skip_partials—trueSkip htmx fragments, Turbo Frames, XHR and Inertia partial reloads that load part of a page.
middleware.skip_prefetch—trueSkip a request the browser announced as speculative (Sec-Purpose or Purpose carrying prefetch). A pointer resting on a link is not a visit. See Prefetched and prerendered pages.
middleware.strip_query—falseDrop the query string from the tracked URL, campaign parameters included.
middleware.client_hints—falseAsk the browser for the client hints that name the platform version, the device model and the full browser version (Accept-CH on HTML responses). See device and operating system.
middleware.performance—falseStamp the server generation time onto the page view.

See server-side tracking.

Client-side snippet​

KeyEnvDefaultMeaning
js.enabledMATOMO_JS_ENABLEDtrueRender the client snippet at all. Governs both @matomoScript and the <noscript> pixel.
js.hostMATOMO_JS_HOSTnullSeparate asset host for the tracker script; tracking stays on host.
js.tag_manager—nullFull Tag Manager container URL. When set, the container renders instead of the tracker.
js.enable_link_tracking—trueTrack outbound links and downloads.
js.performance—truefalse pushes disablePerformanceTracking.
js.custom_dimensions—[]Map of dimension id to value, set on every page view.
js.content_tracking—falsefalse, 'all' or 'visible'.
js.heartbeat—15Heartbeat timer in seconds; 0 disables it.
js.noscript—trueRender a <noscript> tracking pixel.
js.dns_prefetch—trueEmit a dns-prefetch hint for the Matomo origin.

See client-side tracking.

SPA​

KeyEnvDefaultMeaning
spa.enabledMATOMO_SPAfalseRecord a virtual page view on each soft navigation.
spa.adapters—['livewire', 'inertia']Which adapters to attach: livewire, inertia, generic.
spa.performance—trueForward an app-provided timing object per virtual page view.

See SPA and soft navigation.

Web Vitals​

KeyEnvDefaultMeaning
web_vitals.enabled—falseEnable the ingest route and the directive.
web_vitals.path—matomo-analytics/web-vitalsRoute path for the beacon endpoint.
web_vitals.category—Web VitalsMatomo event category the samples are recorded under.
web_vitals.metrics—['LCP', 'CLS', 'INP', 'FCP', 'TTFB']Accepted metrics. Also the allowlist the route validates against.
web_vitals.throttleMATOMO_WEB_VITALS_THROTTLE60,1Route throttle, "requests,minutes", counted per client address and per /64 for IPv6. null disables it; an absent key falls back to the shipped value rather than to no limit.
web_vitals.middleware—[]Extra middleware for the ingest route. Empty by default, because the browser beacons it with sendBeacon() and that carries no CSRF token — which also means no session is started there, so tracking.track_authenticated and tracking.except_abilities see a guest on this path. EncryptCookies followed by MatomoAnalytics\Http\Middleware\ReadSessionWithoutWriting applies them without writing the session; ['web'] applies them too, writes the session, and needs a CSRF exemption for this one route on your side.
web_vitals.library—nullScript URL for the web-vitals library; null means your app provides it.

See Web Vitals.

Prefetched and prerendered pages​

KeyEnvDefaultMeaning
prefetch_beacon.enabled—falseEnable the beacon route and the @matomoPrefetchPageView directive.
prefetch_beacon.path—matomo-analytics/page-viewRoute path for the beacon endpoint.
prefetch_beacon.throttleMATOMO_PREFETCH_BEACON_THROTTLE60,1Route throttle, "requests,minutes", counted per client address and per /64 for IPv6. null disables it; an absent key falls back to the shipped value rather than to no limit.
prefetch_beacon.middleware—[]Extra middleware for the beacon route. Empty for the same reason as web_vitals.middleware: sendBeacon() carries no CSRF token, so no session is started on this path. The same read-only session pair applies the visitor rules here.

See Prefetched and prerendered pages.

Hits from the browser​

KeyEnvDefaultMeaning
hit_beacon.enabled—falseEnable the hit route and the @matomoHitBeacon directive.
hit_beacon.path—matomo-analytics/hitRoute path for the hit endpoint.
hit_beacon.throttleMATOMO_HIT_BEACON_THROTTLE60,1Route throttle, "requests,minutes", counted per client address and per /64 for IPv6. null disables it; an absent key falls back to the shipped value rather than to no limit.
hit_beacon.middleware—[]Extra middleware for the hit route. Empty for the same reason as web_vitals.middleware: sendBeacon() carries no CSRF token, so no session is started on this path. The same read-only session pair applies the visitor rules here.
hit_beacon.event_categories—[]The only event categories a page may send. Empty allows every category.

See Hits without matomo.js.

Annotations​

KeyEnvDefaultMeaning
annotations.releaseMATOMO_ANNOTATE_RELEASESfalseEnable matomo:annotate --release.
annotations.starred—falseStar release annotations.
annotations.release_prefix—DeployedRelease note is the prefix followed by the version.

See release annotations.

Events​

KeyEnvDefaultMeaning
events—trueFire the package's Laravel events.

See events.

Keys your published config may still carry​

These keys are gone from the shipped config file. If you published the config in an earlier version, your copy still has them — and they do nothing. Deleting the lines changes nothing:

  • resilience.durability (and its MATOMO_DURABILITY variable) — never read by any code path; removed from the shipped config in 0.19.0
  • bots.record_ai_dimension — removed earlier

They are listed here rather than quietly dropped, because a reference that omits a key you can see in your own file is worse than one that explains it. Publishing the config again with --force gives you the current set, but overwrites your edits.

Every environment variable​

MATOMO_ENABLED=true
MATOMO_HOST=
MATOMO_SITE_ID=
MATOMO_TOKEN=
MATOMO_TRACKER_PATH=matomo.php
MATOMO_JS_PATH=matomo.js
MATOMO_TIMEOUT=5

MATOMO_MODE=queue
MATOMO_REQUIRE_TLS=false

MATOMO_QUEUE_CONNECTION=
MATOMO_QUEUE=matomo
MATOMO_QUEUE_TRIES=5
MATOMO_QUEUE_RETRY_UNTIL_MINUTES=1440

MATOMO_BATCH_DRIVER=database
MATOMO_BATCH_SIZE=200
MATOMO_BATCH_INTERVAL=60
MATOMO_BATCH_REDIS=default
MATOMO_BATCH_PATH=
MATOMO_BATCH_STALE_AFTER_MINUTES=15
MATOMO_BATCH_MAX_ATTEMPTS=25
MATOMO_DEAD_LETTER_RETENTION_DAYS=30

MATOMO_SCHEDULE_BACKGROUND=true

MATOMO_REPORT_CHANNEL=report
MATOMO_REPORTING_PATH=index.php
MATOMO_REPORTING_TIMEOUT=10
MATOMO_REPORTING_PERIOD=day
MATOMO_REPORTING_DATE=today
MATOMO_REPORTING_CACHE_STORE=

MATOMO_IP_HEADER=
MATOMO_JS_ENABLED=true
MATOMO_JS_HOST=
MATOMO_SPA=false
MATOMO_ANNOTATE_RELEASES=false

Only MATOMO_HOST and MATOMO_SITE_ID have no usable default — everything else can be left unset. MATOMO_ENABLED has a default, but it is false, so it is the one you must set to start tracking.

MATOMO_URL is not read. It was accepted as an alias until 0.16.0, which meant an application configuring its own, separate Matomo integration through that key was activating this package as well.