Vercel
Vercel analytics without a script. Point a Vercel Log Drain at MetrikStack and every page request served by Vercel is counted, bots and AI crawlers included.
A Vercel Log Drain forwards
your deployment's logs to any HTTPS endpoint. Point one at
POST /v1/logs/vercel and MetrikStack turns the request logs into
pageviews, without any code in your app or script on the page.
Drains are a Vercel feature of the Pro and Enterprise plans, and Vercel bills them per GB sent. On Hobby, use the browser script.
Create a source of kind logs for the site in the dashboard to get an
ingest token (in_…).
Set up the drain
- Vercel dashboard → your team → Observability → Drains → Add Drain, choose Logs and a Custom endpoint.
- Endpoint:
https://api.metrikstack.com/v1/logs/vercel - Format:
NDJSON(aJSONarray is accepted too). - Sources:
StaticandFunction(lambda/edge). Build, firewall and external logs can stay off; MetrikStack skips them anyway. - Environments:
Production(addPreviewif you want preview traffic counted in the same site). - Custom headers:
Authorization: Bearer in_…. - Save. Vercel verifies the endpoint right away (see below).
If the drain UI you are using cannot set headers, put the token in the URL
instead; every /v1/logs/* endpoint accepts it as a query parameter:
https://api.metrikstack.com/v1/logs/vercel?token=in_...A token in a URL ends up in Vercel's project settings and in request logs, so use the header when you can, and rotate the token from the dashboard if it leaks.
Endpoint verification
Before it starts sending, Vercel probes the endpoint and requires the
response to carry an x-vercel-verify header with the value shown in the
Vercel UI. Set that value as vercel_verify in the source's config
(dashboard or API).
The header is on every response of /v1/logs/vercel, including GET
(which is what Vercel probes) and error responses, so a mistyped token
doesn't block verification.
Signature checking (optional)
Vercel signs each delivery with x-vercel-signature, the hex SHA-1 HMAC of
the raw request body keyed with the drain's secret. Configure the secret as
vercel_secret in the source config, and every unsigned or mismatched
delivery is rejected with 403. With no secret configured the signature is
ignored and the bearer token is the only credential.
What becomes a pageview
An entry counts when all of the following hold:
sourceisstatic,lambdaoredge, and the entry has aproxyobject, meaning it describes a real request and not build output or a function'sstdout;proxy.methodisGETorHEAD;proxy.pathis not an asset path (same extension and prefix rules as every other source; see Access logs);- the status is not a 3xx redirect. A 304 counts: the browser checked whether the copy of the page it kept from an earlier visit is still current.
Everything else is counted in the response's skipped figure, not rejected.
Fields map like this:
| Vercel | MetrikStack |
|---|---|
proxy.path | path + query |
proxy.host | hostname |
proxy.method | method |
proxy.statusCode | status_code |
proxy.userAgent[0] | user agent (bot classification, device, browser) |
proxy.referer | referrer |
proxy.clientIp | visitor hash + GeoIP country, then dropped |
proxy.vercelCache, proxy.cacheId | cache_status |
timestamp (ms) | event timestamp |
requestId | request_id |
proxy.region is the Vercel edge region (fra1), not the visitor's
location, so it is not stored as a region; country comes from the client IP
at ingest.
Drains and the request-id merge
The drain only ever sees requests that go through Vercel's proxy. Traffic served by another CDN in front of Vercel, or by a rewrite to an external origin, never reaches it.
Vercel's requestId is the platform's own id. It is not the
X-MetrikStack-Request-Id that the Node SDK sets on the response, and a
drain entry carries no application response headers, so the two ids cannot
be matched. In practice:
- Drain as the only source: every page request is a pageview. This is the simplest and most accurate setup.
- Drain plus the tracker script or the Node SDK: there is no shared
request id, so merging falls back to the
60-second dedupe window on
(site, visitor, path). That works for most sites. The drain adds the cached and bot traffic the script never sees; the script adds screen size, language, time on page and in-app navigation in single-page apps.
Response
{ "accepted": 42, "skipped": 118, "rejected": [] }skipped covers build logs, function output, assets, redirects and
non-GET requests. Batches arrive in near real time, and Vercel retries
failed deliveries, so a short outage on our side doesn't lose data.
WordPress
WordPress analytics without cookies. The MetrikStack plugin adds the browser script, tracks pageviews server-side, or both, and counts each view once.
Netlify
Netlify analytics without a script. Send your site's traffic logs to MetrikStack with a Netlify log drain and count every page request, bots included.