React Native and Expo
@rabolic/react-native is Rabolic for React Native apps on iOS and Android, Expo included: app installs, opens and updates, sessions, screens, identity and deep links. It has no native code of its own. Events are kept in AsyncStorage until they are sent. Source: github.com/rabolic/sdks/js/react-native.
Use the project's publishable key (rb_pub_…). A secret key is refused: it must never ship in an app.
Install
The quickest way is npx rabolic init in your app's folder. By hand:
npx expo install @rabolic/react-native @react-native-async-storage/async-storage
npm install @rabolic/react-native @react-native-async-storage/async-storage && cd ios && pod install
Initialize
import { rabolic } from '@rabolic/react-native'
// Once, at app start. You don't have to await it: calls made before it finishes are kept.
void rabolic.init({ projectKey: 'rb_pub_…', app: { version: '4.12.0', build: '412' } })
// after signup or login, on every platform with the same id
rabolic.identify(user.id, { plan: 'pro' })
rabolic.track('workout_started', { program_id: 'strength-30' })
Pass your app's version (app.version): with it, the first launch on a new version sends $app_update. In Expo, Application.nativeApplicationVersion from expo-application has it.
Options
| Option | Default | |
|---|---|---|
projectKey | required | rb_pub_… |
host | https://ingest.rabolic.com | For a first-party proxy |
app | none | { version, build, bundle } |
trackLifecycle | true | The four $app_ events |
consent | granted | The state to start with when the app hasn't set one |
flushAt | 20 | Send when this many events are queued (1–500) |
flushIntervalMs | 15000 | Send at least this often |
maxQueueSize | 10000 | Events kept on the device; the oldest go first |
debug | false | Log calls and responses |
Screens
With React Navigation, hand the container's ref to trackNavigation once it's ready. Every route change sends $screen with the route's name:
const ref = useNavigationContainerRef()
<NavigationContainer ref={ref} onReady={() => rabolic.trackNavigation(ref)}>
With Expo Router, in app/_layout.tsx:
import { useNavigationContainerRef } from 'expo-router'
const ref = useNavigationContainerRef()
useEffect(() => rabolic.trackNavigation(ref), [ref])
Or send screens yourself:
rabolic.screen('Paywall', { variant: 'b' })
Automatic events
| Event | When |
|---|---|
$app_first_open | The first launch after install |
$app_update | The first launch on a new app.version, with previous_version |
$app_open | Each launch and each return to the foreground, with from_background |
$app_background | Going to the background, with foreground_ms. Queued events are sent then |
trackLifecycle: false turns these events off.
Sessions
A session starts at launch, and again on return after more than 30 seconds in the background. The project's mobile background timeout can change the 30 seconds. Background time never counts as active time. See Sessions.
API
| Method | Does |
|---|---|
init(options) | Starts the SDK. A second call returns the first one's promise |
track(event, properties?) | Custom event. snake_case; names starting with $ are reserved |
screen(name, properties?) | A $screen view |
trackNavigation(ref) | $screen on every React Navigation route change. Returns a function that stops it |
identify(userId, traits?) | Sets user_id on this and later events; sends $identify with traits |
reset() | Logout: new anonymous id and session, no user id, no super properties |
register(properties) / unregister(key) | Super properties, sent with every later event |
setConsent(state), optIn(), optOut() | Consent |
trackDeepLink(url) | $deep_link for a link the app was opened with |
flush() | Sends the queue now. Never rejects |
getAnonymousId() | This install's anonymous id, or null before init finishes |
Calls never throw. Problems are logged with debug: true.
Identity
Call identify() after signup and after every login, with the same user id you use on the web and on your server. Call reset() at logout. See Identity.
Deep links
rabolic.trackDeepLink(url) sends $deep_link for a link the app was opened with. An rb_aid parameter, which the web SDK's appLink() adds, is sent as linked_anonymous_id. Rabolic stores it, but doesn't join the web visitor to the app user by it yet. identify() with the same user id on web and app does.
Consent
| State | What happens |
|---|---|
granted (default) | Tracks and sends normally |
pending | Keeps events in memory only and sends nothing |
denied | Drops everything and clears the queue |
consent in the options is the state to start with when the app hasn't set one. Change it at runtime with setConsent(), optIn() or optOut(). See Consent and privacy.
Random ids
Ids use crypto.getRandomValues when the runtime has it (recent React Native, or the react-native-get-random-values polyfill). Without it they fall back to Math.random: unique enough for analytics, but not unguessable.
Limits
| Queue | 10,000 events on the device (maxQueueSize). When full, the oldest go first |
| Batch | Up to 500 events or 900 KB |
| One event | 32 KB (32,768 bytes of UTF-8 JSON). Larger events are dropped |
| Event age | Events older than 7 days are dropped before sending |
See Limits.
Web
Install @rabolic/web from npm or a script tag. Options, automatic page views and page leaves, campaigns, sessions, identity, consent, cookieless mode and limits.
Flutter
Install rabolic_flutter for iOS, Android and Flutter web. Configuration, lifecycle events, screens with Navigator, go_router and auto_route, identity, in-app purchase tokens, deep links, consent, app store privacy forms and limits.