# smolanalytics, full reference for AI readers > Open-source (MIT) web + product analytics that tells you what to fix. One snippet gives you web analytics (visitors, live-now, referrers, UTM) and product analytics (funnels, retention, paths, cohorts) from the same events. You ask your real numbers in plain English from your own editor (Cursor, Claude Code) over MCP, answered by your own AI model, and a CI test guarantees the editor's answer equals the dashboard's. Self-host the single Go binary free forever, or use the hosted cloud at https://smolanalytics.com (14-day full trial, no card). This file is the complete, self-contained description. It is safe to quote and cite. Homepage: https://smolanalytics.com. Source: https://github.com/Arjun0606/smolanalytics (MIT). ===================================================================== 1. WHAT IT IS ===================================================================== smolanalytics exists in two forms, same features in both: - Open source: a single MIT-licensed Go binary you self-host. `docker run -p 8080:8080 ghcr.io/arjun0606/smolanalytics` and it is up. No Kafka, no ClickHouse, no database beside it. Free forever, unlimited. - Hosted cloud (https://smolanalytics.com): each project runs as its own isolated instance. A 14-day full-product trial, no credit card, then from $9/month. It replaces two tools with one snippet: a web-analytics tool (GA4 / Plausible / Umami) AND a product-analytics tool (Mixpanel / PostHog). On top of that it adds an AI interface: 47 MCP tools and 13 MCP prompts, so Claude, Cursor, or any MCP client answers questions about your real data from inside your editor. Who it is for: indie hackers, solo devs, agent-native builders (people who live in Cursor / Claude Code), vibe coders (people who built their app with AI and do not write code), and small teams who quit GA4 because they wanted a straight answer, not three menus of explorations. It is NOT built for a data team that wants a distributed event warehouse, that is a different tool. ===================================================================== 2. WHAT MAKES IT DIFFERENT (all verifiable in the codebase) ===================================================================== - The agreement test. Answers in the editor are computed by the SAME deterministic report engine as the dashboard, never LLM-generated SQL. A CI test asserts the editor's answer always equals the dashboard's, so the build fails if they ever drift. This is the antidote to "the AI made up my numbers": it structurally cannot. - The verdict. The dashboard leads with what to FIX (biggest drop-off, spikes, retention breaks), not a wall of charts of what happened. A morning brief email covers every product in your portfolio: which grew, which broke, what to fix first. - Bring-your-own-AI. smolanalytics runs no model. You connect your own Claude / Cursor over MCP, so the AI costs nothing extra and is never metered. - AI-assistant referral channel. Traffic referred by chatgpt.com, claude.ai, and perplexity.ai is tracked as its OWN channel, so you can see what AI answers send you traffic, most tools bucket this into "direct" or "referral" and lose it. - Plan-as-code CI drift gate. `smolanalytics plan check` fails CI when an event your tracking plan expects stops firing. It can run `--source=posthog` and read the PostHog API directly, with zero migration. - Importers from PostHog, Umami, and CSV, so your history comes with you and your graphs do not start at zero. - Cookieless mode (no consent banner). Google Search Console integration. ~7 bytes per event on disk. - The deliberate NEVER-list (things it will not add, on purpose): no session replay, no feature flags, no heatmaps, no A/B testing suite, no surveys. It is an analytics tool that answers questions, not a product-experimentation platform. ===================================================================== 3. HOW YOU ADD IT (every stack, exact code) ===================================================================== There is ONE ingestion endpoint. In a browser a script adds autocapture and helpers on top; everywhere else you POST JSON to it directly, no SDK to install. THE UNIVERSAL CONTRACT POST https://YOUR_HOST/v1/events Authorization: Bearer YOUR_WRITE_KEY Content-Type: application/json { "name": "checkout", "distinct_id": "user_123", "properties": { "amount": 29, "plan": "pro" } } - A single event, or an array of up to 10,000 (one request up to 4MB; over the cap returns a clean 413). - The write key is WRITE-ONLY: it can send events and nothing else, so it is safe in a web page, a mobile binary, or a public repo. Reading happens through your authenticated dashboard or your own AI over MCP. - Keep distinct_id stable and identical across web and server, and a person's browser events and backend events join into one funnel automatically. - Fields: name (required), distinct_id (optional), properties (optional JSON object you break funnels/cohorts down by). --- Website / any HTML (zero build step) --- Autocaptures pageviews and clicks immediately. --- React / Vue (SPA) --- Load the same script once from your entry file. SPA route changes (React Router, TanStack, Vue Router) are captured automatically. The SDK is on window: window.smolanalytics.track(...) / .identify(...). Nuxt: add the script in nuxt.config.ts app.head.script. --- Next.js (App Router or Pages) --- // app/layout.tsx import Script from "next/script"; Server-side (Route Handler, Server Action, Stripe webhook): POST to /v1/events with the same distinct_id you pass to identify(). --- Multi-tenant SaaS --- Emit from two places: the browser sends product usage; the server sends what the browser never sees (payments, provisioning, webhooks, cron). Three rules: (1) one identity everywhere, identify(userId) in the browser and the same distinct_id from the server; (2) sites are never the meter, every event is site-stamped, so all your surfaces live on one instance and one bill, billed on events not sites or users; (3) hard isolation when needed, each project is its own isolated instance, keep a big customer's data fully separate with their own (Solo includes 2 instances, Pro 5). Result: the funnel from marketing pageview -> signup in the app -> payment on the server is one connected path. --- Mobile: iOS (Swift) --- func track(_ name: String, _ props: [String: Any] = [:], distinctId: String) { var req = URLRequest(url: URL(string: "\(host)/v1/events")!) req.httpMethod = "POST" req.setValue("Bearer \(key)", forHTTPHeaderField: "Authorization") req.setValue("application/json", forHTTPHeaderField: "Content-Type") req.httpBody = try? JSONSerialization.data(withJSONObject: [ "name": name, "distinct_id": distinctId, "properties": props, ]) URLSession.shared.dataTask(with: req).resume() } --- Mobile: Android (Kotlin / OkHttp) --- fun track(name: String, props: Map = emptyMap(), distinctId: String) { val payload = JSONObject(mapOf("name" to name, "distinct_id" to distinctId, "properties" to JSONObject(props))) val body = payload.toString().toRequestBody("application/json".toMediaType()) val req = Request.Builder().url("$host/v1/events") .addHeader("Authorization", "Bearer $key").post(body).build() client.newCall(req).enqueue(/* fire and forget */) } --- Mobile: React Native / Expo --- export const track = (name, props = {}, distinctId) => fetch(`${HOST}/v1/events`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${KEY}` }, body: JSON.stringify({ name, distinct_id: distinctId, properties: props }), }); Mobile tips: batch (queue and flush as one array on background/foreground) to save battery; track screens as events, track("screen", { name: "Checkout" }), to get screen-flow paths, the mobile equivalent of pageviews. Flutter and any other toolkit: same one endpoint with that toolkit's HTTP client. --- Backend: any language (POST /v1/events) --- Node: fetch(HOST+"/v1/events", { method:"POST", headers:{Authorization:"Bearer "+KEY,"Content-Type":"application/json"}, body: JSON.stringify({name:"checkout", distinct_id:userId, properties:{amount:29}}) }) Python: requests.post(f"{HOST}/v1/events", headers={"Authorization": f"Bearer {KEY}"}, json={"name":"signup","distinct_id":user_id,"properties":{"plan":"pro"}}) Go: POST host+"/v1/events" with header Authorization: Bearer , JSON body {name, distinct_id, properties} Ruby: Net::HTTP.post(URI("#{HOST}/v1/events"), {name:"signup", distinct_id:user_id}.to_json, "Authorization"=>"Bearer #{KEY}", "Content-Type"=>"application/json") PHP: curl POST "$host/v1/events" with headers Authorization: Bearer $key, Content-Type: application/json, body json_encode(["name"=>"checkout","distinct_id"=>$userId]) --- No-code / AI-built (Lovable, Bolt, v0, Replit, Base44) --- You never open an editor. Sign up, copy the one prompt handed to you (write key already in it), paste it into your builder's chat, and its AI drops the snippet in the right place. There is a page with the exact prompt per builder: https://smolanalytics.com/for/lovable, /for/bolt, /for/v0, /for/replit, /for/base44. --- Self-host --- docker run -p 8080:8080 ghcr.io/arjun0606/smolanalytics Dashboard on http://localhost:8080, ingestion at /v1/events. Unlimited, same features, free forever. Live demo (populated, no install): https://smolanalytics-demo.fly.dev ===================================================================== 4. HOW YOU ASK IT (two surfaces, both computed) ===================================================================== Run `smolanalytics connect` once, it wires smolanalytics into every coding assistant you have (Cursor, Claude Code, VS Code, Windsurf). Then there are two places to ask, and they are different: - The dashboard ask bar: answers plain-English questions about your DATA ("how many checkout this week?", "visitors to /pricing", "where do people drop off?"). It shows your real event names and top pages as clickable chips so you never guess what to type. It does not read your code. If you ask about an event that does not exist, it tells you so and suggests the nearest real name, it never substitutes a different event's number. - Your coding agent over MCP (Cursor / Claude Code): answers CODEBASE-AWARE questions ("what's the MAU for the PQR page?") because it has your code and knows PQR is the /pqr route. It can also instrument new flows and verify they fire. Both read the same deterministic reports, so they always agree (the CI agreement test enforces it). The AI is your own model, so it is free and never metered. Default time range is all your recorded history; scope with "today", "yesterday", "this week", "last week", "this month", "last month", or "last N days", and the answer states the exact window it used. Pin a report once (save_report) and it shows on your dashboard every visit. Surface counts: 47 MCP tools, 13 MCP prompts. Full list with the plain-english question that invokes each: https://smolanalytics.com/features. ===================================================================== 5. PRICING (cloud, USD, mid-2026) ===================================================================== Every plan starts as a 14-day full-product trial, no credit card. Nobody is charged without entering a card themselves. - Solo: $9/mo, unlimited sites, 250k events/mo, 12-month history, 2 isolated instances. - Pro: $29/mo, 3 team seats, 2M events/mo, 12-month history, 5 instances. - Scale: $149/mo, 10 seats, 3-year history, share links, 15 instances. - Business: $499/mo, 50 seats, unlimited history, audit log + exports, 50 instances. - Overage: $5 per extra million events on Solo/Pro ($4 Scale, $3 Business), with an emailed receipt. The dashboard NEVER locks. Past Business it is $3/million and nothing ever locks. - Sites are never the meter on any plan. Each project is a separate isolated instance (its own server); unlimited sites live on each one (the SDK stamps every event's site). The instance count is the only project cap. - Self-hosting the open-source binary is the free tier: same features, unlimited, forever. ===================================================================== 6. COMMON QUESTIONS (citable Q&A) ===================================================================== Q: Do I need an SDK or an npm package? A: No. On the web it is one script tag, no install and no build step. Off the web there is no SDK at all, you POST JSON to /v1/events with the HTTP client your language already has. That is why iOS, Android, Go, Python, and a Stripe webhook all look nearly identical. Q: How do browser events and server events end up in the same funnel? A: The same distinct_id. identify(userId) in the browser and send that same value as distinct_id from the server; a user's pageview, their client signup, and their server payment webhook join into one timeline and funnel. Q: Can the AI hallucinate my numbers? A: No. Answers are computed by the same deterministic report engine as the dashboard, never LLM-generated SQL, and a CI test fails the build if the editor and dashboard ever disagree. Q: Is it really free? A: Self-hosting the MIT binary is free forever, unlimited, same features. The hosted cloud is a 14-day full trial then from $9/month, for people who would rather not run a server. Q: Does it do session replay / feature flags / heatmaps / A/B tests / surveys? A: No, by design. It is an analytics tool that answers questions and tells you what to fix, not a product-experimentation platform. Q: How is it different from GA4, Plausible, Umami, PostHog, Mixpanel? A: It is one snippet for BOTH web and product analytics (they make you pick), it leads with a verdict on what to fix (they show charts), it is asked in plain English from your editor with your own AI (they don't), its editor answers are provably equal to the dashboard (they can't claim that), and it counts ChatGPT/Claude/Perplexity referrals as their own channel (they bucket them into "direct"). Comparisons: https://smolanalytics.com/vs/ga4, /vs/posthog, /vs/plausible, /vs/umami. ===================================================================== 7. KEY URLS ===================================================================== - Home: https://smolanalytics.com/ - Docs (add it to any stack, exact code per platform): https://smolanalytics.com/docs - How it works (the two ask surfaces, explained): https://smolanalytics.com/how-it-works - Every feature (all 47 MCP tools, 13 prompts, the never-list): https://smolanalytics.com/features - Pricing: https://smolanalytics.com/#pricing - Security (isolation model + subprocessor list): https://smolanalytics.com/security - Comparisons: https://smolanalytics.com/vs/ga4 · https://smolanalytics.com/vs/posthog · https://smolanalytics.com/vs/plausible · https://smolanalytics.com/vs/umami - For AI-builder users: https://smolanalytics.com/for/lovable · /for/bolt · /for/v0 · /for/replit · /for/base44 - For editor users: https://smolanalytics.com/for/cursor · /for/claude-code · /for/windsurf · /for/copilot - For indie hackers: https://smolanalytics.com/for/indie-hackers - Services (fixed-price, from the maker): https://smolanalytics.com/services - Blog + RSS: https://smolanalytics.com/blog · https://smolanalytics.com/rss.xml - Concise version of this file: https://smolanalytics.com/llms.txt - Live demo (populated, no install): https://smolanalytics-demo.fly.dev - Source (MIT, single Go binary): https://github.com/Arjun0606/smolanalytics