Know which traffic
actually pays.

Connect every payment to the visit that caused it. Run the whole stack on your own server.

  • One Docker container
  • One SQLite file
  • No external services

Works with the stack you already run

Next.jsAstroReactSvelteKitWordPress ShopifyWebflowFramerPlain HTML

How it works

From one script tag to revenue clarity

No data team, no tagging plan, no 40-tab dashboard. Three steps, one afternoon.

01

Add one script tag

Paste 2.5 KB of JavaScript into your layout. Works with every framework, including single-page apps.

index.html
<script defer
  data-website-id="acme"
  src="/js/kestrel.js">
</script>
02

Connect your payments

Add a webhook or send a small JSON payload. Dodo Payments is native; Stripe and others work through the API.

Dodo PaymentsNative webhookConnected
StripeServer-side APIReady
PolarServer-side APIReady
03

See what actually pays

Open the dashboard and find the channels, pages and posts that create customers, not just clicks.

Revenue by source$9,412
ChatGPT$3,220
Google$2,180
X / Twitter$1,940
Newsletter$1,120

The part other tools skip

Traffic is easy.
Knowing what it earned is the point.

Kestrel stitches every payment back to the visit that caused it. Not a vanity dashboard: an attribution engine that answers the only question that matters.

  • Last non-direct touch. “Saw the tweet, came back 17 days later and paid” is credited to the tweet.
  • Works without metadata. Return page, customer history, identified email and checkout timing as fallbacks.
  • Every payment is explained. The Journey tab shows exactly how each one was matched.
  • Your payment stack. Dodo Payments built in, plus a generic API for Stripe, Lemon Squeezy, Polar and anything else.
Deploy Kestrel

Features

Small tracker. Serious answers.

All the reports you need to make decisions, none of the consent-manager-required, script-bloated, dashboard-slow baggage.

Revenue-first overview

Visitors, revenue, conversion, revenue per visitor, bounce rate and session time with period-over-period changes.

Visitors18.2k+24%
Revenue$9.4k+38%
Rev / visitor$0.52−3%

A real AI channel

ChatGPT, Claude, Perplexity and Copilot get their own channel, so you can see what the answer engines send you.

ChatGPTClaudePerplexity CopilotGeminiGrok
AI share of revenue20.6%+6.4 pts

Live activity

See who is on the site right now, the page they landed on and what they are doing. Addictive in a useful way.

/pricingChatGPT · Berlin
now
/blog/alternativesGoogle · London
12s
/X / Twitter · Austin
28s

Visitor journeys, not just pageviews

Click any visitor for a full timeline: visits, pages, goals, identified email and payments. See the exact path from first touch to checkout.

ChatGPT answerFeb 2 · /alternatives
Pricing pageFeb 3 · 2 sessions
Started checkoutFeb 4 · goal

Goals & funnels

Button clicks, custom events and multi-step funnels. No extra product, no per-goal pricing.

Visited pricing4,120
Started checkout1,730
Paid742

Shareable dashboards

Publish a read-only link for a client or investor. No account to create, revoke it any time.

Own the whole stack

One SQLite file. Back up the entire product with one command. No Postgres, no managed database bill.

kestrel.dbSQLite · 84 MB
Yours
cp data/kestrel.db backup.db

The honest comparison

Why people leave GA4, Umami and Plausible

Self-hosting removes the bill. Kestrel removes the reasons you still needed a second tool.

Kestrel Google Analytics 4 Umami Plausible
Tracker size (gzipped)~2.5 KB~45–90 KB~2 KB~1 KB
Self-hosted, no cloudYes, 1 containerNoYesYes (CE)
Database you ownSQLite fileGoogle’sPostgres / MySQLPostgres / ClickHouse
Revenue attributionBuilt inComplex setupNoNo
AI assistant channelDedicatedMixed into referralMixed into referralMixed into referral
Goals & funnelsIncludedIncluded, heavyGoals onlyGoals only
Visitor journey profilesFull timelineLimitedNoNo
GDPR-friendly (first-party)YesConsent modeYesYes
Cost$0 foreverFree / $50k+Free / $20+Free / €9+

Approximate values, checked October 2026. “Self-hosted” means you run it on your own server. Kestrel uses first-party cookies to recognise returning visitors, with no cross-site identifiers, no data sold, no third party.

Deploy

Your server. Your data. One afternoon.

Node 22.13+ or Docker. No build service, no database admin, no monthly bill. The first boot creates the database and runs every migration automatically.

Docker

recommended
git clone https://github.com/rahulxdevv/kestrel.git
cd kestrel
docker build -t kestrel .

docker run -d --name kestrel -p 3000:3000 \
  -v kestrel-data:/data \
  -e ADMIN_PASSWORD='a-strong-password' \
  -e SESSION_SECRET="$(openssl rand -hex 32)" \
  kestrel

Open http://localhost:3000/app. Everything lives in the volume at /data.

Dokploy / Coolify

compose
services:
  kestrel:
    build: .
    restart: unless-stopped
    ports: ["3000:3000"]
    environment:
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
      SESSION_SECRET: ${SESSION_SECRET}
    volumes:
      - kestrel-data:/data

volumes:
  kestrel-data:

Build type: Dockerfile. Add a persistent volume at /data and point your domain at port 3000.

Render

blueprint
# render.yaml is included in the repo
services:
  - type: web
    name: kestrel
    runtime: docker
    plan: starter
    healthCheckPath: /api/health
    disk:
      name: kestrel-data
      mountPath: /data
      sizeGB: 1

Render needs a persistent disk for the SQLite file; without it the database resets on every deploy.

VPS / Cloudflare

both
# Any VPS with Node 22.13+
npm ci && npm run build
ADMIN_PASSWORD='…' SESSION_SECRET='…' npm start

# Cloudflare Workers (optional)
npx wrangler d1 create kestrel
npm run deploy:cloudflare

Put Caddy or Nginx in front for HTTPS. Both runtimes share the same code and schema.

Then add one script tag

2.5 KB. No dependencies. No cookies on other domains.

Works with Next.js, Astro, WordPress, Shopify, Webflow, plain HTML and single-page apps.

<script defer data-website-id="YOUR_SITE_ID"
  src="https://analytics.yoursite.com/js/kestrel.js"></script>

FAQ

Questions worth asking

Is Kestrel really free?

Yes. MIT licensed, self-hosted, no seat limits, no event limits, no feature gates. You pay for your own server if you don’t already have one.

Do I need a cookie banner?

Kestrel only uses first-party cookies on your own domain to recognise a returning visitor and keep a session together. There are no third-party cookies and no cross-site tracking. Whether you need a banner depends on your jurisdiction and legal advice, but the data is far smaller, and it never leaves your server.

Can I use Postgres or MySQL?

Not today. Kestrel is deliberately SQLite-first: one file, zero operations, fast on a $4 VPS and easy to back up. A managed Postgres adapter is on the roadmap.

How do I get visitor countries on a VPS?

Put Cloudflare in front of your domain (free), or use a proxy that adds geo headers (Caddy with the geo module, Traefik + GeoIP, Vercel). Without geo headers Kestrel simply leaves the country empty; nothing breaks.

Does it work with Stripe?

Yes, through the generic payments API: post a small JSON payload from your webhook with the visitor id, amount and email. Dodo Payments has a native, signature-verified webhook.

Can I keep the Cloudflare deployment?

Yes. The repo still ships a Worker entry, D1 migrations and wrangler config. Run npm run deploy:cloudflare and you get the same dashboard on Workers, free.

Will it handle my traffic?

On SQLite with WAL mode, a small VPS handles millions of events per month comfortably. The dashboard uses pre-aggregated SQL queries with indexes and the tracker batches engaged-time pings, so there is no scanning of raw events on page load.

How do I back up or move servers?

Copy data/kestrel.db (plus the WAL files while stopped, or use sqlite3 .backup) and mount it on the new host. The schema migrates itself on boot.

Open source · MIT · Self-hosted

Stop renting your own analytics.

Deploy Kestrel once. Own the dashboard, the database and the story your traffic tells.

No account. No trial. No monthly bill.