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.
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.
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([...]);.
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.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./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.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.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.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.doTrack* call you want them attached to, and unset them afterwards if you make further calls in the same request.request()->userAgent() or an X-Requested-With check saves you cleanup later.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.How can I help you explore Laravel packages today?