Integration with React Native

We know that React Native is very famous recently. It has great DX and it provides a lot of speed to projects. We are very happy to having an official integration library and fully supporting React Native. If you are looking for Android please check Android and for iOS please check iOS docs. For other mobile integrations please check mobile integration. If you are with React Native, you are in the right place. Let's start!

Our official integration library in NPM, which name is @metricalp/react-native

Installation

You can install it as:

yarn add @metricalp/react-native

or

npm install @metricalp/react-native

Integration

We tried to make integration flexible and smooth to keep developer experience in best level. Here we will share a complete App.tsx (from an example Expo project) to show how you can integrate Metricalp to your React Native app in your entrypoint file (App.js, main.js, index.js...). Then we will define every detail of the code below.

tsx
        import { StatusBar } from 'expo-status-bar';
        import { AppState, NativeEventSubscription, Platform, StyleSheet, Text, View } from 'react-native';
        import { Metricalp } from '@metricalp/react-native';
        import * as Crypto from 'expo-crypto';
        import AsyncStorage from '@react-native-async-storage/async-storage';
        import { useEffect, useState } from 'react';
        
        export default function App() {
          const [appInitialized, setAppInitialized] = useState(false);
        
          useEffect(() => {
            let subscription: NativeEventSubscription;
        
            async function init() {
              let uuid = await AsyncStorage.getItem('uuid');
              if (!uuid) {
                uuid = Crypto.randomUUID();
                await AsyncStorage.setItem('uuid', uuid);
              }
              const osWithVersion = (Platform.OS === 'ios' ? 'iOS' : 'Android') + ' ' + Platform.Version;
        
              Metricalp.init({
                platform: Platform.OS,
                app: 'ExampleApp@1.0.0',
                language: 'English-US',
                os: osWithVersion,
                uuid,
                tid: 'mam48',
              }, 'MainScreen');
        
              subscription = AppState.addEventListener('change', (nextAppState) => {
                if (nextAppState === 'background' || nextAppState === 'inactive') {
                  Metricalp.appLeaveEvent();
                } else if (nextAppState === 'active') {
                  Metricalp.screenViewEvent('MainScreen');
                }
              });
        
              setAppInitialized(true);
            }
        
            init();
        
            return () => {
              subscription?.remove();
            };
          }, []);
        
          return (
            <View style={styles.container}>
              {appInitialized ? (
                <View>
                  <Text>Open up App.tsx to starddt working on your app!</Text>
                  <StatusBar style="auto" />
                </View>
              ) : (
                <Text>Loading...</Text>
              )}
            </View>
          );
        }
        
        const styles = StyleSheet.create({
          container: {
            flex: 1,
            backgroundColor: '#fff',
            alignItems: 'center',
            justifyContent: 'center',
          },
        });
        

Firstly, we imported import { Metricalp } from '@metricalp/react-native'; library which we call methods through it.

The first method to call is Metricalp.init and the most important one is to properly integrate. We will init Metricalp to collect events. It is important to do this in entrypoint file (App.js, main.js, index.js...). Metricalp.init takes attributes object, initial screen path (for auto triggered first screen_view as optional). If you not provide initial screen, then it will skip auto triggered first screen_view event. Let's explain:

Metricalp.init() Attributes Argument Props

platform (required)

You need to provide current platform. Possible values are ios or android. All must be lowercase. You can get it with Platform.OS from react-native like above example.

app

You should provide your app name and version. It is important to provide version to track it in dashboard. You can provide it as AppName@Version syntax ExampleApp@1.0.0 like above example.

language

You should provide your current app language. You can provide it as Language (long name)-Country(ISO Code) syntax English-US like above example or Spanish-ES orTurkish-TR etc. If you are not sure about country, you can provide unknown. For example English-unknown

os

You can provide your current app OS and version. You can provide it as OSName OSVersion syntax iOS 14.5 like above example or Android 11.Here we converted ios to iOS and android to Android to have a beatuiful and consistent data in dashboard (just lowercase => uppercase conversions). It is optional but suggested.

uuid

We need to explaing this UUID prop. Normally in Web tracking, Metricalp is not using cookies as we mentioned in many places. We are identifying users with their IP addresses in one-way hashes. The formula is something like this: hash(user_ip + user_agent + salt). Here ip + user_agent is almost unique for every user. But in mobile apps, user agent strings are inconsistent and not reliable. So we need to have a unique identifier for every user. We left this unique identifier to you. You can use any unique identifier for your app. For example if it is an authorization app and you are tracking only after users logged-in, then you can provide user ids. Or you can use device related real unique identifiers (Android and iOS has some native methods to get it). Or, as like above example, you can generate a random UUID when user first opens the app and store it in storage (we used AsyncStorage above). Then use it as UUID. Now, the hashing algorithm will be like hash(user_ip + UUID + salt). In this approach, the UUID will be unchanged unless user removes and re-installs the app. But that is fair enough. If it is not enough for you, you can provide your own unique identifier as we mentioned above. User ID or device identifier or any other combination. If you just want to use IP then just pass empty string '' as UUID or completely omit it. But, we strongly suggest to use a unique identifier for better tracking. UUID is optional but suggested.

bypassIpUniqueness

This is an optional prop. Possible values are "enable" or "disable". If you see above final hash example with metr_unique_identifier: hash(user_ip + metr_unique_identifier + salt), we still have IP info in the hash. Then, when user for example in Wifi and then changed to mobile network, then IP will be changed. While metr_unique_identifier is same, because of IP change, it may count as another unique count for that day. This setting removes also ip from hash. If you set this as "enable", then we will not use IP in hash function (as default): hash(metr_unique_identifier + salt). But if you pass disable, then ip will also used in hash function: hash(user_ip + metr_unique_identifier + salt). We are not suggesting this because breaking unique count with ip is meaningless in most scenarios for mobile. Then, we set this settings default as enable. So, in most scenarios just do not pass this option, let it be default (enable).

tid (required)

You should provide your TID (a.k.a Tracking ID) to init method. You can get it from Metricalp dashboard. It is required. If you don't provide it, you will get an error. You can find your tid in Embed & Share Tracker page.

More Details about Integration

Well, we defined all possible props. But there are a few details in above code. Let's explain all them now.

Firstly, we made our app initialization in useEffect with an async function. We set a state to show a Loading text to user while we are initialization. You can show a splash screen or any other loading screen. You can init and configure any other settings for your app in this function, this is a common approach.

Inside of init() function (in useEffect), we are checking for UUID in AsyncStorage, if there is not one, we are generating it. AsyncStorage and UUID functions are from Expo but you can use any library you wish. Then we are generating an OS with version string. Then we are calling Metricalp.init with all props. As we mentioned above, Metricalp will fire first screen_view event automatically with the path (second argument of init function), but you can skip this with omitting second argument.

tsx
   Metricalp.init({
          platform: Platform.OS,
          app: 'ExampleApp@1.0.0',
          language: 'English-US',
          os: osWithVersion,
          uuid,
          bypassIpUniqueness: true,
          tid: 'mam48',
    }) // Here we omitted screen name to disable auto fire

There are two important system event scenarios in Metricalp React Native integration: screen view and app leave. We are tracking visited screens, bounce rates etc based on these events. So, we strongly suggesting that you should trigger these events in your app additional to any custom events. You should use library provided methods to trigger these events. In above example, we are listening AppState changes by React Native and triggering these events whenever app is active or inactive/background state. We are using screenViewEvent and appLeaveEvent methods from library.

tsx
        ...
        ...
        subscription = AppState.addEventListener('change', (nextAppState) => {
          if (nextAppState === 'background' || nextAppState === 'inactive') {
            Metricalp.appLeaveEvent();
          } else if (nextAppState === 'active') {
            Metricalp.screenViewEvent('MainScreen');
          }
        });
  
        setAppInitialized(true); // Set state to show app content
      }
  
      init(); // call init function
  
      return () => {
        subscription?.remove(); // Remove subscription on unmount to prevent memory leaks
      };
      ...
      ...

Metricalp.screenViewEvent method provided by library to make it easier for you. You should provide current screen name (path) to this method. You can also pass any additional data (custom props) to these methods as second argument:

tsx
Metricalp.screenViewEvent('MainScreen', { custom_prop1: 'Unauthenticated User' });

Metricalp.appLeaveEvent method provided by library again to make it easier for you. You can pass any additional data (custom props) to these methods as first argument:

tsx
Metricalp.appLeaveEvent({ custom_prop1: 'Unauthenticated User' });

Here the theme is a custom prop alias. You can check Custom Event & Props docs for detailed info.

Basically that is all. You successfully integrated your React Native app with Metricalp now. One more thing is, you can also create some custom events to get more deep insights.

Custom Events

There is also another method from library for custom events: Metricalp.customEvent. It takes event type as first argument and data attributes as second argument. You can use it like:

tsx
Metricalp.customEvent('click_purchase', {path: 'PricingScreen', custom_prop1: user.id, theme: 'dark'})

Here we passed path info, also we passed user.id as custom_prop. We passed another custom prop theme but we used alias this time. You can check Custom Event & Props for detailed info. Now with power of custom events and props you can track and analyze any event to get deep insights.