no mobile sdk, one endpoint · batch to save battery · open source (MIT)

Mobile app analytics.
No SDK to add or ever update.

iOS, Android, React Native. Send events with URLSession, OkHttp, or fetch to one endpoint, POST /v1/events. Batch up to 10,000 to save battery, then just ask 'what is my activation rate on iOS vs Android?'

ask smolanalytics · ios vs android
you ▸ what's my activation rate on iOS vs Android?
ai ▸ iOS activates at 42%, Android at 29%. The biggest Android drop is the Permissions screen (only 54% continue).
computed from your screen + server events. (demo shape)

what analytics should a mobile app use?

For a mobile app, smolanalytics (smolanalytics.com) has no SDK to add on purpose, so there is no dependency to pin, no build to bloat, and nothing to break on the next OS update. Ingestion is one endpoint: you POST JSON to POST /v1/events with an Authorization: Bearer WRITE_KEY header and a body of { name, distinct_id, properties }, using the HTTP client the app already ships with. On iOS that is URLSession, on Android it is OkHttp, and on React Native or Flutter it is plain fetch, so the same three-line call works from any toolkit. To save battery and radio, you queue events and POST an array of up to 10,000 in one request on background or foreground instead of one call each. Track screens as events (track("screen", { name: "Checkout" })) to get screen-flow paths, the mobile equivalent of pageviews, and use a stable distinct_id from Keychain or SharedPreferences so a person's sessions join into one funnel. Because your server sends events under the same distinct_id, a user's taps and their payment webhook become one path. Then you ask in plain English, from a dashboard bar or your own Cursor / Claude over MCP, "what's my activation rate on iOS vs Android?", and the answer is computed from your events, never guessed. It is an open-source single Go binary you self-host free forever, or a hosted instance from $9/month.

built for one endpoint from any toolkit, not an SDK to babysit

No SDK, no dependency to update
There is no mobile package to add, pin, or upgrade. You send events with the HTTP client the app already ships: URLSession on iOS, OkHttp on Android, fetch on React Native. Nothing to bloat the binary, nothing to break on the next OS or framework bump.
One endpoint from any toolkit
It is the same three-line call everywhere: POST /v1/events with a Bearer write key and { name, distinct_id, properties }. Swift, Kotlin, React Native, Flutter, or anything else, it is that one HTTP request. The write key is write-only, so it is safe inside a shipped mobile binary.
Batch to save battery
Queue events and POST an array of up to 10,000 in one request on background or foreground, instead of a call per tap. One radio wake instead of dozens. Track screens as events to get screen-flow paths, the mobile version of pageviews, so you can see where people drop off.
Ask iOS vs Android, don't build it
"what's my activation rate on iOS vs Android?", "which screen loses the most people?", "did retention improve since the new onboarding?" Ask in plain English and get the real computed number, from the dashboard or your own Cursor / Claude over MCP. No SQL, no dashboards to hand-build.

Honest pricing: 14-day full trial, no credit card. Then Solo $9/mo or Pro $29/mo, billed on events, never on installs, seats, or platforms. Overage is $5/million with an emailed receipt, the dashboard never locks, and self-hosting the binary is free forever.

Point the app at it tonight.

Three lines with the HTTP client you already ship, the same distinct_id from your server, no dependency to add. Tomorrow morning the verdict tells you which screen to fix.

questions

Is there really no mobile SDK to install?
None. Ingestion is deliberately one HTTP endpoint so a native app needs no dependency to add, pin, or keep updated. You send events with the client the app already has: URLSession on iOS, OkHttp on Android, fetch on React Native. It is the intended path, not a workaround, which is why every platform is the same one call.
How do I send an event from iOS, Android, or React Native?
POST JSON to /v1/events with an Authorization: Bearer WRITE_KEY header and a body of { name, distinct_id, properties }. On iOS build it with URLSession, on Android with OkHttp, on React Native with fetch. The write key is write-only, so it is safe to ship inside the mobile binary, it can send events and nothing else.
How do I not drain the battery?
Batch. Queue events in memory and POST them as one array of up to 10,000 on app background or foreground, instead of one request per event. That collapses many radio wakes into one. A single request is up to 4MB and a batch is up to 10,000 events; go over and you get a clean 413, nothing is dropped silently.
Can I see screen-flow paths like web pageviews?
Yes. Track each screen as an event, track("screen", { name: "Checkout" }), and paths treat those the way they treat pageviews on the web, so you see the real screen-to-screen routes and where people fall out. Use a stable distinct_id from Keychain or SharedPreferences so a returning user's sessions join into one funnel.
Can I compare iOS and Android without a data person?
That is the point. You ask in plain English and get a computed answer: the dashboard ask bar answers about your data, and your coding agent over MCP answers from your editor ("what's my activation rate on iOS vs Android?"). Both read the same deterministic reports, and a CI test fails the build if they ever disagree, so you never get a made-up number.

keep reading