Analytics for React Native Implementation Guide
Once you've installed the Analytics React Native library, you can start collecting data through Segment's tracking methods:
The Identify method lets you tie a user to their actions and record traits about them. This includes a unique user ID and any optional traits you know about them like their email, name, or address. The traits option can include any information you want to tie to the user. When using any of the reserved user traits, be sure the information reflects the name of the trait. For example, email should always be a string of the user's email address.
To send updates for anonymous users who haven't yet signed up for your app, pass null for the userId like in the example below.
identify: (userId: string, userTraits?: JsonMap) => void;
The Track method lets you record the actions your users perform. Every action triggers an event, which also has associated properties that the track method records.
track: (event: string, properties?: JsonMap) => void;
The Screen method lets you record whenever a user sees a screen in your mobile app, along with optional extra information about the page being viewed.
You'll want to record a screen event whenever the user opens a screen in your app. This could be a view, fragment, dialog, or activity depending on your app.
Not all integrations support screen, so when it's not supported explicitly, the screen method tracks as an event with the same parameters.
screen: (name: string, properties?: JsonMap) => void;
For setting up automatic screen tracking, see the Automatic Screen Tracking instructions.
The Group method lets you associate an individual user with a group— whether it's a company, organization, account, project, or team. This includes a unique group identifier and any additional group traits you may know, like company name, industry, or number of employees. You can include any information you want to associate with the group in the traits option. When using any of the reserved group traits, be sure the information reflects the name of the trait. For example, email should always be a string of the user's email address.
group: (groupId: string, groupTraits?: JsonMap) => void;
The Analytics React Native utility methods help you to manage your data. They include:
- Alias
- Reset
- Flush
- Cleanup
The alias method is used to merge two user identities by connecting two sets of user data as one. This method is required to manage user identities in some of Segment's destinations.
alias: (newUserId: string) => void;
The reset method clears the internal state of the library for the current user and group. This is useful for apps where users can log in and out with different identities over time.
Warning
Note: Each time you call reset, a new AnonymousId is generated automatically.
reset: () => void;
By default, the analytics client sends queued events to the API every 30 seconds or when 20 events accumulate, whichever occurs first. This also occurs whenever the app resumes if the user has closed the app with some events unsent. These values can be modified by the flushAt and flushInterval config options. You can also trigger a flush event manually.
flush: () => Promise<void>;
In case you need to reinitialize the client, that is, you've called createClient more than once for the same client in your application lifecycle, use this method on the old client to clear any subscriptions and timers first.
1let client = createClient({2writeKey: 'KEY'3});45client.cleanup();67client = createClient({8writeKey: 'KEY'9});
If you don't do this, the old client instance would still exist and retain the timers, making all your events fire twice.
Ideally, you shouldn't have to use this method, and the Segment client should be initialized only once in the application lifecycle.
Analytics React Native was built to be as extensible and customizable as possible to give you the ability to meet your bespoke analytics needs.
- Control upload with flush policies
- Add or remove policies
- Create your own flush policies
- Automatic screen tracking
- React navigation
- React Native navigation
- Handle errors
- Report errors from plugins
- Native anonymousId
- Retrieving the anonymousId
- Configure iOS deep link tracking
- Device identifiers
- Using a WebView Component with React Native
To more granularly control when events are uploaded you can use FlushPolicies
A Flush Policy defines the strategy for deciding when to flush, this can be on an interval, on a certain time of day, after receiving a certain number of events or even after receiving a particular event. This gives you even more flexibility on when to send event to Segment.
To make use of flush policies you can set them in the configuration of the client:
1const client = createClient({2// ...3flushPolicies: [4new CountFlushPolicy(5),5new TimerFlushPolicy(500),6new StartupFlushPolicy(),7],8});
One of the main advantages of FlushPolicies is that you can add and remove policies on the fly. This is very powerful when you want to reduce or increase the amount of flushes.
For example you might want to disable flushes if you detect the user has no network:
12import NetInfo from "@react-native-community/netinfo";34const policiesIfNetworkIsUp = [5new CountFlushPolicy(5),6new TimerFlushPolicy(500),7];89// Create our client with our policies by default10const client = createClient({11// ...12flushPolicies: policies,13});1415// If we detect the user disconnects from the network remove all flush policies,16// that way we won't keep attempting to send events to segment but we will still17// store them for future upload.18// If the network comes back up we add the policies back19const unsubscribe = NetInfo.addEventListener((state) => {20if (state.isConnected) {21client.addFlushPolicy(...policiesIfNetworkIsUp);22} else {23client.removeFlushPolicy(...policiesIfNetworkIsUp)24}25});
You can create a custom FlushPolicy special for your application needs by implementing the FlushPolicy interface. You can also extend the FlushPolicyBase class that already creates and handles the shouldFlush value reset.
A FlushPolicy only needs to implement 2 methods:
start(): Executed when the flush policy is enabled and added to the client. This is a good place to start background operations, make async calls, configure things before executiononEvent(event: SegmentEvent): Gets called on every event tracked by your clientreset(): Called after a flush is triggered (either by your policy, by another policy or manually)
They also have a shouldFlush observable boolean value. When this is set to true the client will attempt to upload events. Each policy should reset this value to false according to its own logic, although it is pretty common to do it inside the reset method.
1export class FlushOnScreenEventsPolicy extends FlushPolicyBase {23onEvent(event: SegmentEvent): void {4// Only flush when a screen even happens5if (event.type === EventType.ScreenEvent) {6this.shouldFlush.value = true;7}8}910reset(): void {11// Superclass will reset the shouldFlush value so that the next screen event triggers a flush again12// But you can also reset the value whenever, say another event comes in or after a timeout13super.reset();14}15}
As sending a Screen event with each navigation action can get tiresome, it's best to track navigation globally. The implementation is different depending on which library you use for navigation. The two main navigation libraries for React Native are React Navigation and React Native Navigation.
You can handle analytics client errors through the errorHandler option.
The error handler configuration receives a function which will get called whenever an error happens on the analytics client. It will receive an argument of SegmentError type.
You can use this error handling to trigger different behaviours in the client when a problem occurs. For example, if the client gets rate limited you could use the error handler to swap flush policies to be less aggressive:
1const flushPolicies = [new CountFlushPolicy(5), new TimerFlushPolicy(500)];23const errorHandler = (error: SegmentError) => {4if (error.type === ErrorType.NetworkServerLimited) {5// Remove all flush policies6segmentClient.removeFlushPolicy(...segmentClient.getFlushPolicies());7// Add less persistent flush policies8segmentClient.addFlushPolicy(9new CountFlushPolicy(100),10new TimerFlushPolicy(5000)11);12}13};1415const segmentClient = createClient({16writeKey: 'WRITE_KEY',17trackAppLifecycleEvents: true,18collectDeviceId: true,19debug: true,20trackDeepLinks: true,21flushPolicies: flushPolicies,22errorHandler: errorHandler,23});24
The reported errors can be of any of the ErrorType enum values.
Plugins can also report errors to the handler by using the .reportInternalError function of the analytics client, Segment recommends that you use the ErrorType.PluginError for consistency, and attaching the innerError with the actual exception that was hit:
1try {2distinctId = await mixpanel.getDistinctId();3} catch (e) {4analytics.reportInternalError(5new SegmentError(ErrorType.PluginError, 'Error: Mixpanel error calling getDistinctId', e)6);7analytics.logger.warn(e);8}
If you need to generate an anonymousId either natively or before the Analytics React Native package is initialized, you can send the anonymousId value from native code. The value has to be generated and stored by the caller. For reference, you can find a working example in the app and reference the code below:
iOS
1...2#import <segment_analytics_react_native-Swift.h>34- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions5{6...7// generate your anonymousId value8// dispatch it across the bridge910[AnalyticsReactNative setAnonymousId: @"My-New-Native-Id"];11return yes12}
Android
1// MainApplication.java2...3import com.segmentanalyticsreactnative.AnalyticsReactNativePackage;45...6private AnalyticsReactNativePackage analytics = new AnalyticsReactNativePackage();78...9@Override10protected List<ReactPackage> getPackages() {11@SuppressWarnings("UnnecessaryLocalVariable")12List<ReactPackage> packages = new PackageList(this).getPackages();13// AnalyticsReactNative will be autolinked by default, but to send the anonymousId before RN startup you need to manually link it to store a reference to the package14packages.add(analytics);15return packages;16}17...18@Override19public void onCreate() {20super.onCreate();21...2223// generate your anonymousId value24// dispatch it across the bridge2526analytics.setAnonymousId("My-New-Native-Id");27}
The React Native library does not have a specific method for retrieving the anonymousId. However, you can access this value by calling the following in your code:
segmentClient.userInfo.get().anonymousId
Retrieving the anonymousId can be useful if you need to pass this value to your backend, or if you're using a web view component with Segment's Analytics.js library and need to link user activity.
Warning
This is only required for iOS if you're using the trackDeepLinks option. Android doesn't require any additional setup.
To track deep links in iOS, add the following to your AppDelegate.m file:
1#import <segment_analytics_react_native-Swift.h>2....3- (BOOL)application:(UIApplication *)application4openURL: (NSURL *)url5options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {67[AnalyticsReactNative trackDeepLink:url withOptions:options];8return YES;9}
On Android, Segment's React Native library generates a unique ID by using the DRM API as context.device.id. Some destinations rely on this field being the Android ID, so be sure to double-check the destination's vendor documentation. If you choose to override the default value using a plugin, make sure the identifier you choose complies with Google's User Data Policy. For iOS the context.device.id is set the IDFV.
To collect the Android Advertising ID provided by Play Services, Segment provides a plugin that can be used to collect that value. This value is set to context.device.advertisingId. For iOS, this plugin can be used to set the IDFA context.device.advertisingId property.
If you use a webView component in your app that uses Segment's Analytics.js library, you can use Segment's Querystring API to pass the anonymousId from your React Native app to Analytics.js to ensure activity from anonymous users can be linked across these two sources.
To retrieve and pass the anonymousId:
- Retrieve anonymousId from the React Native library using:
const anonymousId = segmentClient.userInfo.get().anonymousId
- Pass this value into the querystring that opens the webview using the
ajs_aidoptional query string parameter noted in the documentation above. For example, the URL that opens your webview might look like:
http://segment.com/?ajs_aid={anonymousId}
- When a user clicks the element that opens the webview, Analytics.js will read that parameter and automatically set the anonymousId to whatever value is passed in, linking your events across both libraries to the same user.