lib/analytics.ts (Expo managed, fetch) · open source (MIT) · ask in plain English

Add analytics to Expo.

Expo analytics means tracking navigation and taps in a managed React Native app across iOS, Android, and web. smolanalytics has no Expo module or config plugin. You send events with fetch to /v1/events, which stays inside the managed workflow with no native build step. Batch to save battery, then ask your numbers in plain English.

lib/analytics.ts (Expo managed, fetch)
const host = 'https://YOUR-INSTANCE';
const key = 'WRITE_KEY';

export function track(name: string, distinctId: string, properties: Record<string, unknown> = {}) {
  return fetch(`${host}/v1/events`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
    body: JSON.stringify({ name, distinct_id: distinctId, properties }),
  });
}

// batch on background: POST an array to the same endpoint
// import { AppState } from 'react-native';
// AppState.addEventListener('change', s => { if (s !== 'active') flushQueue(); });

No Expo config plugin needed and no native rebuild. fetch is built in, so this works in the managed workflow and in Expo Go. Call track from an Expo Router or React Navigation listener.

how do I add analytics to expo?

Expo analytics means tracking navigation and taps in a managed React Native app across iOS, Android, and web. smolanalytics has no Expo module or config plugin. You send events with fetch to /v1/events, which stays inside the managed workflow with no native build step. Batch to save battery, then ask your numbers in plain English.

Drop track() into an Expo Router segment effect or a React Navigation screen listener so every screen logs a screen_view with the route name, and call it on the taps that matter (signup, purchase, invite). Use a stable distinct_id, the user id after login and a persisted install id before, so one person threads across screens without any native code.

Keep requests low on device. Queue events in an array and flush a batched JSON POST to /v1/events on an interval or when AppState leaves active. It is the identical endpoint and write key your web build and backend use, so a user who moves between mobile and web stays one profile, and you can ask in plain English which step of onboarding leaks.

Honest pricing: 14-day full trial, no credit card. Then Solo $29/mo, never metered on seats or sites. Overage is $5/million with an emailed receipt, the dashboard never locks, and self-hosting the single Go binary is free forever (MIT).

Add analytics to Expo tonight.

One snippet, or one endpoint. Tomorrow morning the verdict tells you which part of the funnel to fix.

questions

How do I add analytics to Expo?
Expo analytics means tracking navigation and taps in a managed React Native app across iOS, Android, and web. smolanalytics has no Expo module or config plugin. You send events with fetch to /v1/events, which stays inside the managed workflow with no native build step. Batch to save battery, then ask your numbers in plain English.
Do I need a cookie banner?
Not in cookieless mode. smolanalytics can run without storing anything on the device, so there is no consent banner to add. You still get visitors, referrers, funnels, retention, and paths, and AI-assistant referrals (chatgpt.com, claude.ai, perplexity.ai) show up as their own channel.
Is it enough for a real product, or just page counts?
It does funnels, retention, paths, cohorts, and a daily verdict on what to fix, from the same events, and you ask it in plain English. It deliberately skips session replay, feature flags, and experiments. If you want a straight answer on what to fix, that you own and can self-host free, it fits.

keep reading