Skip to main content

Installation

Requirements

  • PHP 8.4+
  • Laravel 12 or 13

Any release of either major. The constraints floor at ^12.0 and ^13.0 rather than at a later minor, so an application still on Laravel 12.0 installs the package as readily as one on the newest 13.x.

The package requires focused illuminate/* components rather than laravel/framework, so it adds no framework weight to an application that only uses part of Laravel.

Install

composer require pushery/matomo-analytics-for-laravel
php artisan matomo:install

The service provider is discovered automatically — there is nothing to register. matomo:install publishes config/matomo-analytics.php (every option is documented inline in that file) and prints the environment variables to set.

Publishing the config file is optional. The package merges its own defaults, and every setting is read with an explicit fallback, so the package is fully functional with no published file at all. Publish it when you want to change something that has no environment variable, such as tracking.except_routes or reporting.segments.

Point it at your instance

MATOMO_HOST=https://your-instance.matomo.cloud # or https://analytics.example.com
MATOMO_SITE_ID=1
MATOMO_TOKEN= # optional; see below
# MATOMO_MODE=batch # switch single -> batch transmission

MATOMO_HOST is the base URL of your Matomo — everything else is derived from it: the tracking endpoint, the Reporting API, the JavaScript tracker, the opt-out iframe and the no-script pixel. Only MATOMO_HOST is read — MATOMO_URL is not an alias for it.

Nothing is tracked until you set MATOMO_ENABLED=true. Installing the package does not start tracking anyone: dormancy is the shipped state, not a side effect of an unset host. Tracking additionally stays a no-op while MATOMO_HOST or MATOMO_SITE_ID is missing, so the package remains inert in local development and CI without any extra guard in your code, and no call site needs to know whether analytics is configured.

Should you set a token?

MATOMO_TOKEN is a token_auth and is used server-side only. Matomo only honors three things when a token is sent: the real visitor IP (cip), the exact hit time (cdt) and geolocation derived from that IP. Without a token, hits are attributed to your application server's IP and timed at the moment Matomo receives them.

That second point matters more than it looks. In the default queue mode — and much more so in batch mode, after a retry, or after a dead-letter replay — a hit can reach Matomo minutes or hours after the event happened. Set a token if you want server-side hits attributed and timed correctly. Use a dedicated tracking token rather than your personal one.

A token is also what the read side needs: see Reporting (view access) and GDPR requests (admin access).

Verify

php artisan matomo:test

matomo:test sends one real hit to the configured tracking endpoint and reports the HTTP status, so a misconfigured host, a firewall or a wrong site id surfaces immediately instead of as missing data a week later. It fails with a clear message when the package is not configured at all.

To confirm the read side as well:

php artisan matomo:report VisitsSummary.get

Database tables

Two tables back batch mode: the hit buffer and the dead-letter queue. The package registers its migrations automatically, so php artisan migrate creates them.

The buffer table is only touched in batch mode. The dead-letter table is written from queue mode too, so an application on the shipped default does use one of them. You can still opt out of the automatic registration — call this from a service provider's register() method — but switch batch.dead_letter.enabled off along with it, or the delivery path is left with nowhere to park an exhausted batch:

use MatomoAnalytics\MatomoAnalyticsServiceProvider;

MatomoAnalyticsServiceProvider::ignoreMigrations();

To manage the migrations in your own application instead, publish them and edit the copies.

⚠️ Publishing is only half of it — call ignoreMigrations() as well, or migrate breaks permanently. vendor:publish rewrites the 0001_01_01_00000N_ prefix to the publish date, and the migrator keys on the FILE NAME — so the copies are five different migrations, not replacements. Measured on both engines: ten migrations found instead of five, the bundled ones run, the published create then dies with a duplicate-table error, and every later migrate dies the same way.

// in a service provider's register()
MatomoAnalyticsServiceProvider::ignoreMigrations();
php artisan vendor:publish --tag=matomo-analytics-migrations
php artisan migrate

See Database tables for the schema of each table.

What else can be published

TagPublishes
matomo-analytics-configconfig/matomo-analytics.php — what matomo:install publishes.
matomo-analytics-migrationsThe batch-buffer and dead-letter migrations.
matomo-analytics-viewsThe privacy-policy partial, into resources/views/vendor/matomo-analytics.
matomo-analytics-langThe package translation files, into lang/vendor/matomo-analytics.

Next steps