Everything that connects, and nothing that doesn't.
28 integrations, every one self-serve. No partnership to negotiate, no marketplace to be accepted into, no “contact us for API access”. If it is on this page you can switch it on yourself in the next few minutes.
Revenue in
The one that changes what the product says. Without revenue a finding is sized in people — “480 people/mo”. With it, the same finding reads “~$14,400/mo · 480 people”, and the investigation starts ranking the expensive problem above the loud one. Paste one URL into your processor's own dashboard; nobody approves anything.
| what | how you turn it on | notes |
|---|---|---|
| Stripe | POST /v1/revenue/stripe | checkout.session.completed, invoice.paid, payment_intent.succeeded |
| Lemon Squeezy | POST /v1/revenue/lemonsqueezy | order_created, subscription_payment_success |
| Polar | POST /v1/revenue/polar | order.created — uses net_amount, not gross |
| Dodo Payments | POST /v1/revenue/dodo | payment.succeeded — uses settlement_amount |
| Your own track() call | track("checkout", { amount: 29 }) | if you'd rather not wire a webhook at all |
Deploys in
What turns “checkout fell 33%” into “Ship a3f91c2 landed the same day”. One curl in your build command works on every host, which is why it is documented first: of six hosts only Netlify and Railway offer a free self-serve deploy webhook, and Fly.io has none at all.
| what | how you turn it on | notes |
|---|---|---|
| GitHub Actions | copy .github/workflows/deploy-marker.yml | in the repo, runs on push |
| Vercel · Netlify · Railway · Render · Cloudflare · Fly | one curl in the build command | per-host variables in the docs |
| GitHub App (cloud) | install it once | records a marker per merged PR, no config |
| Feature-flag flips | automatic | flipping a flag is a ship, and the only kind detectable with no setup |
| CLI / API | smolanalytics deploy · POST /v1/deploys | reads sha, subject and author out of git |
Alerts and digests out
Where the answer arrives when you are not looking at a dashboard. Every delivery now records its status and retries with backoff — an endpoint that starts failing says so instead of going quiet.
| what | how you turn it on | notes |
|---|---|---|
| Slack | paste an incoming-webhook URL | detected automatically from the host |
| Discord | paste a channel webhook URL | detected automatically; long digests are clipped, not dropped |
| Mattermost · Rocket.Chat | paste the URL, pick “Slack format” | they speak Slack's contract on your own domain, so the URL can't be detected |
| Anything else | signed JSON + X-Smolanalytics-Signature | HMAC-SHA256 of the body; the secret is shown once when you add it |
| the daily brief | hosted; self-host pipes `smolanalytics brief` to whatever you like |
Your existing data in
Bring your history so the graphs do not restart at zero. Original timestamps are kept and re-runs are idempotent, so an interrupted import can simply be run again.
| what | how you turn it on | notes |
|---|---|---|
| PostHog | smolanalytics import --format=posthog | or --format=posthog-api to read their API directly |
| Mixpanel | smolanalytics import --format=mixpanel | |
| Amplitude | smolanalytics import --format=amplitude | gzipped .json.gz is decompressed for you |
| Umami | smolanalytics import --format=umami | |
| CSV / JSONL | smolanalytics import --format=csv|jsonl | JSONL round-trips straight back out of /v1/export |
| Google Search Console | smolanalytics gsc auth | queries, impressions, positions, and the page-level opportunities |
Your editor and your agent
The reports are MCP tools, so answers arrive where you already work, computed by the same engine the dashboard runs — never SQL a model wrote. Your own model does the reasoning, so there is nothing metered.
| what | how you turn it on | notes |
|---|---|---|
| Claude Code · Cursor · Copilot · Windsurf · Codex | one MCP connection | 94 tools, 15 prompts, set up once |
| Any MCP client | stdio, or POST /mcp | one org token routes to any project by name |
| Lovable · Bolt · Replit · v0 | paste the install line | the agent fetches the guide and wires it up |
Where the events come from
One snippet covers the web. Everything else is a thin wrapper over the same open endpoint, so you are never locked into a client.
| what | how you turn it on | notes |
|---|---|---|
| Any website | <script src="…/sdk.js"> | autocaptures pageviews, clicks, scroll, rageclicks, exceptions |
| Next.js · React · Vue · Nuxt · SvelteKit · Vite · Astro | npx smolanalytics init | detects the framework and edits the one file that needs it |
| Swift · Kotlin · React Native · Flutter | SPM · JitPack · npm · pub.dev | offline queue, sessions and screen tracking included |
| Any backend | POST /v1/events | no SDK: a Go service and a Stripe webhook look nearly identical |
Questions
Do any of these need a partnership or an approval?
No, and that is a deliberate constraint rather than a coincidence. Every integration here is one you switch on yourself: a URL you paste into a dashboard you already own, a command you run, or a token you generate. Nothing on this page required us to be listed in a marketplace or accepted into a partner programme, which is also why the Stripe App and the Vercel Marketplace integration are absent — both are review-gated.
What happens when a webhook I've configured stops working?
It tells you. Each delivery records its status and its error, retries with backoff on a 5xx or a 429, and after four consecutive failures the endpoint disables itself and the settings row says which failures did it. A definite refusal — a 400 or a 404 — is not retried, because the receiver understood and said no. Before this, a failing endpoint went quiet and nothing anywhere recorded it.
Why does revenue need a distinct_id?
Because a payment payload carries a billing identity — a customer id, an email — and never your analytics distinct_id, so without a join the money lands against people who appear in no funnel and every revenue-per-person figure is wrong. Pass your distinct_id as the checkout reference and the join is exact. Failing that it falls back to the customer id, then the email, and records which one it used, so you can see how solid the attribution is. A payment with nothing at all to join on is not stored rather than being attributed to an invented person.
Can I send events from a platform that isn't listed?
Yes. Everything above is a thin wrapper over one open endpoint, POST /v1/events, which takes JSON and a write key. If your platform can make an HTTP request it can send events, and there is nothing to install.
Is there anything you deliberately don't integrate with?
Anything that needs someone's permission, and anything that would make us a customer-data platform. This is analytics: it reads your product and tells you what changed. It is not a place to route events onward to twenty other tools, and building that would mean maintaining a hundred destinations rather than making the reports better.