Your coding agent writes the track() calls.
Start by finding out what is missing. One command reads the repo you are standing in and names the user actions nothing is measuring, with the file and the line. No account, no key, and no network call, so your code never leaves your machine. The calls go into the analytics you already run: Google Analytics, PostHog, Plausible, Mixpanel, Amplitude or Segment.
This is one half of smolanalytics. The other half is an agent that uses your app in a real browser on every pull request and tells you what broke — no test code, one sentence per test. They are the same walk through your product: something that can drive your checkout knows your checkout has a checkout action, which is why the same tool can test it and keep it measured.
$ npx smolanalytics audit
3 things your product does that nothing is measuring.
An action nobody instrumented looks identical to one nobody performed.
untracked payment app/api/checkout/route.ts:42
suggested event: checkout
untracked signup app/(auth)/signup/page.tsx:88
suggested event: signup
untracked invite lib/team.ts:117
suggested event: invite_sent
Also seen, mostly not worth an event: 9 form submits, 14 api mutations.Then npx smolanalytics init wires the snippet: it works out what your project is, names the one file it will edit before touching anything, and refuses to write a placeholder key rather than leave you an app that looks instrumented and sends nothing.
npx smolanalytics audit reads the repo you are standing in and names the user actions nothing is measuring, with the file and the line: payments first, then signups, logins, invites, deletions, shares, uploads. Generic shapes like a form or a POST handler are counted as a footnote rather than padding the list, because a report of 497 findings gets dismissed once and never opened again. No key, no signup, and no network call on this path.
Already running PostHog, GA4, Mixpanel, Amplitude, Plausible or Segment? Skip this step: the calls in step 3 go into that SDK, and nothing is replaced. If you have nothing, one snippet of ours captures pageviews, every click with its element chain, honest engagement time (focused and visible seconds, not a backgrounded tab), scroll depth, rage clicks, dead clicks and JS exceptions, with no track() calls needed for any of it. npx smolanalytics init works out what your project is and names the one file it will edit before touching anything.
Connect your editor with npx smolanalytics connect, then type /instrument-my-app. Your agent calls propose_instrumentation, which reads the repo and hands back the exact calls for signup, activate and checkout with file, line and properties — written in whichever SDK the repo already runs, so a PostHog project gets posthog.capture() and a Mixpanel one gets mixpanel.track(). The agent applies them, guided by us. We never touch your code, your agent does.
verify_instrumentation cross-references the code and live traffic and returns FIRING, WIRED (in the code, just run the flow) or MISSING per event. No guessing, no waiting a day. PostHog's wizard sets you up once; this proves it worked in seconds.
The tracking plan is committed to your repo and npx smolanalytics plan check gates CI, so the build fails the day a tracked event stops firing. The plan is also what makes the unattended restore safe: with no declared plan, an event that broke and an event you retired on purpose are indistinguishable, so nothing acts.
When an event in your tracking plan stops arriving but the traffic behind it doesn't, smolanalytics finds the commit that deleted the track() call and opens a pull request putting it back. The line comes back verbatim out of the parent blob, not generated. Off by default twice over: a deployment-wide switch, and a per-project setting that starts at off. Worst case is a duplicate track() call, visible in the same numbers that opened the PR, undone by closing a PR nobody merged.
the four tracking commands
Four commands write and keep your tracking. Every one of them runs through npx on your own machine, and the first needs no account at all:
npx smolanalytics audit # what nothing is measuring, no account needed npx smolanalytics init # wire the snippet into this project npx smolanalytics connect # wire the MCP server into your editors npx smolanalytics plan check # fail CI when a planned event stops firing # then, in the editor you just connected: /instrument-my-app # → reads your repo, writes the track() calls, declares the plan, # and proves each event fires before it's done
No coding agent? You can still define events from clicks you already captured, with no code in your app and nothing to re-deploy: one POST /v1/defined names a business event out of clicks the snippet already recorded, retroactive to install.
These four are the tracking half. The testing half is its own set — test, suggest, guard, desk and mcp — and npx smolanalytics --help prints all nine. The setup for those is in the docs.
what the events are for
Two things read them. The first is the test runner: a suite of sentences and a workflow file put a verdict on every pull request, and the flows those tests walk are the same flows these events measure — one says whether it still works, the other says whether anyone did it. The setup for that half is in the docs.
The second is the analytics you already run. The calls are written in that SDK's own idiom, so the numbers land in the PostHog, Mixpanel or GA4 your team already opens, and nothing here asks anyone to read a second dashboard. What smolanalytics keeps is the plan: once the events are declared, npx smolanalytics plan check knows which of them should be arriving, and that declaration is what lets the CI gate and the unattended restore tell an event that broke from an event you retired on purpose. Deploys are declared the same way, with record_deploy from the editor or one POST from your CI, so a ship has a marker beside the events around it. The full sequence is on how it works.
Worth saying plainly: the audit, the CI gate and the tests themselves all work on the first day, because they read your code and your app rather than waiting on events, which is why they come first on this page instead of last.
how you get custom events elsewhere
| Tool | How you get your custom events |
|---|---|
| smolanalytics | Your coding agent writes the track() calls over MCP; a CI drift gate fails the build the day a tracked event stops firing; verify_instrumentation proves each one is wired and firing in seconds. Autocapture covers the rest. |
| Heap | autocaptures everything but can't touch your code, you define events by hand in their UI |
| Mixpanel / Amplitude | taxonomy first, you plan the events in a governance tool, then hand-write every track() call |
| Segment | enforces a tracking plan but you still write all the instrumentation yourself |
| PostHog | a setup wizard installs it once, but custom events are manual and nothing gates the plan in CI |
npx smolanalytics audit
Then wire it up