set-up · vercel · log drain
Vercel log analytics, from a log drain
Vercel log analytics starts with Vercel's own request logs. A log drain posts every request your site answered to Skald, with nothing to change in your site's code.
Vercel log analytics is reading the requests Vercel served for your site, not only the browsers that ran a script. Vercel keeps its request logs to itself, but a Log Drain, on Vercel Pro or Enterprise, posts them to an address you give it. Skald reads Vercel's drain format directly.
30-day free trial · no card · we set it up within one working day · free to self-host
- 09:14:02 203.0.113.24 "GET /pricing" 200 static "GPTBot/1.2"AI · training
- 09:14:04 198.51.100.140 "GET /docs" 200 lambda "Claude-User/1.0"AI · live fetch
- 09:14:05 198.51.100.23 "GET /docs" 200 static ref "chatgpt.com"people · from ChatGPT
- 09:14:07 203.0.113.66 "GET /blog" 200 edge "bingbot/2.0"search
- 09:14:09 192.0.2.91 "GET /wp-login.php" 404 static "python-requests"bots · probe
Sample records from a drain. A script tag would have seen one of these five: the person.
[01] your vercel plan
What Skald sees on your Vercel plan
Server log analytics needs a record of every request. On Vercel that record is a Log Drain, and Log Drains are a Vercel Pro and Enterprise feature. Your plan is in Vercel's Settings > Billing.
A log drain: everything
Vercel posts every request to Skald. You see people, AI assistants such as ChatGPT, Claude and Perplexity, search crawlers, bots, and your own traffic, in five groups that add up to the whole log. Add the script tag too, for forms, clicks and bookings.
The script tag only
No drain on Hobby, so Skald has only the script tag. You see people, sources, forms, bookings and conversions. You do not see AI assistants or crawlers: they never run scripts. A Pro trial lets you see everything.
| Seen | Log drain |
|---|---|
| People and their sources | yes |
| AI live fetches and training crawls | yes, each one named |
| Search crawlers | yes |
| Bots and scanners | yes |
| Forms, clicks, bookings | with the script tag beside it |
[02] where skald runs
Skald runs beside Vercel, not on it
Skald keeps its history on a disk and runs its own schedule all day. Vercel's functions stop between requests and keep no disk, so Skald runs somewhere that stays up, and Vercel sends it your site's traffic.
Hosted Skald
We set it up for you on app.skaldanalytics.com within one working day. Then you add the drain.
Render or Railway
One service from the Skald image with a disk. On Render a disk needs a paid instance: without one the history is lost at every restart.
A small server
Docker on any small Linux server, with a name such as
stats.example.comand HTTPS, which sign-in needs.
[03] the log drain
Set up the Vercel log drain, step by step
In Skald, Settings > Connections > Send this site's visits to Skald, then Vercel. The dialog shows your send address and makes a sending token. Then in Vercel:
Team Settings > Drains > Add Drain > Logs
Projects: your site's project. Sources:
static,edge,lambda, plusexternalandredirectif you rewrite or redirect to other domains. Leave outbuild. Environments:production.Sampling: 100%
A sample would undercount every figure. Skald never scales one up.
Destination: custom endpoint
https://stats.example.com/traffic-ingest/example.com?format=vercel, with your own Skald and site. Format: JSON or NDJSON; both work.Custom header
Authorization: Bearer <your sending token>. Create the drain: Vercel tests the address, and Skald answers 200.Keep IP Address Visibility on
Team Settings > Security & Privacy. Without the visitor's address Skald cannot tell people apart, so it refuses those requests and counts them as rejected.
[04] what is kept
What Skald keeps from each Vercel record
The time, the visitor's address, the host, method, path and query, status, referrer, user agent, response size and the request id. Everything else in the record is dropped before anything is written.
- Function output, build logs and background revalidations are not requests: Skald skips them and counts them as skipped.
- A request whose function wrote several log lines is read once, by its request id.
- A delivery Vercel retries is kept once.
- Records for host names that are not your site's, such as a test's sample records, are kept but never counted.
Vercel's signature (optional)
Vercel signs each delivery with the drain's secret. To require it, the person who runs your Skald puts the secret in an environment variable and names it in Skald's config. A delivery with a wrong or missing signature is then refused, even with a token.
ingest:
enabled: true
drains:
example.com:
vercel_secret_env: SKALD_VERCEL_DRAIN_SECRET # the variable's name, not the secret
A secret that is named but cannot be read refuses every delivery, never lets one through. Details: HOSTING.md on GitHub.
[05] what a log cannot see
Add the script tag for forms, clicks and bookings
A drain sees requests, not what happens inside a page. The tag reports forms started and sent, clicks, scroll depth and booking embeds such as Calendly. It needs nothing on Vercel: it posts to Skald directly.
To serve it from your own domain instead, so fewer ad blockers stop it, add two rewrites to vercel.json and tell Skald your site's address. Skald leaves those two paths out of the drain's figures.
{
"rewrites": [
{ "source": "/traffic-beacon", "destination": "https://stats.example.com/traffic-beacon" },
{ "source": "/traffic-js/:path*", "destination": "https://stats.example.com/traffic-js/:path*" }
]
}
Put your own Skald's address in place of stats.example.com. In Next.js, the tag goes in the root layout.
[06] check it
Check that Vercel's logs reach Skald
Open your site in a private window. Within minutes the visit shows in Skald's live view, and the dialog's Test says what arrived, or why it was refused, with the fix.
| You see | What to do |
|---|---|
| Vercel says the drain test failed | Your Skald is not reachable over HTTPS yet, or the site name in the address is wrong. |
| Nothing in Live after 10 minutes | Check the drain's sources and environments, and the site's host names in Skald. |
| Rejected: no visitor address | Turn IP Address Visibility on in Vercel. |
What it does not do
- No drain on Vercel Hobby. There, Skald has only the script tag, which never sees AI crawlers, search crawlers or bots.
- No country in Vercel's records. Countries come only from a GeoIP file on Skald's server; without one they say Not recorded.
- On a Next.js site, a page opened by a click inside the site is not counted from the drain: its records carry no request headers. Only the first page of each visit shows.
- Skald cannot run on Vercel itself. It runs beside it, hosted or on a server you choose.
- No middleware road: Vercel's middleware runs before the response exists, so it cannot see the status.
keep reading
More on Vercel log analytics
questions
Vercel log analytics FAQ
Straight answers, including what Skald does not do.
Which Vercel plan do I need for Skald?
Log Drains are a Vercel Pro and Enterprise feature, so the full picture needs Pro or Enterprise. On Hobby, Skald can use only the script tag: you see people, sources, forms and bookings, but not AI assistants or crawlers, because they never run scripts.
Can Skald run on Vercel?
No. Skald needs an always-on process and a disk for its history, and Vercel's functions stop between requests and keep no disk. Skald runs beside your site instead: hosted Skald, or your own copy on Render, Railway or a small server, and Vercel posts the site's requests to it.
Why not use Vercel middleware instead of a log drain?
Vercel's Routing Middleware runs before the response is made, so it cannot see the status or the cache result of a request. A log drain is sent after Vercel answered, with the status, so Skald uses the drain.
Why do my Vercel visits have no country?
Vercel's drain records carry no country. Skald looks each address up in a GeoIP country file when the person who runs your Skald server has set one. Without a file, the country says Not recorded, and it is never guessed.
Does a Next.js site on Vercel count every page?
Not from the drain alone. A click inside a Next.js site loads no new HTML page, and the drain's records carry no request headers, so Skald cannot tell a click from a prefetch and counts neither. Only the first page of each visit shows as a page view. The script tag reports in-site page views as its own events, kept apart.
Is the drain's data checked like a server log?
Yes. Skald keeps each drain record as one line and an independent audit recounts it with its own reader. A day the two counts disagree on is withheld, never guessed.
$ tail -f access.log | skald
See what AI does with your site. Free for 30 days.
No card. We set up hosted Skald for you within one working day, or you self-host it free. Every line of your log, sorted and added up.