-
Choose a provider. Each has different strengths:
| Provider | Best for | Free tier | Source maps | Session recording |
|---|
| Sentry | Crashes + performance monitoring | 5K errors/month | Yes | Yes (beta) |
| Firebase Crashlytics | Crash-only, Google ecosystem | Unlimited | Yes (via CLI) | No |
| PostHog | Product analytics + feature flags | 1M events/month | No | Yes |
| Mixpanel | Event funnels and retention | 20M events/month | No | No |
You can combine providers. A common pattern is Sentry for crashes + PostHog for product analytics.
-
Set up Sentry (recommended). For Expo:
npx expo install @sentry/react-native
Add the config plugin in app.json:
{
"expo": {
"plugins": [
[
"@sentry/react-native/expo",
{
"organization": "your-org",
"project": "your-project"
}
]
]
}
}
-
Initialize Sentry. In app/_layout.tsx or your entry point:
import * as Sentry from "@sentry/react-native";
Sentry.init({
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN!,
environment: __DEV__ ? "development" : "production",
tracesSampleRate: __DEV__ ? 1.0 : 0.2,
enabled: !__DEV__,
});
Wrap your root component:
export default Sentry.wrap(function RootLayout() {
return <Stack />;
});
-
Upload source maps for readable stack traces. With EAS Build, add a post-publish hook in app.json:
{
"expo": {
"hooks": {
"postPublish": [
{
"file": "@sentry/react-native/expo",
"config": {
"organization": "your-org",
"project": "your-project"
}
}
]
}
}
}
Set the auth token in your EAS secrets:
eas secret:create --name SENTRY_AUTH_TOKEN --value "your-token" --scope project
-
Track custom events. Beyond automatic crash reporting:
import * as Sentry from "@sentry/react-native";
Sentry.addBreadcrumb({
category: "navigation",
message: "User opened profile screen",
level: "info",
});
Sentry.captureMessage("User completed onboarding");
Sentry.captureException(new Error("Payment failed"), {
tags: { payment_provider: "stripe" },
extra: { amount: 999, currency: "usd" },
});
-
Set up PostHog for product analytics (optional). Install:
npx expo install posthog-react-native
Initialize in your app:
import { PostHogProvider } from "posthog-react-native";
export default function RootLayout() {
return (
<PostHogProvider
apiKey={process.env.EXPO_PUBLIC_POSTHOG_KEY!}
options={{
host: "https://us.i.posthog.com",
enableSessionReplay: true,
}}
>
<Stack />
</PostHogProvider>
);
}
Track events:
import { usePostHog } from "posthog-react-native";
function CheckoutScreen() {
const posthog = usePostHog();
const handlePurchase = () => {
posthog.capture("purchase_completed", {
product_id: "premium_yearly",
price: 39.99,
});
};
}
-
Identify users. Link analytics to authenticated users:
Sentry.setUser({ id: user.id, email: user.email });
posthog.identify(user.id, { email: user.email, plan: "premium" });
Sentry.setUser(null);
posthog.reset();
-
GDPR and privacy compliance. Respect user privacy:
import * as Sentry from "@sentry/react-native";
function disableTracking() {
Sentry.init({ enabled: false });
posthog.optOut();
}
function enableTracking() {
Sentry.init({ enabled: true, dsn: process.env.EXPO_PUBLIC_SENTRY_DSN! });
posthog.optIn();
}
Add a privacy settings screen where users can opt out of analytics. Required for EU users under GDPR and recommended for App Store review.