ChatGPT, Perplexity, Claude and Google's AI read your pages from their own servers without running JavaScript, so script-based analytics can't see them. AI visibility uses your server's view instead: you send LogZuno the requests your server receives, and LogZuno classifies each one and checks crawlers against the addresses their operators publish.
1. Create a server key
Open Project settings → API keys and create a key with the Server traffic (AI visibility) scope. Keep it on your server: it vouches for your visitors' IP addresses. A server key can only send server traffic, and an ingest key can't send it.
2. Choose a collector
| Where your site runs | Collector |
|---|---|
| Vercel (Pro or Enterprise) | Vercel log drain: no code |
| Netlify (Enterprise) | Netlify log drain: no code |
| Anything else | Send requests to /v1/hits yourself, as below |
Ready-made collectors for Cloudflare Workers, Node.js and Next.js, Laravel and WordPress are built and will be listed here when their packages are published.
3. Send requests to /v1/hits
POST /v1/hits takes a hits list of up to 100 requests. Send them in batches after you respond, never in the request path.
# A server key (scope: Server traffic) is required: it vouches for the
# visitor's IP address, which LogZuno uses to verify crawlers and never stores.
curl -sS -X POST "${LOGZUNO_ENDPOINT:-https://api.logzuno.app/v1}/hits" \
-H "Authorization: Bearer $LOGZUNO_SERVER_KEY" \
-H "Content-Type: application/json" \
-w "\nHTTP %{http_code}\n" \
-d '{
"hits": [
{
"timestamp": '"$(date +%s)"',
"method": "GET",
"scheme": "https",
"host": "example.com",
"path": "/pricing",
"status": 200,
"user_agent": "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot",
"ip": "203.0.113.7",
"accept": "text/html",
"collector": "custom"
}
]
}'| Field | Required | What it is |
|---|---|---|
method | Yes | GET or HEAD (other methods are not pages) |
host, path | Yes | The requested host and path (path starts with /) |
ip | Yes | The visitor's address, as your server saw it. Used for verification, never stored |
collector | Yes | custom for your own code |
timestamp | No | Unix seconds; defaults to now |
scheme, query, status | No | https, the query string, and the status you answered |
user_agent, referrer, accept, sec_fetch_dest, sec_ch_ua | No | Request headers, as received |
signature, signature_input, signature_agent | No | Web Bot Auth headers, so signed agents such as ChatGPT's agent can be verified |
country | No | Two-letter country code, if your CDN provides it |
insert_id | No | A UUID, so a resent batch isn't counted twice |
LogZuno answers 202 with how many hits it accepted and how many it ignored (requests for images, scripts and other assets are ignored). The example above uses an address from a documentation range, so it will show as an impostor: a request claiming to be ChatGPT-User from outside OpenAI's published list. Real ChatGPT fetches arrive from OpenAI's addresses and show as verified.
What to send
Send page requests (GET or HEAD for HTML) from anything that isn't a mainstream browser, plus every request for /robots.txt, /llms.txt, /llms-full.txt and sitemaps. That keeps you well inside your allowance. Sending browser page loads too shows how many never ran your analytics script, at the cost of more allowance.
Allowance
Server requests have their own monthly allowance, separate from events: 10,000 to 100,000 a month depending on the plan, and 500 during the trial. Each project may send 100 to 1,000 requests a minute depending on the plan, where a batch counts as one. See pricing.