Laravel
Server-side analytics for Laravel 11 and 12. A Composer package that records pageviews on your own queue after the response has been sent.
The Laravel package tags every HTML response with a request id and, after the response has been sent, puts one small event on your application's own queue. The request is never blocked and nothing is sent during it.
Requirements
- PHP 8.2+
- Laravel 11 or 12
- A working queue (the
syncdriver works too, but then the POST happens during the request)
Installation
Not published yet. The package is not on Packagist yet, so the command below does not work today. This page describes how it will work. Until then the browser script and the edge and log sources cover the same traffic.
composer require metrikstack/laravelThe service provider is auto-discovered. Publish the config if you want to edit it:
php artisan vendor:publish --tag=metrikstack-configSet the environment variables:
METRIKSTACK_TOKEN=your-site-token
METRIKSTACK_ENDPOINT=https://api.metrikstack.com
# optional
METRIKSTACK_ENABLED=true
METRIKSTACK_QUEUE_CONNECTION=redis
METRIKSTACK_QUEUE=metrikstack
METRIKSTACK_TRUST_PROXY="*"MetrikStack looks up the site from the token, so you don't configure a site id.
Middleware
The provider adds MetrikStack\Laravel\Middleware\TrackPageview to the
web middleware group, so tracking starts after composer require.
To register it yourself instead, drop it from the group and add it
explicitly in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
\MetrikStack\Laravel\Middleware\TrackPageview::class,
]);
})Only requests that satisfy all of the following are tracked:
- method
GETorHEAD Acceptheader containstext/html- the path is not an asset: not ending in
.js .css .png .jpg .jpeg .gif .svg .ico .woff .woff2 .ttf .map .json .xml .txt, and not under/_debugbar,/storage,/vendor,/build,/assets,/static
Both lists are configurable via ignore_extensions and ignore_paths.
Blade
Add the meta tag to your layout's <head>:
<head>
<meta charset="utf-8">
@metrikstackMeta
...
</head>It renders <meta name="metrikstack-request-id" content="...">, and
nothing on pages that aren't tracked. The id is also shared with every view as
$metrikstackRequestId if you'd rather render it yourself.
Custom events
use MetrikStack\Laravel\Facades\MetrikStack;
MetrikStack::track('signup', ['plan' => 'pro']);Custom events are queued the same way and, when raised during a request, carry that request's id so they line up with the pageview.
Why the request id matters
A pageview can be seen by more than one source: this package on the
server and the browser script in the page. Both send the same request_id,
so they are merged into one pageview (see How merging
works). The id reaches the browser in two ways, so it gets
through most setups:
<meta name="metrikstack-request-id">, from@metrikstackMetaServer-Timing: metrikstack;desc=<id>, read by the script viaperformance.getEntriesByType('navigation')[0].serverTiming, which works through CDNs where the meta tag might be cached away
The response also carries X-MetrikStack-Request-Id for debugging and log
correlation.
What is sent
These fields and nothing else:
| Field | Source |
|---|---|
name | pageview, or your custom event name |
url | full URL, query string stripped to utm_* and ref only |
referrer | Referer header |
request_id | UUIDv7 generated per HTML response |
ts | RFC 3339 timestamp |
status_code | response status |
method | GET / HEAD |
ip | $request->ip(), hashed and discarded at ingest |
user_agent | User-Agent header |
accept_language | Accept-Language header |
Never sent: cookies, session data, form/request bodies, headers beyond the three above, route parameters, authenticated user identity, or the full query string.
IP and proxies
ip is whatever $request->ip() returns. Behind a load balancer set
METRIKSTACK_TRUST_PROXY to * (trust the immediate peer) or to a
comma-separated list of proxy IPs/CIDRs. Leave it unset to use the
application's own TrustProxies configuration untouched. The IP is hashed
at ingest and the raw value discarded.
Delivery
MetrikStack\Laravel\Jobs\SendEvents POSTs {"events": [...]} to
{endpoint}/v1/batch with Authorization: Bearer <token>, a 5 s HTTP
timeout, 2 tries and a [5, 30] second backoff. After that the batch is
dropped, so a MetrikStack outage can't clog your queue. Nothing is sent
when enabled is false or the token is empty. The request id headers are
still set, so the browser script keeps working.
Node SDK
Server-side analytics for Node.js with middleware for Express, Hono and Next.js that records pageviews without slowing down responses.
WordPress
WordPress analytics without cookies. The MetrikStack plugin adds the browser script, tracks pageviews server-side, or both, and counts each view once.