Quickstart: RN / Expo
Add FounderHQ to a React Native or Expo app.
Install the SDK, create the client once, and see your first event in FounderHQ. About 5 minutes.
Before you start
You need a FounderHQ account and a publishable key. In the app, open Sequences → Settings → Event API keys, create a key for Browser/mobile, and copy it. The full key is shown only once.
Install the SDK
npx expo install @founderhq/events-react-native \
@react-native-async-storage/async-storage \
expo-application expo-device expo-localizationThe three Expo packages let the SDK report app version, device model,
locale, and time zone. Building bare React Native? Install
@founderhq/events-react-native and
@react-native-async-storage/async-storage with npm, and skip them.
Create the client once
Create one module and import it everywhere.
// lib/analytics.ts
import { createFounderHqExpoClient } from "@founderhq/events-react-native/expo";
export const events = createFounderHqExpoClient("fhq_pk_XXXX");Bare React Native uses the same API without the Expo context:
import { FounderHqReactNativeClient } from "@founderhq/events-react-native";
export const events = new FounderHqReactNativeClient("fhq_pk_XXXX");App lifecycle, sessions, and on-device queuing start immediately. The queue survives a restart, so events captured offline still arrive.
Track screens
Expo Router:
import { usePathname } from "expo-router";
import { useEffect, useMemo } from "react";
import { createExpoRouterTracker } from "@founderhq/events-react-native";
import { events } from "./lib/analytics";
export function ScreenTracker() {
const pathname = usePathname();
const trackScreen = useMemo(() => createExpoRouterTracker(events), []);
useEffect(() => {
trackScreen(pathname);
}, [pathname, trackScreen]);
return null;
}React Navigation instead? Pass your navigationRef to
createReactNavigationTracker(events, navigationRef) and spread the
returned onReady and onStateChange onto <NavigationContainer>.
Identify and capture
events.identify("user_8421", { email: "jane@acme.com", plan: "pro" });
events.capture("trial.started", { plan: "pro" });Pass your own stable user ID, not an email. Call events.reset() on
sign-out.
Verify
- Run the app on a simulator or device and trigger the event.
- In FounderHQ, open Sequences → Events.
- You see
trial.startedwithplan: pro, a$session_start, and a$screenfor the screen you opened. - Open Sequences → Contacts. Jane is there with her email.
Events can take a few seconds to appear. The SDK batches them. To send
immediately, await events.flush().
Troubleshoot
Events only appear after a restart
That is the queue doing its job. It flushes on a timer, on batch size, and when the app goes to the background.
Purchases are not attributed
In-app purchases need the purchase claim flow, not capture. See
Mobile purchase claims.