Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Piwik Laravel Package

robbrazier/piwik

Laravel package that integrates the Piwik (Matomo) analytics API into your app, providing a simple facade to track visits and query reports, stats, and metrics without writing raw API calls.

View on GitHub
Deep Wiki
Context7

Getting Started

robbrazier/piwik is a thin Laravel wrapper around the Piwik/Matomo PHP tracker. It gives you a Piwik facade so you can fire server-side tracking requests without hand-rolling cURL calls. As of 4.2.0 it also ships a small reporting layer (DevicesDetection and UserCountry modules), so the package is no longer purely write-only.

composer require robbrazier/piwik

On Laravel 5.5+ the service provider and Piwik alias are auto-discovered. On older versions add RobBrazier\Piwik\PiwikServiceProvider::class to config/app.php and alias 'Piwik' => RobBrazier\Piwik\Facades\Piwik::class.

Publish the config and set the three values you actually need — host, site ID, and token:

php artisan vendor:publish --provider="RobBrazier\Piwik\PiwikServiceProvider"
PIWIK_URL=https://analytics.example.com
PIWIK_SITE_ID=1
PIWIK_TOKEN_AUTH=anonymous

The first use case is almost always the same: you have a page view or action that the browser-side JS tag cannot see — a redirect, a form POST, a queued job, an API endpoint, or a checkout success page. Track it straight from the controller:

use RobBrazier\Piwik\Facades\Piwik;

Piwik::doTrackPageView('Checkout complete');
Piwik::doTrackEvent('Orders', 'Purchased', 'sku-123', 49.99);

The facade proxies calls to the underlying PiwikTracker, so the method names are the tracker's doTrack* methods (doTrackPageView, doTrackEvent, doTrackGoal, doTrackSiteSearch, doTrackAction), not Laravel-styled names. When in doubt, read the PiwikTracker source or the package README — that is the real API surface.

If you also need to read data, 4.2.0 introduced report modules. Start with UserCountry and DevicesDetection:

Piwik::getUserCountry(/* see module source for exact signature */);
Piwik::getDeviceType(/* ... */);

Reporting calls are a different code path from tracking: they hit the Matomo Reporting API, need a real token_auth with view access to the site, and are not fire-and-forget.

Implementation Patterns

Wrap the facade in your own service. Never sprinkle Piwik:: through controllers. One AnalyticsTracker class with methods like pageView(), purchase(), signup() gives you a single place to guard, log, and later swap providers.

final class AnalyticsTracker
{
    public function purchase(Order $order): void
    {
        if (! config('analytics.enabled')) {
            return;
        }

        Piwik::setUrl(route('orders.show', $order));
        Piwik::setUserId((string) $order->user_id);
        Piwik::doTrackGoal(1, (float) $order->total);
    }
}

Set request context once with middleware. URL, user agent, IP, and user ID are global tracker state. A small middleware that calls setUrl, setIp, setUserAgent, and setUserId before the controller runs keeps every downstream tracking call consistent without repeating four lines everywhere.

Track domain events, not routes. The best integrations call the tracker from listeners (OrderPaid, UserRegistered) or after a queued job completes, so tracking works identically for web and CLI entry points.

Use goals and revenue for anything financial. doTrackGoal($goalId, $revenue) is the cleanest way to get conversions and revenue into Matomo without an e-commerce integration. Pair it with doTrackEvent for the granular funnel steps.

Cache reporting calls; never call them in a hot path. The 4.2 reporting modules (DevicesDetection, UserCountry) are synchronous API round trips against Matomo. Put them behind Cache::remember() with a 5–60 minute TTL, or behind a scheduled job that writes to your own table. A dashboard widget firing a report per page load will hammer your Matomo instance.

Keep a separate reporting wrapper. Because reporting needs a privileged token and different error handling, don't reuse AnalyticsTracker. An AnalyticsReporter with countryBreakdown(), deviceSplit() methods keeps the anonymous tracking token away from the read token, and keeps your 500-page safe if Matomo's reporting API is slow.

Guard with a config flag. Add an analytics.enabled key driven by APP_ENV so local dev and CI never hit the analytics host. This also makes tests deterministic. Add a second flag (analytics.reporting.enabled) if reporting is only used by admin dashboards.

Mock at the facade in tests. Piwik::shouldReceive('doTrackGoal')->once()->with(1, 49.99); is enough; you do not need HTTP fakes because the facade is the boundary. Same for reporting: Piwik::shouldReceive('getUserCountry')->andReturn([...]);.

Gotchas and Tips

  • Synchronous HTTP on the request thread. Every doTrack* call is a blocking request to your Matomo instance. A slow or down analytics server will slow or break checkout. Wrap calls in try/catch, log failures, and never let a tracking exception bubble to the user. For anything non-trivial consider dispatching after the response or from a queue.
  • State leaks between calls. The tracker is a singleton for the request. setSiteId, setUrl, setCustomVariable, and setUserId persist until changed. If you track two different users or pages in one request (a loop, a bulk import), reset or re-set the relevant fields before each call, otherwise the second event inherits the first event's context.
  • Piwik vs Matomo naming. The project was renamed Matomo years ago. The tracking endpoint may be /matomo.php rather than /piwik.php depending on your install version; confirm the URL in config matches what your server actually exposes.
  • anonymous token only works for tracking. Reporting API calls — including the new 4.2 UserCountry and DevicesDetection modules — need a real token_auth with at least view access to the site. Tracking-only usage is fine with the default; the moment you call a report method with anonymous you get an empty or error response.
  • Report method signatures changed within 4.2.0 itself. Commit bc78d84 removed idSite/period parameters from the module methods that do not support them. If you pinned early 4.2.0 code or copied signatures from a dev branch, re-check the released source before upgrading — passing extra args will at best be ignored and at worst error.
  • HTTPS and scheme mismatches fail silently. If your app is HTTPS but the configured host is HTTP, browsers and some proxies will drop the request and you will see nothing in the dashboard. Verify the reported URL, not just the return value. The same applies to reporting: a URL mismatch surfaces as an empty result set, not an exception.
  • The facade returns the tracker, not a response object. Don't expect a boolean or status from doTrackPageView(). If you need to know whether tracking succeeded, you have to check the underlying request yourself or log around the call. The report methods likewise return arrays/collections rather than typed DTOs — validate the shape before rendering.
  • Re-run php artisan config:cache after changing env. The classic "I set PIWIK_SITE_ID and nothing changed" is a cached config. Doubly true when you swap in a real token_auth for reporting.
  • Custom variables and dimensions are per-hit. Set them immediately before the doTrack* call you want them attached to, and unset them afterwards if you make further calls in the same request.
  • Bulk tracking exists. If you are emitting many events in one request (imports, batch jobs), batch them instead of looping individual HTTP calls — one request, one round trip.
  • Filter bots and health checks. Cron hits, uptime pings, and search crawlers will pollute your data. A simple guard on request()->userAgent() or an X-Requested-With check saves you cleanup later.
  • Reporting coverage is still narrow. UserCountry and DevicesDetection are a starting point, not a reporting platform. Anything beyond country and device dimension lookups — e-commerce reports, funnels, segments, arbitrary API.get calls — still means hitting Matomo's Reporting API with a dedicated HTTP client (Guzzle, matomo-org/matomo-php-tracker for writes, or your own thin client for reads). Treat these modules as convenience accessors, not as a substitute.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels