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.

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 }