Technical DocReact Native

Contentsquare React Native Integration

Get Started

Add Contentsquare to your app

This guide walks you through the process of adding the Contentsquare SDKs to your React Native application. The Contentsquare Bridge for React Native is a bridge between the Contentsquare SDKs for iOS and Android, and your React Native JavaScript code. It allows for the use of our solution both in native and JavaScript parts of your app. The Contentsquare functionality is provided through a simple NPM package including only the bridge and dependencies to specific versions of the SDKs. Check the compatibility section for more information about these dependencies, and the minimum React Native version compatible for each version of the bridge.

Note that our Bridge is fully compatible with TypeScript, and includes a d.ts file in order to get typings within your TypeScript React Native projects when adding the Contentsquare Bridge.

How to include it

Open up a terminal window and navigate to the folder where your application is stored. First, find the latest version of the bridge compatible with your version of React Native using our compatibility table. Then, install the bridge as follows, specifying the exact version you want to install if needed:

$ npm install @contentsquare/react-native-bridge
$ cd ios && pod install

iOS specific note

As React Native projects are Objective-C projects for iOS, and our iOS SDK is written in Swift, you will have to embed the Swift standard libraries to your project. To do so, go to the Build Settings of your project's target, and set the Build Option Embedded Content Contains Swift Code to YES.

Also, you will have to make sure that your CocoaPods version is 1.10.0 or up (pod --version). If it is not, simply do [sudo] gem install cocoapods. Why ? CocoaPods is the tool that we use in order to link our SDK and our bridge for iOS on React Native, and having a lower version will make the linking of the both impossible, as the SDK is now embedded in an XCFramework, which were only supported by CocoaPods in late 2020.

How to import the bridge in your JavaScript code

The Contentsquare module is our main module, as well as the default export of our bridge. The Currency module is only used to send Transactions, and contains all supported currencies (see section Send Transactions).

import Contentsquare, {Currency} from '@contentsquare/react-native-bridge';

Important note about React Native apps with native code

Depending on if you created your app as a React Native first app, or if you gradually added some React Native code to your Native first app, you might be using some non JavaScript elements in your app, as well as a mix of native screens and JavaScript screens. If that is the case, it is your responsibility to track all of the screens, either by calling our native SDKs directly in the first case, or the bridge in the second. The same remark applies for other functionalities of the SDK - for example, you might need to send a Transaction Event via the native SDK or via the bridge, depending on the technology used to create your buying page.

Please have a look at the native SDKs documentation to find out how to call them in native parts of your app.

Also, please note that we specifically cover the use of the JavaScript bridge in this documentation. You should never call the Bridge's NativeModule directly yourself. If for any reason you do so, know that we cannot certify that your implementation will work as expected. Please only call our SDKs through the JavaScript Contentsquare module we provide in you JavaScript code (as explained in this document), or directly in your native code.

Start the SDK

You do not need to do anything to start the SDK. Now that the SDK is a dependency of your app, it will autostart itself when your application starts.

Enabling SDK Manual Start

If you prefer to control if and when the SDK starts, you can disable the autostart feature and programmatically start the SDK when needed.

Disabling autostart on iOS:

You need to edit the Info.plist, usually located in ios/{project_name}/, add the following key:

<dict>
    ...
    <key>CSDisableAutostart</key>
    <true/>
    ...
</dict>
Disabling autostart on Android:

You need to edit the AndroidManifest.xml, usually located in android/app/src/main/, add the following flag:

<application>
  ...
   <meta-data android:name="com.contentsquare.android.autostart" android:value="false"/>
  ...
</application>
Programmatically start the SDK

Then, you can start the Contentsquare SDK by calling the start() method of the Contentsquare class. This function should be called as early as possible in the app process. It is recommended to call this function in the useEffect of your App element:

const App = (): JSX.Element => {
    ...

    useEffect(() => {
        Contentsquare.start()
        ...
    });
    ...
}

Note about using Contentsquare along with Expo

Unfortunately, if you are currently using Expo, you will not be able to use the SDK without ejecting your app from expo, which is a non-reversible process that adds native projects to your React Native project, but remove all the Expo benefits. The reason for that is that our Bridge depends on our Native SDKs, and they cannot be imported in Expo - it is one of the limitation of this platform.

If you are starting a new Expo project though, note that there exist a starter project that can allow you to run your React Native app both in Expo and ejected from Expo. Note that, although we provide you with this link, we don't take any responsibility regarding it.

Validate SDK integration

Please look at the native SDK docs for validation on each platform.

In-app features

Alongside its tracking capabilities, the SDKs embed some features aimed at Contentsquare users such as Snapshot Capture & SDK Logs.

Implement in-app features

This implementation phase is required on the iOS side only (on Android, there is nothing to do). You will have to do a few changes on the native side of your app:

1. Add the custom URL scheme to Info.plist

In order for your application to open when you scan the QR code or enter the URL we provide in a web browser, you have to add the custom URL scheme to your app's Info.plist file. For more info about how to do it, check the iOS documentation.

2. Call the SDK when your app is opened with the custom URL

Then, you will need to link your app with our SDK. When your application is started via a deeplink, a specific delegate function is called in your AppDelegate file. In order for us to be able to handle it, you will need to call a function of our API that will handle it.

There are 2 ways to do so.

1. Call the react native API.

You can follow this guide to call the react native API.

Linking.addEventListener('url', (event: { url: string }) => {
    Contentsquare.handleUrl(event.url);
})
2. Call the iOS native API.

You will need to update your iOS application's AppDelegate, located in the ios folder of your React Native app (AppDelegate.m if you have a project set up in Objective-C, AppDelegate.swift if it is set up in Swift).

  1. Import ContentsquareModule in order to be able to call the Contentsquare API from the AppDelegate.

⚠️ If you are using Flipper, make sure you do not write the import after the FB_SONARKIT_ENABLED macro - to be sure, you can write your import at the topmost of the file. In general, make sure you do not import the SDK in the scope of an #ifdef macro.

[tab] Objective-C
##import <ContentsquareModule/Contentsquare-Swift.h>
[tab] Swift
import ContentsquareModule
[tabend]
  1. Implement the openURL delegate method as following.
[tab] Objective-C
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
    [Contentsquare handleWithUrl:url];
    return YES;
}
[tab] Swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    Contentsquare.handle(url: url)
    return true
  }
[tabend]

Check the full section in the Native iOS SDK documentation

Enable in-app features

In-app features can be enabled in different ways:

Scan the QR Code

If you have access to the Contentsquare platform, you can open the in-app features modal from the menu and scan the QR code displayed with your phone.

Take a look at the native documentation for further information.

Alternative methods

We provide alternative methods to enable in-app features especially for iOS Simulator and Android Emulator.

[tab] Android

Please follow the Native Android SDK documentation for Enable in-app features

[tab] iOS

Please follow the Native iOS SDK documentation for Enable in-app features

Debugging & Logging

Contentsquare provides Logging capabilities that allow you to see the raw event data logged by your app. This is very useful for validation purposes during the instrumentation phase of development and can help you discover errors and mistakes in your analytics implementation and confirm that all events are being logged correctly.

[tab] Android

Please follow the Native Android SDK documentation for Debugging & Logging

[tab] iOS

Please follow the Native iOS SDK documentation for Debugging & Logging

Snapshot Capture

In order to unlock the full data-visualization capabilities of Contentsquare, the SDK provides a way to capture snapshots of your app screens. These snapshots can only be taken by Contentsquare's users on their device. They are not captured from your end-users device. It means your Personal Data is safe, as long as you use a test user account.

For snapshot capture to work, the session has to be tracked (included in tracked users and not opted-out) and a first screenview event has to be sent before.

[tab] Android

Please follow the Native Android SDK documentation for Snapshot Capture

[tab] iOS

Please follow the Native iOS SDK documentation for Snapshot Capture

Track Screens

Contentsquare aggregates user behavior and engagement at the screen level. To do so, it is required to track screen transitions by calling a dedicated API. When the API is called, the SDK logs a screenview event that identifies the new screen with the screen name provided.

Sessions without at least one screenview will be discarded.

import Contentsquare from '@contentsquare/react-native-bridge';

// Contentsquare.send(string);
Contentsquare.send("ScreenName");

Screen name

The screen name length is not limited on the SDK side. However, the limit is 2083 characters on the server side.

Implementation recommendations

From a functional standpoint, we expect a screenview to be sent:

  • When the screen appears
  • When a modal/pop-up is closed and the user is back on the screen
  • When the app is put in the foreground (after an app hide)

How to name screens

As a general rule, it is recommended to have a number of distinct screen names under 100. As they are used to map your app in Contentsquare, you will want something comprehensive.

Separate words with space, dash or underscore characters

If you want to generate screen names including more than one word, it is best to separate them and to do so using space, dash or underscore characters. Contentsquare handles automatically the formatting for them.

Example: For a sub-category list of a retail app, use Home & Living - Home Furnishings instead of homeLivingHomeFurnishings.

Use screen template/layout names

As a general recommendation, it is recommended to use names referring to the screen template/layout rather than referring to the specific content (data). This will help:

  • To keep the number of distinct screen names low and therefore make Contentsquare easier to use
  • Remove the risk of sending Personal Data to Contentsquare

List of screen types falling into that category: Product detail, Event detail, Conversation/Chat, User profile...

Multiple layouts/states for one screen

In some cases, there will be screen that can have different layouts/states depending on the user context. In this situation, it would be interesting to append the layout/state value to the screen name. Examples:

  • Home screen of a travel app adapting its layout on the user context:
    StateScreen name
    No trip plannedHome - no trip
    Trip plannedHome - trip planned
    Trip about to startHome - upcoming trip
    Trip in progressHome - trip in progress
  • Product detail screen of an e-commerce app with different layouts depending on the type of product:
    StateScreen name
    Default templateProduct detail
    Template with suggested productsProduct detail - Suggestions
    Template with bundled productsProduct detail - Bundle

Track Transactions

To associate a user's session with their potential purchases (and corresponding revenue), you must send the transaction via a dedicated API. For each transaction, we send:

  • Price (number, mandatory)
  • Currency (Currency or string, mandatory)
  • Transaction ID (string, optional)
import Contentsquare, {Currency} from '@contentsquare/react-native-bridge';

// numeric currency: Contentsquare.sendTransaction(number, Currency, string?)
Contentsquare.sendTransaction(10, Currency.USD);
Contentsquare.sendTransaction(200, Currency.EUR, "my_transaction_1");

// alphanumeric currency: Contentsquare.sendTransactionWithStringCurrency(number, string, string?)
Contentsquare.sendTransaction(10, "USD");
Contentsquare.sendTransaction(200, "eur", "my_transaction_2");

Each transaction must only be sent once. A common mistake is to trigger the sending when the confirmation screen is displayed. This leads to triggering the transaction each time the user puts the app in background and then in foreground on the confirmation screen.

Currency

The currency is conforming to the ISO 4217 standard. Although the currency can be passed either as "alphanumeric code" or "numeric code", you should always prefer using the bridge's Currency object values. If you have to pass the ISO code as a string, note that capitalization is not a factor (Currency.USD, "USD", "Usd" or "usd" will all be treated as the US Dollar).

If the currency passed doesn't match our supported currencies, the SDK will send a currency value of "-1". It will be processed as the default currency of the project.

Track Dynamic Variables

General principles

Usage

Dynamic variables are additional information on the session that can be used to segment sessions.

For example, they can include information on the A/B Test variations displayed to the current user.

Limits

On the server side
  • It is possible to save up to 40 distinct dynamic variable keys per screen view. If more are received, only the first 40 keys will be kept.
  • If you are using the same key twice, the last value associated with the key will be recorded.
On the SDK side
  • Every dynamic variable is composed of a pair of key (max. 50 characters) and value (max. 255 characters string or number of type Long between 0 and 2^32 -1). In case these maximums length are reached, the SDK will automatically trim the exceeding characters.
  • If key or value are empty, the SDK will instead send the literal string "cs-empty".

Defining dynamic variables

To define and send a dynamic variable, you just need to use the following API once a first screenview has been triggered. For each dynamic variable, we send:

  • key (string, mandatory)
  • value (string or integer, mandatory)

Note that if you send an integer as a value, it has indeed to be an integer. A null or a float will not be accepted as a valid parameter, and will result in an error.

Also, in order for you to be able to handle such errors happening when we try to send the dynamic variable (see the constraints on keys and values in the Limits section above), you can also add, as a last parameter, a function that we will call so you can handle it gracefully. Note that if you do not add that callback, we will simply log the error's message on the console whenever it happens.

import Contentsquare from '@contentsquare/react-native-bridge';

// alphanumeric value: Contentsquare.sendDynamicVar(string, string, ({ name, message, stack }: { name: string, message: string, stack: string }) => {} ?)
Contentsquare.sendDynamicVar("my key", "my value 1");
Contentsquare.sendDynamicVar("my key", "my value 2", ({ message }) => {
          Toast.show(message, 0.3);
        });

// numeric value: Contentsquare.sendDynamicVar(string, number, ({ name, message, stack }: { name: string, message: string, stack: string }) => {} ?)
Contentsquare.sendDynamicVar("my key", 10);
Contentsquare.sendDynamicVar("my key", 5000, (errorObject) => {
          Console.log(errorObject.toString());
        });

Type of the value — The value can be either a number or a string. For each case, available features won't be the same in the Contentsquare app:

  • For number, you will be able to do some algebra. Example: sessions with dynamic variable key = "numberOfFriends" and value >= 10
  • For string, auto-completion and Regular Expression will be available. Example: sessions with dynamic variable key = "accountType" and value is "Premium"

Track WebViews

How it works

In order to be able to track what is happening in your WebViews, we need to be able to build a bridge between the content of the WebView and our native SDK. This implies two things:

1/ Implementing the Contentsquare WebView JavaScript Tracking Tag on all the web pages that are displayed in your app's WebViews and that you want to track.

-> See WebView JavaScript Tracking Tag Documentation

2/ Injecting a JavaScript bridge in your WebViews, which will allow the Tracking Tag you added to the web page in the previous step to communicate with our native SDK.

In order to inject this JavaScript, you will have to call two functions from our bridge:

function injectWebView(webViewRef: RefObject<object>): void;
function removeWebViewInjection(webViewRef: RefObject<object>): void;

The first one will inject your WebView with our JavaScript bridge, and the second remove the injection from it. The RefObject parameter is the React reference to your WebView object, which we will explain how to implement thereafter.

Implementing the JavaScript bridge

Our implementation will work if and only if the WebView React Native component you are using in your app is relying on an underlying instance of android.webkit.WebView on Android and WebKit's WKWebView on iOS. This is the case of the Facebook recommended component, Facebook recommended component, react-native-webview.

[Android only] Our implementation reloads the current page while injecting the Contentsquare JavaScript interface to accommodate with the behavior of the underlying Android Webview (see. WebView addJavascriptInterface).

Here is a simple screen with a react-native-webview WebView component. Let's detail how we will inject it with the Contentsquare JavaScript WebView interface.

import { WebView } from 'react-native-webview';
const WebviewWithTagScreen = () => {
    return (
        <>
            <WebView
                source={{ uri: "https://www.mywebpage.com" }}
            />
        </>
    );
};
export default WebviewWithTagScreen;

1. Expose the reference to the WebView

In order to be able to call our bridge injection functions, you need to expose the React ref of the WebView component - which you will send back to us. We do that using the useRef hook (1), and passing the value it returns as the ref of the WebView component (2).

import React, { RefObject, useRef } from 'react';
import { WebView } from 'react-native-webview';
const WebviewWithTagScreen = () => {    
   const myWebViewRef = useRef<WebView>(null); // (1)
   return (
        <>
            <WebView
                source={{ uri: "https://www.mywebpage.com" }}
                ref={ myWebViewRef } // (2)
            />
        </>
    );
};
export default WebviewWithTagScreen;

2. Call the Contentsquare bridge's injection/removal functions

In order for the injection and removal to be successful, you should call the bridge when your WebView is fully loaded, and before it is destroyed. In order to do so, you should inject it in componentWillMount() and remove the injection in componentWillUnmount(), or use its hook counterpart, useEffect() (1) and its return function (2). Make sure to only inject it once, and pay attention to side effects of useEffect when states change within your component.

import Contentsquare from '@contentsquare/react-native-bridge';
import React, { RefObject, useEffect, useRef } from 'react';
import { WebView } from 'react-native-webview';
const WebviewWithTagScreen = () => {    
   const myWebViewRef = useRef<WebView>(null);

   useEffect(() => {
        // When useEffect is called, we inject our WebView.
        // We do not have state changes in this component, so we do not protect the call.
        Contentsquare.injectWebView(myWebViewRef) // (1)
        return () => {
            // We are removing the injection in the return function, which is run when this component unmounts.
            Contentsquare.removeWebViewInjection(myWebViewRef); // (2)
        }
    }, []);

    return (
        <>
            <WebView
                source={{ uri: "https://www.mywebpage.com" }}
                ref={ myWebViewRef }
            />
        </>
    );
};
export default WebviewWithTagScreen;

Privacy

The Contentsquare React Native Bridge & SDKs are compliant with the Play Store & App Store Privacy guidelines as well as with the EU General Data Protection Regulation (GDPR).

Please consult our Privacy Center and Privacy Policy.

Even though Contentsquare only collects usage data on your app, we will consider every new user to be opted-out. To start tracking, the Opt-in API must be called.

If for some reason you think that securing user consent is not required for your app, discuss it during the Implementation process with your main contact.

Opt-in

Use the Opt-in API to get user consent. Calling this API will generate a user ID and initiate tracking.

import Contentsquare from '@contentsquare/react-native-bridge';

Contentsquare.optIn();

Opt-Out

Permanently breaking the link and stopping all data collection.

When this API is called, tracking stops immediately, all settings are reset (session number, page number, user ID...) and all files related to Contentsquare tracking are deleted. Contentsquare will never track and collect any data from the user's phone unless the Opt-in API is called again.

import Contentsquare from '@contentsquare/react-native-bridge';

Contentsquare.optOut();

Forget me

Permanently breaking the link between the collected data and actual user.

This resets all settings (session number, page number, user ID...) and deletes all files related to Contentsquare tracking from the user's device. If the user is opted in, next time the user starts the app, the SDK will re-start its collection mechanisms as if this was the first ever run for a new user, under a new user ID. Configurations will be fetched from the server and application tracking will be on.

'Forget me' only works when user is opted in.

import Contentsquare from '@contentsquare/react-native-bridge';

Contentsquare.forgetMe();

Give me my data

We allow the client to provide to their users their Contentsquare user ID.

This ID is a non binding identifier which can be used to make a data request to Contentsquare. You are able to get an ID only if the user is not Opted-out. To do so, pass a callback as a parameter to the function.

import Contentsquare from '@contentsquare/react-native-bridge';

const [userId, setUserId] = useState('not retrieved yet');

//Contentsquare.getUserId(string => {})
Contentsquare.getUserId(newUserId => {
        console.log(`Your Contentsquare UserID is ${newUserId}`);
        setUserId(newUserId);
    }
);

Stop / Resume Tracking

Although we do not gather any humanly readable text from the user's screens, we understand that there may be some areas that you want to completely exclude from tracking. For this reason, we also support stopping and resuming the complete tracking mechanism.

import Contentsquare from '@contentsquare/react-native-bridge';

// Stop tracking
Contentsquare.stopTracking();

// Resume tracking
Contentsquare.resumeTracking();

As this mechanism stops the tracking, please make sure that you call resume once your user exits the sensitive screen. Best practice would be to link these method calls to lifecycle events.

Use Google Tag Manager

Pre-requisite

If you are following this Google Tag Manager integration process, you should already have followed the React Native Firebase setup. We will assume that you are using the officially supported Firebase bridge the officially supported Firebase bridge. We will also assume that you have added the native GTM library to your iOS and Android project (following the iOS documentation and the Android documentation).

Before anything, you also need to integrate the Contentsquare Bridge (see section: Add Contentsquare to your app).

Integration

The whole integration will happen in the native part of your app, as well as in the GTM interface. Here is how it will work (note that you need to do these steps twice, once for iOS and once for Android):

  • You will first setup custom tag, trigger and variables in your GTM interface.
  • Then, you will have to add a custom Tag class in your native project.
  • In your JavaScript/TypeScript code, or in your native code, you will use the Firebase Analytics library to send events, as explained thereafter.
  • As you have created a trigger for that specific type of event, it will trigger the code in your native custom Tag class, where you will be calling the native SDK function corresponding to that event, thus allowing Contentsquare to record those events.

Screenview events

Screenview events will be triggered in the Firebase React Native bridge by calling setCurrentScreen.

As the integration is exactly the same as the native ones, you can refer directly to the SDKs' explanation of the iOS integration and Android integration. You will have to do both in order to have a similar behavior across both platforms.

Transaction events

Transaction events will be triggered in the Firebase React Native bridge by calling logEcommercePurchase.

As the integration is exactly the same as the native ones, you can refer directly to the SDKs' explanation of the iOS integration and the Android integration. You will have to do both in order to have a similar behavior across both platforms.

Dynamic variable events

Dynamic variables are generally custom, and as such can be used with any type of event that can be boiled down to a key/value pair with value types that are valid for the Contentsquare SDK (a string or an unsigned integer). The most common event in that case will thus be a custom event, sent by calling logEvent.

As the integration is exactly the same as the native ones, you can refer directly to the SDKs' explanation of the iOs integration/Android integration. You will have to do both in order to have a similar behavior across both platforms.

How the SDK works

Initialization

The way our SDK works is by auto-starting with the application launch and attaching to the current process in order to intercept the events and gestures we are interested in.

Configuration

Once started, our SDK fetches it config from our servers, and then depending on the segmentation size (defined by our team when you sign a contract) it will start collecting data from system and user events it detects from the runtime.

Tracking

The SDK monitors the application lifecycle events and the view hierarchy, and generates analytics data from the behavior of the app, the content of the screen and the interaction of the user. These events are then locally stored, and eventually sent to our servers in batches. We then aggregate that data to create usable visual information into our Web Application, which you use to gather insights.

Sending data

[tab] Android

Please checkout the Native Android SDK documentation for Sending data

[tab] iOS

Please checkout the Native iOS SDK documentation for Sending data

Session definition

A session represents a single period of user interaction in the app. In Contentsquare, a session ends when the user has spent a certain amount of time outside the app. The SDK checks this when an app start or app show event is detected. This time spent outside the app, ending a session is set to 30 minutes by default. But it can be changed if it is requested.

If the app is put in the background or killed (intentionally by the user or by the OS) but the user comes back within 30 minutes, it will not end the session. These events are considered to be part of a session.

Collected data points

  • The events are in JSON format, which lists the properties and their description in comment.
  • Events are sent to the server in batches.
  • A batch is a subset of events originating from one session. A session can send events in more than one batch.
  • The batch size is defined in a run configuration file specific to each app (50 events by default).

Requests meta data

Each batch has a common header, a set of device specific, and repeatable information and an array of events, which is immutable. The header is composed at the moment of sending, so it has to be constant info ONLY. The array in the payload is data stored at the moment of recording.

The structure of the batches of events will have the following format:

{
    pid:8, // int - ProjectId - represented in the mobile config format
    uid:"ac1529a7-59f6-49d9-b254-6f0a22f57284", // String - uuid Unique user ID
    dt:4, // int - device type (loosely enforced enum - [SDK-phone : 4, SDK-tablet :5])
    dma:"Samsung", // String - device manufacturer. This property is optional and if by any chance the device model cannot be determined it will be dropped from the Json object.
    dmo:"SG", // String - device model. This property is optional and if by any chance the device model cannot be determined it will be dropped from the Json object.
    os:"7.0", // String - os version (Android version name 6.0, 7.0, 8.0)
    l:"en_US", // String - Language in iso-639 format https://www.ibabbleon.com/iOS-Language-Codes-ISO-639.html
    tz:"Europe/Paris", // String - timezone https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
    now:1522159618000, // long - timestamp when the batch was sent
    to:{ // object - type origin of the event
        an:"appname" // String - application name
        st:"SDK-android", // String - type of SDK
        sf:"release", // string - SDK flavor/variant [release/debug/god]
    },
    r:{ // Device - resolution.
        w:1080, // int - width
        h:1920 // int - height
        d: 1.5 // The device density as float. Its values can vary between (0.75 and 10)
    },
    pl:[] // JSon array payload - list of event objects, see below
}

Events

Events meta data

All events have a common first part (don't confuse it with the header explained above). This common section is data which is common for all events by type but is gathered at the moment the event occurred. This common section is a part of the actual event payload.

{
    upt:1522, // long - system update in milliseconds
    euid:"euid", // String - event UUID
    url:"app-and://identifier/mainPath/secondaryPath?title=screeName", // String - screenName is passed in the title query Parameter
    scn:4, // int - the number of screens already shown in the session
    c:3, // int - connectivity type [-1 - offline, 0 - error, 1 - wifi, 2 - 2g, 3 - 3g, 4 - 4g]
    ci:"verizon", // String - carrier_id when user is on mobile network
    o:1, // int - orientation [0 = portrait, 1 = landscape]
    vo:{ // object - version origin of the event
        sv:"2.1", // string version of the SDK
        sb:4, // int - SDK build number
        av:"appVersion", // String - application version
        af:"appFlavor" // String - application string - [release/debug/god]
        ab:1 // int - application build number
    },
    sn:1, // int - session id (positive int)
    t:12894726459435 // long - timestamp of the event (in milliseconds)
}

All event specific properties are appended to this JSON object.

App Start

This event describes the absolute start of the app.

The trigger for this event is the absolute start of the app.

This is the first event sent when the SDK is invoked.

ea:0 // int - event action - defined above

App Show

This event is sent when the user brings the app in the foreground (switching from another app, exiting lock screen, etc.). This event means the app is focused.

ea:1 // int - event action - defined above

App Hide

This event is sent when the user exit (minimizes) the app, or switches to something else . This event means the app is not focused and the session might end, but we have not completely ended the session yet, as the user might return.

ea:2 // int - event action - defined above

Screenview

Everything starts with a View event. This is an event which describes the equivalent of a "page view" in the web. This event is sent when the Track Screen API is called.

ea:4 // int - event action - defined above
st:"title", // String - screen title
sl:34543 // int - (load time) screen load time (diff between last action and this event)

Tap

Single Finger gesture event, when the user is interacting with a loaded screen. This is an event which describes the equivalent of a "click" in the web. This event is defined by the following sequence of touch events:

  • Touch Down -> N x Touch Move -> Touch Up
ea:6 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id
ur: true, // boolean - was this a "responsive" touch event (the target view had a handler)

Long press

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Duration: > 500ms
  • Distance: < 24 dp
ea:8 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id

Drag (Slow Swipe)

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Distance: > 48 dp
  • Finger Velocity < 100 dp/s
ea:9 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view path
tvid:"btn_ok", // String - target view id
fd: 3, // int - finger direction - [1,2,3,4,5] -> [up, down, left, right, complex_pattern]
tvd:100, // int - target view distance dragged
tvv:100 // int - target view velocity while dragging dp/s

Flick (Fast Swipe)

Single Finger gesture event, when the user is interacting with a loaded screen.

This event is defined by the following sequence of touch events:

  • Touch Down → N x Touch Move → Touch Up
  • Distance: > 48 dp
  • Finger Velocity > 100 dp/s
ea:10 // int - event action - defined above
tvp:"[root]>view#id>view2>", // String - target view graph path
tvid:"btn_ok", // String - target view id
fd: 3, // int - finger direction - [1,2,3,4,5] -> [up, down, left, right, complex_pattern]
tvd:100, // int - target view distance scrolled
tvv:100 // int - target view velocity while scrolling dp/s

Transaction

To track transactions, we provide a public API which can send a transaction object (see section Track Transactions). This object must contain the following parameters:

ea:16, // int - event action - defined above
tr:{ // a json object with different properties defining the transaction made
        vl: 20.0, // mandatory - float - the value of the transaction
        cu: 978, // mandatory - int - the ISO 4217 code of the currency of the transaction
        id: "32akjkljklJ575775" // optional - string - an id for the transaction
        }

Dynamic variables

To track dynamic variables we provide a public API which can send a custom event object (see section Dynamic variables).

// Dynamic variable event with a string value
ea:18, // int - event action - defined above
k:"key", // String - Custom key assigned by client.
v:"value" // String - Custom value assign by client.
// Dynamic variable event with a number value
ea:19, // int - event action - defined above
k:"key", // String - Custom key assigned by client.
v: 2344 // Integer - Custom value assign by client.

Security

Transmission and hosting

Our server side uses HTTPS to makes sure that data is encrypted in transport.

Our hosting solution is a PCI DSS Level 1 Service Provider.

What is not recorded

  • Passwords from password fields
  • Geo location information
  • Information from contacts, emails, or any other user identifiable information.
  • text from labels, buttons, and any other widget which contains text
  • accessibility information from any widget which the user interacts with
  • labels printed on the screen of any kind.

Compatibility

Each version of the Contentsquare bridge will be linked to specific, fixed versions of each native SDK. In order to make that clear, here is a compatibility table to consider when choosing your version of the bridge (refer to the React Native Bridge Changelog to know what the changes are for each version.

Bridge VersioniOS SDK VersionAndroid SDK VersionMin React Native VersionMax React Native Version
2.6.04.13.04.9.00.59.00.68.x
2.5.34.10.14.7.00.59.00.67.x
2.5.24.10.14.7.00.60.00.66.x
2.5.14.10.14.7.00.60.00.66.x
2.5.04.10.04.6.00.60.00.66.x
2.4.04.9.04.4.00.60.00.64.x
2.3.04.6.04.3.00.60.00.64.x
2.2.14.4.04.2.00.60.00.64.x
2.1.04.1.04.1.00.60.00.63.x
2.0.04.0.04.0.00.60.00.63.x
1.1.13.2.13.2.00.60.00.63.x
1.1.03.2.03.2.00.60.00.63.x
1.0.03.1.13.1.00.60.00.62.x

Impact on performances

We always strive to be non-intrusive, and transparent to the developers of the client app.

We apply this rule on the performance as well.

[tab] Android
[tab] iOS

Changelog