Docs

Simple Analytics

Privacy-friendly page statistics stored directly in the POD. No Google Analytics, no cookie banners, no external scripts. One line of code.

Setup

Add the tracking snippet to your Astro layout (or any HTML page):

<script src="https://YOUR-ADMIN-URL/t.js" data-api="https://YOUR-ADMIN-URL/api/hit" defer></script>

Replace YOUR-ADMIN-URL with the URL where your Orbiter admin runs. The snippet is also available as a copy-to-clipboard button on the Analytics page in the admin.

Under 500 bytes. No cookies. No fingerprinting. Respects Do-Not-Track. Uses sendBeacon for zero performance impact, with an image pixel fallback.

What's tracked

FieldSourceNotes
Page pathlocation.pathnamee.g. /blog/my-post
Referrerdocument.referrerOnly external referrers (same-host filtered)
Screen widthscreen.widthFor device type estimation
LanguageAccept-Language headerFirst language only
Bot flagUser-Agent pattern matchGooglebot, GPTBot, ClaudeBot, etc.

Not tracked: IP addresses, cookies, browser fingerprints, session duration, scroll depth, click events.

Bot detection

The tracking endpoint automatically flags known bot and AI agent user agents. The analytics dashboard shows human vs. bot traffic separately — so you can see what percentage of your readers are AI systems.

Detected agents include: Googlebot, Bingbot, GPTBot, ClaudeBot, PerplexityBot, FacebookExternalHit, LinkedInBot, TwitterBot, and others.

Agent Analytics

Beyond the human/bot split, flagged traffic is further classified into categories — visible as a human-vs-agent split bar, a daily trend chart, and a top-agent-pages table on the Analytics dashboard:

CategoryExamples
ai-crawlerGPTBot, ClaudeBot, Anthropic, Meta AI — training/indexing crawlers
ai-agentPerplexity, ChatGPT — user-driven agent fetches
rag-pipelineCohere — retrieval pipelines
searchGooglebot, Bingbot
feed-readerFeedbin, Feedly, NewsBlur, Miniflux, Inoreader
botAnything else matching a generic bot pattern

Per-agent breakdown (auth required)

GET /api/analytics/agents?days=30

{
  "agents": [
    { "type": "ai-crawler", "name": "ClaudeBot", "hits": 340, "lastSeen": "2026-08-06 10:00:00",
      "topPaths": [{ "path": "/posts/my-post", "hits": 120 }] }
  ],
  "period": 30
}

Daily agent-vs-human trend (auth required)

GET /api/analytics/agent-trend?days=30

{
  "trend": [{ "day": "2026-08-01", "human": 210, "agent": 45 }, ...],
  "totals": { "human": 6300, "agent": 1340 },
  "topAgentPaths": [{ "path": "/posts/my-post", "hits": 120 }, ...],
  "period": 30
}

Dashboard

Open Analytics from the admin sidebar (or g + y in Station mode). The dashboard shows:

  • Stats bar — total views, human views, bot views, top page
  • Daily chart — bar chart with human (purple) and bot (gold) views per day
  • Top pages — most viewed pages ranked by total views
  • Referrers — top traffic sources
  • Period filter — 7 days, 30 days, or 90 days

Data retention

Analytics data is stored in the _analytics table in the POD. To clean up old data:

DELETE /api/analytics/prune?days=90

This deletes all records older than the specified number of days. The default is 90 days.

API

Track a pageview (public, no auth)

POST /api/hit?p=/page-path&r=https://referrer.com&w=1920
GET  /api/hit?p=/page-path&r=https://referrer.com&w=1920  (returns 1×1 GIF)

Get analytics (auth required)

GET /api/analytics?days=30&path=/blog

{
  "total": 1234,
  "humans": 980,
  "bots": 254,
  "topPages": [{ "path": "/", "views": 456, "human_views": 400 }, ...],
  "topReferrers": [{ "referrer": "https://google.com", "count": 89 }, ...],
  "daily": [{ "date": "2026-06-20", "views": 42, "human_views": 35 }, ...]
}

Prune old data (auth required)

DELETE /api/analytics/prune?days=90
{ "ok": true, "deleted": 1500 }