smolanalytics

module
v0.62.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: MIT

README

smolanalytics

web + product analytics in one Go binary. no ClickHouse, no Kafka, no cluster. ask it in your editor.

CI Release Go Stars

Live demo  ·  Docs  ·  Cloud  ·  Star this repo ★


the real product on demo data. open the live demo →

self-hosting posthog means clickhouse, kafka, redis and a postgres. this is one binary.

If you want product analytics you can actually run yourself, the options are bad. PostHog is a stack: ClickHouse, Kafka, Redis, and a Postgres to babysit. Plausible and Umami install easily but stop at web analytics, so no funnels, no retention, no cohorts.

smolanalytics is the middle that didn't exist. One Go binary, one data file, no external database. It does web analytics (visitors, referrers, UTM, devices) and product analytics (funnels, retention, paths, cohorts) from the same events, plus feature flags, A/B testing, click heatmaps, in-product surveys, a session inspector, and deploy-impact. Cookieless mode means no consent banner. MIT, free forever, and your data never leaves your box.

It also answers in plain English, from the dashboard or from your editor over MCP, using your own model, so the AI part costs nothing.

Try it in 30 seconds

docker run -p 8080:8080 ghcr.io/arjun0606/smolanalytics demo
or the single binary / go run
# install script (macOS / Linux)
curl -fsSL https://raw.githubusercontent.com/Arjun0606/smolanalytics/main/install.sh | sh
smolanalytics demo

# or with Go
go run github.com/Arjun0606/smolanalytics/cmd/smolanalytics@latest demo

Open localhost:8080: a fully populated dashboard, a "what to fix" verdict up top, and an ask bar with your real events and pages as one-click chips. Nothing to configure. Prefer not to install? The live demo is the real product on demo data, running right now.

Ask your analytics where you write code

This is the point of the whole tool. smolanalytics is an MCP server, so your coding agent queries your real analytics without you leaving the editor. It has your codebase, your tracking plan, and smolanalytics over MCP, so it answers in your terms: ask "what's the MAU for the PQR page" and it knows PQR is the /pqr route from your code. Your model does the reasoning, so there are no API keys and nothing metered.

smolanalytics connect          # wires it into every coding assistant you have installed
you ▸ how's activation, and is pro converting better than free?
ai  ▸ Activation is 62% (657 of 1,051 signups reach "activate").
      Pro converts 2.4× better end-to-end: 45% signup→checkout vs 19% on free.
      The leak is activate→checkout on free (only 31% continue). Want the paths after activate?

Your model gets 79 tools and 14 built-in prompts, and it runs the whole product, not just queries: ask reports, roll out a flag, read the A/B result, create a cohort, set an alert, verify instrumentation. Anything it creates shows up on the dashboard instantly.

Assistant command Assistant command
Claude Code smolanalytics connect claude-code Cursor smolanalytics connect cursor
Claude Desktop smolanalytics connect claude Windsurf smolanalytics connect windsurf
VS Code (Copilot) smolanalytics connect vscode Cline smolanalytics connect cline
Wire it up by hand, or point at a remote server over HTTP
// stdio (local, reads your data file directly)
{ "mcpServers": { "smolanalytics": { "command": "smolanalytics", "args": ["mcp"] } } }

// HTTP (point at a running instance, local or remote)
{ "mcpServers": { "smolanalytics": { "url": "http://localhost:8080/mcp" } } }

Claude Code, HTTP: claude mcp add --transport http smolanalytics http://localhost:8080/mcp. Any MCP client works (stdio + Streamable HTTP). When a read key is set, add "headers": { "Authorization": "Bearer YOUR_KEY" }.

Testing the endpoint by hand? Streamable HTTP requires an Accept header naming both content types, or the request is rejected:

curl -X POST http://localhost:8080/mcp -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

There is also a built-in dashboard ask bar (zero setup, no code lookup) for quick data questions like "visitors to /pricing" or "where do people drop off?".

The whole toolkit, one binary

The usual advice is "run Plausible for web, something heavier for product, and separate tools for flags, experiments, and surveys." smolanalytics is all of it, computed from one append-only event log, and every surface is askable in your editor.

what you get ask it, or hit the API
Product analytics funnels (ordered / strict / unordered, exclusions, per-step filters, breakdowns), retention (rolling + weekly buckets), trends (count / sum / avg / p90), paths, lifecycle, stickiness, cohorts, sequenced behavioral cohorts, B2B account groups funnel retention trends paths lifecycle stickiness create_sequence_cohort groups
Web analytics visitors, live-now, top pages, referrers, UTM, devices, the Plausible-shaped view web_overview · /v1/web
Feature flags boolean + multivariate, property targeting + percentage rollout, deterministic bucketing so the SDK and the agent always agree; smol.flag() in the browser SDK create_flag evaluate_flag · /v1/flags/evaluate
A/B testing flags measured on a goal event, per-variant conversion after first exposure, lift vs control, 95% two-proportion z-test flag_impact · /v1/flags/{key}/measure
Click heatmaps click-density grid + top clicked elements per page and viewport, from $click autocapture heatmap · /v1/heatmap
In-product surveys NPS / rating / choice / text, URL + sampling targeting, dependency-free SDK widget create_survey survey_results · /v1/surveys/*
Session inspector event-based journey replay: pages, clicks with positions, rage-clicks, ms timing list_sessions session_timeline · /v1/sessions
Deploy impact before/after metric attribution per commit: which ship moved the metric deploy_impact · /v1/deploys?event=

Full tool + prompt reference: docs/prompts.md · the plain-GET stats API: docs/api.md.

Provably correct, or it fails CI

The agreement test asserts, on every build, that the MCP answer equals the /v1 HTTP API answer byte-for-byte for the same question across funnel, retention, trends, web_overview, paths, heatmap, flag_impact, survey_results, list_sessions, and more. The dashboard renders from those same reports, so it cannot drift either. There is no second query path to disagree with. This is the one thing an AI-answer layer built on generated SQL structurally cannot promise.

Send events (web, mobile, server)

One snippet autocaptures pageviews + clicks. Add track() for the moments you care about.

<script src="https://YOUR_HOST/sdk.js"></script>
<script>
  smolanalytics.init("YOUR_WRITE_KEY", { host: "https://YOUR_HOST" });
  smolanalytics.track("signup", { plan: "pro" });   // optional, for funnels
  smolanalytics.identify("user_123");                // on login
</script>

Ingestion is one endpoint, so anything with an HTTP client works (curl -XPOST $HOST/v1/events ...). And there are published native SDKs with an offline-safe queue, batching, sessions, and lifecycle events:

Platform install
Swift (iOS) SPM: github.com/Arjun0606/smolanalytics-swift
Kotlin / Android JitPack: com.github.Arjun0606:smolanalytics-android
React Native / Expo npm: smolanalytics-react-native
Flutter / Dart pub.dev: smolanalytics

Framework guides (2 minutes each): Next.js · React · Vue · Backend · Mobile. Or paste one line into Cursor / Claude Code and let it instrument the app: docs/agents.md.

Which deploy moved the metric?

Every other tool shows you the graph dropped. It cannot tell you which ship dropped it, because it does not have your commits. Record a marker in CI (smolanalytics deploy, one line) and ask your editor "did my last deploy move signups?" and you get a before/after read that leads with any regression, computed from the same reports (correlation, not proof, and the copy says so).

How it compares

smolanalytics Plausible / Fathom Mixpanel / Amplitude PostHog
Funnels · retention · paths · cohorts ⚠️ paid / partial
Flags · A/B · surveys · heatmaps · sessions one binary ⚠️ separate / paid
Ask in plain English your AI, free 💲 their AI 💲 their AI + MCP
AI numbers match the dashboard CI-enforced n/a ⚠️ ⚠️ "may not match the UI"
Which deploy moved the metric
Self-host ✅ one binary ⚠️ Kafka + ClickHouse
Own your data · export ⚠️

Three things they structurally cannot copy: the AI is yours (they meter theirs); answers come from exact reports with CI proving they match the dashboard; your data never leaves your box.

Run it in production

docker run -p 8080:8080 -v $PWD/data:/data \
  -e SMOLANALYTICS_WRITE_KEY=$(openssl rand -hex 16) \
  -e SMOLANALYTICS_PASSWORD=$(openssl rand -hex 12) \
  ghcr.io/arjun0606/smolanalytics

One static binary, no cgo, no cluster. It binds 127.0.0.1 by default and refuses to serve real data unauthenticated on a public interface. Two keys: a public write key (ingest only, ships in your HTML) and a secret read key (reports, export, MCP). Scale to billions of events on flat RAM with an optional S3 / R2 / Tigris cold tier, keep a SMOLANALYTICS_RETAIN_DAYS window, and cron smolanalytics brief for a morning digest. Full config, backups, and the storage design: Deploy guide · STABILITY.md.

Own it, forever

  • Private by architecture. No third party, no cookies by default, a cookieless mode that needs no consent banner, and GDPR erasure in one call (DELETE /v1/users/{id}/data). The answer to "who can see this data?" is: you.
  • MIT, no CLA, no rug-pull. There is no license to revoke. Fork it the day you stop liking us.
  • No lock-in. GET /v1/export hands you everything as CSV or JSONL, and the JSONL round-trips back into /v1/events. Import from PostHog, Mixpanel, Amplitude, Umami, CSV, or JSONL with original timestamps.
  • Works without us. One static binary, no phone-home, no license server. If this repo went dark tomorrow, your instance would not notice.

Don't want to run it? → smolanalytics Cloud

Self-hosting is the free tier, unlimited, forever. The hosted cloud adds an isolated instance per project, your whole team, the morning brief delivered, and scale with zero ops. 14-day full-product trial (no card), then Pro $49/mo (1M events) or Scale $149/mo (10M events), flat $8 per extra million. Overage never locks your dashboard.

The one thing it deliberately does not do

Feature flags, A/B, heatmaps, surveys, a session inspector, cohorts: all ship, all from the same binary. The single deliberate exception is pixel-perfect DOM / video session replay (the screen-recording kind), which needs a heavy recorder and a separate blob store and would break the single-binary model. The event-based session inspector ships instead. Also by design: no multi-node / clustering / HA. Exactly one writer per instance is why it self-hosts in 30 seconds.

Contributing

PRs welcome. Keep it small, correct, and dependency-free (CONTRIBUTING.md). Security: SECURITY.md.

License

MIT, forever. No CLA, no relicense: the business is the hosted cloud, never the license. Use it, fork it, host it, sell hosting of it.


If smolanalytics is useful, a ★ helps other people find it.

Star History Chart

Directories

Path Synopsis
cmd
smolanalytics command
Command smolanalytics is the single binary: product analytics you can run with one command, no cluster.
Command smolanalytics is the single binary: product analytics you can run with one command, no cluster.
internal
agent
Package agent computes agent-observability reports over the same generic event log everything else in the engine runs on — no new storage, no schema change.
Package agent computes agent-observability reports over the same generic event log everything else in the engine runs on — no new storage, no schema change.
aicrawl
Package aicrawl aggregates $ai_crawl events: the AI crawlers' own visits to the customer's site, recorded server-side.
Package aicrawl aggregates $ai_crawl events: the AI crawlers' own visits to the customer's site, recorded server-side.
aivis
Package aivis aggregates $geo_check events — AI-visibility sampling results the cloud runner (or any self-hoster's script) records as ordinary events on the instance.
Package aivis aggregates $geo_check events — AI-visibility sampling results the cloud runner (or any self-hoster's script) records as ordinary events on the instance.
alert
Package alert defines threshold alerts on event metrics — "fire when <event> count over the last N hours is above/below a threshold".
Package alert defines threshold alerts on event metrics — "fire when <event> count over the last N hours is above/below a threshold".
alias
Package alias joins anonymous pre-login activity to the logged-in user — identity stitching.
Package alias joins anonymous pre-login activity to the logged-in user — identity stitching.
api
Package api serves the single-binary HTTP surface: event ingestion + the server-rendered dashboard.
Package api serves the single-binary HTTP surface: event ingestion + the server-rendered dashboard.
audit
Package audit is the change log every real product needs — a record of the operator actions that mutate config or data (account changes, key create/revoke, retention, data clears).
Package audit is the change log every real product needs — a record of the operator actions that mutate config or data (account changes, key create/revoke, retention, data clears).
botua
Package botua identifies crawler/bot user agents so autocaptured web traffic ($pageview/$click) doesn't inflate every report.
Package botua identifies crawler/bot user agents so autocaptured web traffic ($pageview/$click) doesn't inflate every report.
brief
Package brief computes the morning "what to fix" digest: the pulse (last N days vs the N before), the per-product portfolio split, and the verdict engine's findings.
Package brief computes the morning "what to fix" digest: the pulse (last N days vs the N before), the per-product portfolio split, and the verdict engine's findings.
claim
Package claim turns a merged pull request into a prediction with a deadline.
Package claim turns a merged pull request into a prediction with a deadline.
cohort
Package cohort defines reusable user groups — "users who did checkout", "users from Hacker News who activated" — that you define once and apply across every report.
Package cohort defines reusable user groups — "users who did checkout", "users from Hacker News who activated" — that you define once and apply across every report.
defined
Package defined implements retroactive, zero-code events — the Heap wedge.
Package defined implements retroactive, zero-code events — the Heap wedge.
demo
Package demo seeds a realistic dataset so `smolanalytics demo` shows a populated, beautiful dashboard with zero setup — the 60-second "oh" moment.
Package demo seeds a realistic dataset so `smolanalytics demo` shows a populated, beautiful dashboard with zero setup — the 60-second "oh" moment.
deploys
Package deploys records deployment markers — a timestamped point ("this shipped then") you overlay on any metric to answer the one question every other analytics tool leaves you guessing: did that deploy move the number? Markers are cheap to record (a git sha + message from CI, or a named release by hand); the impact math lives in impact.go and is the same trends engine the dashboard renders, so the answer is computed, never guessed, and a CI test pins it to the dashboard.
Package deploys records deployment markers — a timestamped point ("this shipped then") you overlay on any metric to answer the one question every other analytics tool leaves you guessing: did that deploy move the number? Markers are cheap to record (a git sha + message from CI, or a named release by hand); the impact math lives in impact.go and is the same trends engine the dashboard renders, so the answer is computed, never guessed, and a CI test pins it to the dashboard.
engagement
Package engagement computes the standard engagement reports — lifecycle (new/returning/resurrected/dormant) and stickiness (DAU/WAU/MAU) — that every product-analytics tool ships.
Package engagement computes the standard engagement reports — lifecycle (new/returning/resurrected/dormant) and stickiness (DAU/WAU/MAU) — that every product-analytics tool ships.
errortrack
Package errortrack turns the $exception events the SDK already captures into an error report: grouped, ranked by the people they hit, and joined to the funnel they broke.
Package errortrack turns the $exception events the SDK already captures into an error report: grouped, ranked by the people they hit, and joined to the funnel they broke.
event
Package event defines the core analytics event — the single unit everything (funnels, retention, trends) is computed from.
Package event defines the core analytics event — the single unit everything (funnels, retention, trends) is computed from.
exportlink
Package exportlink mints one-time download links for the full raw event export (GET /export/<token>) — "give me my data" from the editor without dumping millions of rows through a conversation.
Package exportlink mints one-time download links for the full raw event export (GET /export/<token>) — "give me my data" from the editor without dumping millions of rows through a conversation.
flag
Package flag is feature flags for smolanalytics — boolean and multivariate, with property targeting and percentage rollouts, evaluated deterministically so the same user always lands in the same bucket.
Package flag is feature flags for smolanalytics — boolean and multivariate, with property targeting and percentage rollouts, evaluated deterministically so the same user always lands in the same bucket.
formula
Package formula evaluates arithmetic across trend series — the derived metrics every mature analytics tool has and this engine did not.
Package formula evaluates arithmetic across trend series — the derived metrics every mature analytics tool has and this engine did not.
funnel
Package funnel computes ordered conversion funnels — the headline feature: of the users who did step 1, how many went on to do step 2, then 3, and where do they drop off.
Package funnel computes ordered conversion funnels — the headline feature: of the users who did step 1, how many went on to do step 2, then 3, and where do they drop off.
geo
Package geo resolves visitor IPs to a country code using the DB-IP Lite free database (db-ip.com, CC BY 4.0 — the dashboard credits it wherever countries render).
Package geo resolves visitor IPs to a country code using the DB-IP Lite free database (db-ip.com, CC BY 4.0 — the dashboard credits it wherever countries render).
goal
Package goal stores named conversion goals — "what counts as success on this site" — defined once, reusable everywhere.
Package goal stores named conversion goals — "what counts as success on this site" — defined once, reusable everywhere.
groups
Package groups computes account-level (B2B) analytics — aggregate by a group property (company, account_id, team) instead of by user.
Package groups computes account-level (B2B) analytics — aggregate by a group property (company, account_id, team) instead of by user.
gsc
Package gsc integrates Google Search Console: the search queries that bring people to your site, next to what they did after arriving — the one report neither GA nor the privacy tools unify well.
Package gsc integrates Google Search Console: the search queries that bring people to your site, next to what they did after arriving — the one report neither GA nor the privacy tools unify well.
heatmap
Package heatmap turns autocaptured $click events into a click-density grid for a page, plus the top clicked elements — computed at query time over the existing events, no new stored config and no screenshots.
Package heatmap turns autocaptured $click events into a click-density grid for a page, plus the top clicked elements — computed at query time over the existing events, no new stored config and no screenshots.
importer
Package importer brings history over from another tool so day one here isn't a zero dashboard.
Package importer brings history over from another tool so day one here isn't a zero dashboard.
insight
Package insight produces the proactive "what's broken / what to look at" digest — the verdict founders actually want instead of a dashboard.
Package insight produces the proactive "what's broken / what to look at" digest — the verdict founders actually want instead of a dashboard.
insights
Package insights persists saved reports and the boards they live on — the "pin this report" feature that turns ad-hoc Explore into a dashboard you open every morning.
Package insights persists saved reports and the boards they live on — the "pin this report" feature that turns ad-hoc Explore into a dashboard you open every morning.
instrument
Package instrument turns "the agent instruments your app" from a pasted prompt into a real capability.
Package instrument turns "the agent instruments your app" from a pasted prompt into a real capability.
investigate
Package investigate is the part of a product manager's week that is mechanical.
Package investigate is the part of a product manager's week that is mechanical.
mcp
Package mcp exposes the analytics engine over the Model Context Protocol so the user connects smolanalytics to THEIR OWN Claude / Cursor / Claude Code and asks questions in plain English — their model calls these tools, we never call a model ourselves (no API keys, no inference cost on our side).
Package mcp exposes the analytics engine over the Model Context Protocol so the user connects smolanalytics to THEIR OWN Claude / Cursor / Claude Code and asks questions in plain English — their model calls these tools, we never call a model ourselves (no API keys, no inference cost on our side).
paths
Package paths computes user flows — "what do users do after event X?" — the Flows / Pathfinder / Paths report.
Package paths computes user flows — "what do users do after event X?" — the Flows / Pathfinder / Paths report.
payments
Package payments turns a payment provider's webhook into an ordinary event in the log.
Package payments turns a payment provider's webhook into an ordinary event in the log.
person
Package person builds person profiles — the last-known traits of every user — from the event log, at query time.
Package person builds person profiles — the last-known traits of every user — from the event log, at query time.
provenance
Package provenance answers the one question no other analytics tool can: SHOW ME THE ROWS BEHIND THIS NUMBER.
Package provenance answers the one question no other analytics tool can: SHOW ME THE ROWS BEHIND THIS NUMBER.
query
Package query is the segmentation backbone: filter events by their properties and break them down (group by) a property.
Package query is the segmentation backbone: filter events by their properties and break them down (group by) a property.
retention
Package retention computes cohort retention — the other core product-analytics primitive: group users by the day they first showed up, then track what % come back on day 1, 2, ...
Package retention computes cohort retention — the other core product-analytics primitive: group users by the day they first showed up, then track what % come back on day 1, 2, ...
session
Package session reconstructs a user's journey from events already captured — pages, clicks (with positions), rage-clicks, and timing — and plays it back.
Package session reconstructs a user's journey from events already captured — pages, clicks (with positions), rage-clicks, and timing — and plays it back.
settings
Package settings holds the operational config every real product needs — project name, timezone, managed API keys, and the session-signing secret — persisted as a single JSON file (atomic rewrite), separate from event data.
Package settings holds the operational config every real product needs — project name, timezone, managed API keys, and the session-signing secret — persisted as a single JSON file (atomic rewrite), separate from event data.
share
Package share issues revocable read-only share links — show your traffic to a cofounder or investor without giving them a login.
Package share issues revocable read-only share links — show your traffic to a cofounder or investor without giving them a login.
sql
Package sql is a small, read-only SQL dialect over the event stream.
Package sql is a small, read-only SQL dialect over the event stream.
store
Package store is the data layer.
Package store is the data layer.
store/blob
Package blob is object storage as one small interface: whole-object Put/Get/List/ Delete.
Package blob is object storage as one small interface: whole-object Put/Get/List/ Delete.
store/file
Package file is a durable store.Store: an append-only JSONL event log that replays into memory on open.
Package file is a durable store.Store: an append-only JSONL event log that replays into memory on open.
store/memory
Package memory is an in-memory store.Store: enough to run the full engine in tests and the zero-setup CLI demo.
Package memory is an in-memory store.Store: enough to run the full engine in tests and the zero-setup CLI demo.
store/segment
Package segment is the scale tier: a durable hot append-log that seals into immutable, time-bounded, compressed columnar segments on a Blob backend (local disk now, S3/R2 next).
Package segment is the scale tier: a durable hot append-log that seals into immutable, time-bounded, compressed columnar segments on a Blob backend (local disk now, S3/R2 next).
survey
Package survey is in-product micro-surveys — one question (NPS, rating, choice, or text), targeted by URL + sampling, answered by a tiny SDK widget.
Package survey is in-product micro-surveys — one question (NPS, rating, choice, or text), targeted by URL + sampling, answered by a tiny SDK widget.
trackplan
Package trackplan stores the intended instrumentation — the events (and their properties) an app MEANS to track.
Package trackplan stores the intended instrumentation — the events (and their properties) an app MEANS to track.
trends
Package trends computes time-series — how many times an event happened per day (optionally unique users), the third core analysis primitive alongside funnels and retention.
Package trends computes time-series — how many times an event happened per day (optionally unique users), the third core analysis primitive alongside funnels and retention.
web
Package web composes the one-glance web-analytics view — live visitors, top pages, referrers, UTM sources, device split — from $pageview events.
Package web composes the one-glance web-analytics view — live visitors, top pages, referrers, UTM sources, device split — from $pageview events.
webhook
Package webhook delivers outbound notifications to operator-configured URLs (used by alerts and the daily digest).
Package webhook delivers outbound notifications to operator-configured URLs (used by alerts and the daily digest).
whatchanged
Package whatchanged finds WHEN a metric changed and WHICH commits could explain it.
Package whatchanged finds WHEN a metric changed and WHICH commits could explain it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL