React Native and Expo
One package, apparent-expo, for Expo (managed or prebuild) and bare React Native. No native code of its own.
Install
Expo:
npx expo install apparent-expo @react-native-async-storage/async-storage expo-application expo-localizationBare React Native:
npm install apparent-expo @react-native-async-storage/async-storage && npx pod-installOnly react-native and @react-native-async-storage/async-storage are required. expo-application, expo-localization, react-native-device-info and expo-router are used when the app has them.
Start it
In the root layout (app/_layout.tsx) or App.tsx, once:
import { Apparent } from "apparent-expo";
Apparent.init({ apiUrl: "https://in.apparent.fyi", app: "<app id>", key: "<write key>" });Add disabled: __DEV__ if you don't want development builds counted at all. You usually don't need to: simulators and test phones are left out of the numbers by themselves.
Screens
expo-router, in the root layout:
import { useApparentScreens } from "apparent-expo/router";
useApparentScreens();React Navigation:
import { apparentScreens } from "apparent-expo/navigation";
import { NavigationContainer, useNavigationContainerRef } from "@react-navigation/native";
export default function App() {
const ref = useNavigationContainerRef();
return <NavigationContainer ref={ref} {...apparentScreens(ref)}>{/* … */}</NavigationContainer>;
}Any other navigator: Apparent.screen("settings").
Events and users
Apparent.track("paywall_view", { source: "onboarding" });
Apparent.setProperties({ plan: "free" }); // added to every later event
Apparent.identify(user.id); // after sign-in
Apparent.reset(); // on sign-outMore in Events and users.
Purchases
await Apparent.linkRevenueCat(Purchases); // after Purchases.configureSee RevenueCat.
Errors and opting out
- Crashes and unhandled promise rejections are caught by themselves (release builds).
- Errors you catch:
Apparent.captureError(error). - Someone declines analytics:
Apparent.optOut(), andApparent.optIn()to start again. Remembered. - Ask for consent first? Start with
optOutByDefault: trueand callApparent.optIn()once they agree. Nothing is collected before that. - Nothing showing up? In a debug build the SDK prints
Apparent: app id or key is wrong — events are not being savedonce when the app id or key doesn't match. Copy both again from Connect. - Simulators and emulators say so themselves (
simulatorin each batch), so they're never counted, even in a release build.
Links, notifications and your own filter
- Links. When a link opens the app, the SDK sends
deep_link_openedwith the link (secrets liketoken=orcode=replaced by[redacted]) and itsutm_source,utm_mediumandutm_campaign. A campaign link that opens the app on its first day counts as where that person came from. Turn it off withtrackDeepLinks: false. - Notifications. With
expo-notificationsin the app, a tap sendspush_openedwith thecampaignandtitleyou put in the notification's data. Never the text people saw. Turn it off withtrackPushOpens: false. - Your own filter.
beforeSendsees every event before it is saved. Return it changed, ornullto drop it:
Apparent.init({
apiUrl: "https://in.apparent.fyi", app: "<app id>", key: "<write key>",
beforeSend: (event) => {
if (event.name === "debug_tap") return null;
const { email, ...props } = event.props ?? {};
return { ...event, props };
},
});Bare React Native: versions
Without expo-application or react-native-device-info the SDK can't read your app's version. Pass it, or app updates can't be noticed:
import { version } from "./package.json";
Apparent.init({ apiUrl: "https://in.apparent.fyi", app: "<app id>", key: "<write key>", appVersion: version });What it promises
- Every event is saved on the phone within a quarter second, and right away when the app goes to the background or crashes.
- Up to 1,000 events wait offline for a week. Nothing is sent twice by mistake: the server ignores repeats.
- One request at a time, 10 seconds each, retries that wait longer each time.
Automatic events: first_open, app_open, app_updated, app_background, screen_view, error, deep_link_opened, push_opened (with expo-notifications), and install_source on Android.