React Native (Bridge)

Follow

This documentation applies to the version 20.4.

React Native Bridge is a successor to React Native SDK

React Native SDK, which has been developed earlier will soon be end-of-life and won't be maintained anymore. Please use this (bridge) SDK for a more complete and tested version.

This is the Countly SDK for React Native applications. It features bridging, that is, it includes all the functionalities that Android and iOS SDKs provide, rather than having those functionalities as React Native code.

Creating a new application

In order to use React Native SDK, please use the following commands to create a new React Native application.

npm install -g react-native-cli     # Install React Native
react-native init AwesomeProject    # Create a new project

cd AwesomeProject                   # Go to that directory
react-native run-android # OR       # Run the android project
react-native run-ios                # Run the iOS project

# New terminal
adb reverse tcp:8081 tcp:8081       # Link Android port
npm start                           # Run the build server

Installing the Countly SDK

Run the following snippet in the root directory of your React Native project to install the npm dependencies and link native libraries.

# Include the Countly Class in the file that you want to use.
npm install --save https://github.com/Countly/countly-sdk-react-native-bridge.git
# OR
npm install --save countly-sdk-react-native-bridge@19.8.5

# Linking the library to your app

# react-native < 0.60. For both Android and iOS
react-native link countly-sdk-react-native-bridge
cd node_modules/countly-sdk-react-native-bridge/ios/
pod install
cd ../../../

# react-native >= 0.60 for iOS (Android will autolink)
cd ios
pod install
cd ..

Implementation

To setup our SDK, we need to call two methods init and start. You may want to specify other parameters at this step also (i.e. whether logging will be used). These methods should be called only once during app's lifecycle and as early as possible. So your main App component's componentDidMount method may be a good place. 

For serverURL value in the code snippet below, If you are using Countly Enterprise Edition trial servers use https://try.count.ly, https://us-try.count.ly or https://asia-try.count.ly. Basically the domain you are accessing your trial dashboard from.

If you use Community Edition and Enterprise Edition, use your own domain name or IP address like https://example.com or https://IP (if SSL is setup).

import Countly from 'countly-sdk-react-native-bridge';

// initialize // modify serverURL to your own. var serverURL = "https://mycompany.count.ly"; var appKey = "f0b2ac6919f718a13821575db28c0e2971e05ec5"; var deviceId = null; // or use some string that identifies current app user Countly.init(serverURL, appKey, deviceId); // configure other Countly parameters if needed Countly.enableParameterTamperingProtection("salt");
Countly.enableLogging(); ...

// start session tracking
Countly.start();

After init and start called once, you may use the commands in the rest of this document to send additional data, metrics to your server. 

User Location

Countly tries to determine following information but if you want you can specify them yourself.

var countryCode = "us"; 
var city = "Houston";
var latitude = "29.634933";
var longitude = "-95.220255";
var ipAddress = "103.238.105.167";

Countly.setLocation(countryCode, city, latitude + "," + longitude, ipAddress);

Following will erase cached location data from device and stop further location tracking.

If, after disabling location setLocation is called with any non null value, tracking will resume.

//disable location tracking
Countly.disableLocation();

Custom events

Below is a quick summary on how to use custom events recording methods and what information they provide. For more information about how custom events and segmentations work, read this guide first.

Note that all data passed to Countly instance via SDK or API should be in UTF-8.

// Example for sending basic custom event
var event = {"eventName":"basic_event","eventCount":1};
Countly.sendEvent(event);

// Example for event with sum
var event = {"eventName":"Event With Sum","eventCount":1,"eventSum":"0.99"};
Countly.sendEvent(event);

// Example for event with segment
var event = {"eventName":"Event With Segment","eventCount":1};
event.segments = {"Country" : "Germany", "Age" : "28"};
Countly.sendEvent(event);

// Example for event with segment and sum
var event = {"eventName":"Event With Sum And 			Segment","eventCount":1,"eventSum":"0.99"};
event.segments = {"Country" : "Germany", "Age" : "28"};
Countly.sendEvent(event);

// Timed events
// Basic timed event
Countly.startEvent("timedEvent");
Countly.endEvent("timedEvent");

// Timed event with a sum
Countly.startEvent("timedEvent");
var event = {
  "eventName": "timedEvent",
  "eventSum": "0.99"
};
Countly.endEvent(event);

// Timed event with segment
Countly.startEvent("timedEvent");
var event = {
  "eventName": "timedEvent"
};
event.segments = {
  "Country": "Germany",
  "Age": "28"
};
Countly.endEvent(event);

// Timed event with segment, sum and count
Countly.startEvent("timedEvent");
var event = {
  "eventName": "timedEvent",
  "eventCount": 1,
  "eventSum": "0.99"
};
event.segments = {
  "Country": "Germany",
  "Age": "28"
};
Countly.endEvent(event);

 

User Profiles

If you have any details about the user/visitor, you can provide Countly with that information. This will allow you track each and specific user on "User Profiles" tab, which is available with Countly Enterprise Edition.

In order to set a user profile, use code snippet below. After you send a user data, it can be viewed under Dashboard > User Profiles.

// Example for setting user data
var options = {};
options.name = "Nicola Tesla";
options.username = "nicola";
options.email = "info@nicola.tesla";
options.organization = "Trust Electric Ltd";
options.phone = "+90 822 140 2546";
options.picture = "http://www.trust.electric/images/people/nicola.png";
options.picturePath = "";
options.gender = "M";
options.byear = 1919;
Countly.setUserData(options);

Countly also supports custom user properties, where you can attach custom data for each user. In order to set or modify a user's data (e.g increment, multiply, etc), the following code sample can be used.

// examples for custom user properties
Countly.userData.setProperty("keyName", "keyValue"); //set custom property
Countly.userData.setOnce("keyName", 200); //set custom property only if property does not exist
Countly.userData.increment("keyName"); //increment value in key by one
Countly.userData.incrementBy("keyName", 10); //increment value in key by provided value
Countly.userData.multiply("keyName", 20); //multiply value in key by provided value
Countly.userData.saveMax("keyName", 100); //save max value between current and provided
Countly.userData.saveMin("keyName", 50); //save min value between current and provided
Countly.userData.setOnce("setOnce", 200);//insert value to array of unique values
Countly.userData.pushUniqueValue("type", "morning");//insert value to array of unique values
Countly.userData.pushValue("type", "morning");//insert value to array which can have duplicates
Countly.userData.pullValue("type", "morning");//remove value from array

Crash reporting

With this feature, Countly SDK will generate a crash report if your application crashes due to an exception, and send it to Countly server for further inspection.

If a crash report can not be delivered to server (e.g. no internet connection, unavailable server), then SDK stores the crash report locally in order to try again later.

You need to call the following method before calling init to activate automatic crash reporting.

// Using countly crash reports
Countly.enableCrashReporting();
Countly.init(...);

You can also add breadcrumb crash logs to your crash report using addCrashLog and catch and send exceptions manually yourself using logException. Please see example code below:

Countly.addCrashLog("User Performed Step A");
setTimeout(() => { Countly.addCrashLog("User Performed Step B");}, 1000);
setTimeout(() => { Countly.addCrashLog("User Performed Step C");}, 1500);
setTimeout(() => {
   try {
     var a = {};
     var x = a.b.c; // this will throw an error.
   } catch (exc) {   
     var stack = exc.stack.toString();
     const customSegments = {"external_lib_version": "4.2.7", "theme": "dark"};
     const nonfatal = true;
     Countly.logException(stack, nonfatal, customSegments);
   }
},2000);

logException takes a string for stack trace, a boolean flag indicating if crash is considered to be fatal or not, and a segments dictionary to add additional data to your crash report.

View tracking

You can manually add your own views in your application, and each view will be visible under Analytics > Views. Below you can see two examples of sending a view using Countly.recordview function.

// record a view on your application
Countly.recordView("My Home Page");
Countly.recordView("Profile Page");

// record view with segments
Countly.recordView("View with Segment", {"version": "1.0", "_facebook_version": "0.0.1"})

View tracking is a means to report every screen view to Countly dashboard. In order to enable automatic view tracking, call:

Countly.setViewTracking(true);

The tracked views will use the full activity names which includes their package name. It would look similar to "com.my.company.activityname".

It is possible to use short view names which will use the simple activity name. That would look like "activityname". To use this functionality, call this before calling init:

Countly.setAutoTrackingUseShortName(true);

Also you can track custom views with following code snippet:

Countly.recordView("View name")

Remote Config

Remote config allows you to modiffy how your app functions or looks by requesting key-value pairs from your Countly server. The returned values can be modiffied based on the user profile. For more details please see Remote Config documentation.

// remoteConfigUpdate will update all remote config values
Countly.remoteConfigUpdate(function(data){ 
	console.log(data);
});

// updateRemoteConfigForKeysOnly will update only those values which keyname are pass in array
Countly.updateRemoteConfigForKeysOnly(["test1"],function(data){
	console.log(data);
});

// updateRemoteConfigExceptKeys will update only values except which keyname are pass in array
Countly.updateRemoteConfigExceptKeys(["test1"],function(data){
	console.log(data);
});
      
// getRemoteConfigValueForKey will fetch remote config values for keyname sent
Countly.getRemoteConfigValueForKey("test1",function(data){
	console.log(data);
});

Clearing Stored Remote Config values

At some point you might want to erase all values downloaded from the server. To achieve that you need to call one function.

Countly.remoteConfigClearValues();

User Consent management

To be compliant with GDPR and other data privacy regulations Countly provides ways to toggle different Countly tracking features on/off depending on a user's given consent. To learn more about how Countly manages this issue and what capabilities we provide to our customers, please visit our guide on Compliance Hub plugin. You may also find more information about how Countly helps organizations with GDPR regulations in this Countly blog post.

Since React Native Bridge SDK employs our IOS and Android SDKs you may also want to check their relevant documentation on this topic (here and here respectively).

Here, we will go over the methods that are available in this SDK.

Method Parameters / Examples Description
setRequiresConsent boolean By default the requirement for checking consent is disabled. To enable it, you have to call setRequiresConsent with true, before initializing Countly. You can pass also a consent flag as true/false, when you call Countly.init.
giveConsent string array of strings To add consent for a single feature (string parameter) or a subset of features (array of strings parameter).
removeConsent string array of strings To remove consent for a single feature (string parameter) or a subset of features (array of strings parameter).
giveAllConsent none To give consent for all available features.
removeAllConsent none To remove consent for all available features.
// Usage examples

Countly.setRequiresConsent(true);

// for a single feature
Countly.giveConsent("events");
Countly.removeConsent("events");

// for a subset of features
Countly.giveConsent(["events", "views", "star-rating", "crashes"]);
Countly.removeConsent(["events", "views", "star-rating", "crashes"]);

// for all available features
Countly.giveAllConsent();
Countly.removeAllConsent();

String values corresponding to features to be used in giveConsent or removeConsent methods can be found here. Please also check our platform SDK documents if the feature is applicable or not for that platform.

Changing a device ID

In case your application authenticates users, you can also change device ID to your user ID later. This helps you identify a specific user with a specific ID on a device she logs in, and the same scenario can also be used in cases this user logs in using a different way (e.g tablet, another mobile phone or web). In this case any data stored in Countly server database and associated with temporary device ID will be transferred into user profile with device id you specified in the following method call:

Countly.changeDeviceId("theNewID", true);

// if you don't want to update on the server but just locally update the id

Countly.changeDeviceId("theNewID", false);

Enabling/disabling logging

If logging is enabled then our sdk will print out debug messages about it's internal state and encountered problems. By default logging is disabled. It is advised enabling it during development. Enabling it before init is recommended to see logs about the initialization process.

Countly.enableLogging();
Countly.init(...); ...
// to disable it again later Countly.disableLogging();

Forcing HTTP POST

If the data sent to the server is short enough, the sdk will use HTTP GET requests. In case you want an override so that HTTP POST is used in all cases, call the "setHttpPostForced" function after you called "init". You can use the same function to later in the apps life cycle disable the override. This function has to be called every time the app starts.

  
// enabling the override
Countly.setHttpPostForced(true);
  
// disabling the override
Countly.setHttpPostForced(false);

Checking if init has been called

In case you want to check if init has been called, you can just use the following call that returns a promise:

Countly.isInitialized().then(result => console.log(result)); // true or false

Checking if onStart has been called

For some Android applications there might a use case where the developer would like to check if the Countly Android SDK onStart function has been called. For such cases the following method that returns a promise can be called:

Countly.hasBeenCalledOnStart().then(result => console.log(result)); // true or false 

Rich Push Notifications

Please check first our Push Notifications Guide to see how you can use this feature. Since Android and IOS handles notifications differently (from how you can send them externally to how they are handled in native code) we need to provide different instructions for these two platforms.

Android Push Notification Setup Steps

Step 1:       Copy google-services.json file to ./android/app directory
Step 2:      Add firebase dependencies to ./android/app/build.gradle

Step 2.1:    inside dependencies
                   implementation 'com.google.firebase:firebase-messaging:20.1.7'
Step 2.2:   at the bottom of this file add this line
                  apply plugin: 'com.google.gms.google-services'

Step 3:     Add google service dependencies to ./android/build.gradle
                 inside dependencies
                 classpath 'com.google.gms:google-services:3.2.0'

JS Push Method Implementation

// Important call this method before init method
Countly.pushTokenType(Countly.messagingMode.DEVELOPMENT);
// Countly.messagingMode.DEVELOPMENT
// Countly.messagingMode.PRODUCTION
// Countly.messagingMode.ADHOC

// Call this method any time.
Countly.askForNotificationPermission();
// This method will ask for permission,
// and send push token to countly server.

React Native JS code to receive notification data. call anywhere or event before init.

Countly.registerForNotification(function(theNotification){
console.log(JSON.stringify(theNotification));
});

iOS Push Notification Documentation

Note: This documentation assumes, that you have created necessary certficate, have proper app bundle id.

STEP 1: Make sure you have proper app bundle id and team selected.

STEP 2: Add Capabilities
              1. Push Notification
             2. Background Mode - Remote Notifications
             Go into your AwesomeProject/ios dir and open AwesomeProject.xcworkspace workspace.              Select the top project “AwesomeProject” ans select the “Signing & Capabilities” tab. Add a 2 new Capabilities using “+” button:
             Background Mode capability and tick Remote Notifications.
             Push Notifications capability

Screenshot_2020-05-05_at_1.43.11_PM.png

Screenshot_2020-05-05_at_1.43.21_PM.png

Screenshot_2020-05-05_at_1.43.36_PM.png

Screenshot_2020-05-05_at_1.43.49_PM.png

STEP 3: Place below code in there respective files.

### AppDelegate.m

Add header file
`#import "CountlyReactNative.h"`
`#import <UserNotifications/UserNotifications.h>`


Before `@end` add these method

  -(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse
  *)response withCompletionHandler:(void (^)(void))completionHandler{
   NSLog(@"didReceiveNotificationResponse");
   NSDictionary *notification = response.notification.request.content.userInfo;
   [CountlyReactNative onNotification: notification];
   completionHandler();
} //Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
    NSLog(@"didReceiveNotificationResponse");
   NSDictionary *userInfo = notification.request.content.userInfo;
   [CountlyReactNative onNotification: userInfo];
   completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}

 

Rich Push Notification

STEP 1: Creating Notification Service Extension
              Editor -> Add Target ->
             Make sure ios is selected
             Make sure Notification Service Extension is selected
             Click Next
             Enter Product Name e.g. CountlyNSE
             Language Objective-C
             Click Finish
             It will ask for a modal / popup Activate “CountlyNSE” scheme?
             Choose Cancel

b0b0f12-f62249f-screen-1.png

04c2353-17d2fec-screen-2.png

 

STEP 2: Adding Compile Source
              Under TARGETS select CountlyNSE
             Select Build Phases
             Expand Compile Sources
             Drag and Drop CountlyNotificationService.h and CountlyNotificationService.m file
             Note: Make sure you have checked "Copy if necessary"
             Note: You may also find this file in Xcode under Pods(Project) -> Pods(Folder) -> Countly
             Note: You may also find this file in Finder under AwesomeProject/ios/Pods/Countly
             Note: You may also find this file in Xcode under AwesomeProject(Project) -> Libraries(Folder) -> countly-sdk-react-native-bridge(Project)->src(Folder)
             Note: You may also find this file in Finder under node_modules/countly-sdk-react-native-bridge/ios/Pods/Countly

Screenshot_2020-05-05_at_1.44.05_PM.png

 

STEP 3: Updating NotificationService file
              Under AwesomeProject(Project) -> CountlyNSE(Folder) -> NotificationService.m
             Add import header #import "CountlyNotificationService.h"
             Add the following line at the end of didReceiveNotificationRequest:withContentHandler:

    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler
    {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];    
        //delete existing template code, and add this line
        [CountlyNotificationService didReceiveNotificationRequest:request withContentHandler:contentHandler];
    }
    

    Note: Please make sure you configure App Transport Security setting in extension's Info.plist file also, just like the main application. Otherwise media attachments from non-https sources can not be loaded.
    
    Note: Please make sure you check Deployment Target version of extension target is 10, not 10.3 (or whatever minor version Xcode set automatically). Otherwise users running iOS versions lower than Deployment Target value can not get rich push notifications.

    Note: To send push messages to applications that are Debug build use Countly.messagingMode.DEVELOPMENT, for App Store built ones use Countly.messagingMode.PRODUCTION, and for TestFlight/Ad Hoc builds use Countly.messagingMode.ADHOC.    

Getting user feedback

There are two ways of getting feedback from your users: Star rating dialog, feedback widget.

Star rating dialog allows users to give feedback as a rating from 1 to 5. The feedback widget allows to get the same 1 to 5 rating and also a text comment.

Feedback widget

Feedback widget shows a server configured widget to your user devices.

It's possible to configure any of the shown text fields and replace with a custom string of your choice.

In addition to a 1 to 5 rating, it is possible for users to leave a text comment and also leave a email in case the user would want some contact from the app developer.

Trying to show the rating widget is a single call, but underneath is a two step process. Before it is shown, the SDK tries to contact the server to get more information about the dialog. Therefore a network connection to it is needed.

You can try to show the widget after you have initialized the SDK. To do that, you first have to get the widget ID from your server:

Using that you can call the function to show the widget popup:

Countly.showFeedbackPopup("WidgetId", "Button Text");

Star rating dialog

Star rating integration provides a dialog for getting user's feedback about the application. It contains a title, simple message explaining what it is for, a 1-to-5 star meter for getting users rating and a dismiss button in case the user does not want to give a rating.

This star-rating has nothing to do with Google Play Store ratings and reviews. It is just for getting a brief feedback from users, to be displayed on the Countly dashboard. If the user dismisses star rating dialog without giving a rating, the event will not be recorded.

Countly.showStarRating();

Native C++ Crash Reporting

If you have some C++ libraries in your Android app, React Native Bridge SDK allows you to record possible crashes in your Countly server by integrating sdk-native developed within our Android SDK. You can get more information on how this works from here.

Since this feature is optional, to make it available you need to uncomment some parts in our SDK files. First of all, go to android/build.gradle and add the package dependency (all file paths in this section are given relative to countly-sdk-react-native-bridge which was npm installed above):

dependencies {
    implementation 'ly.count.android:sdk-native:19.02.3'    
}

Then in android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java file uncomment the following:

import ly.count.android.sdknative.CountlyNative;
    
@ReactMethod
  public void initNative(){
  CountlyNative.initNative(getReactApplicationContext());
}
	
@ReactMethod
  public void testCrash(){
  CountlyNative.crash();
}
    

Now to connect from JS to these new methods modify Countly.js:

Countly.initNative = function(){
    CountlyReactNative.initNative();
}

Countly.testCrash = function(){
    CountlyReactNative.testCrash();
}

If you are using our sample app in example/App.js you can also uncomment the following parts in it for easy testing:

initNative(){
  Countly.initNative();
};

testCrash(){
  Countly.testCrash();
}

// ...

            < Button onPress = { this.initNative } title = "Init Native" color = "#00b5ad"> 
            < Button onPress = { this.testCrash } title = "Test Native Crash" color = "crimson"> 

It is suggested to call Countly.initNative(); as soon as your app is initialized to be able to catch setup time crashes. Sending crash dump files to the server will be taken care by Android SDK during next app initialization. We also provide a gradle plugin to be able to upload symbol files to your server automatically (for symbolication of crash dumps, these are needed). You can integrate it to your React Native project as explained in the relevant Android documentation page.

Here is how the debug logs will look like if you are going to use this feature:

$ adb logcat -s Countly:V countly_breakpad_cpp:V

# when Countly.initNative() is called 

D/countly_breakpad_cpp(123): breakpad initialize succeeded. dump files will be saved at /Countly/CrashDumps

# when a crash occurs (you may trigger one by Countly.testCrash())

D/countly_breakpad_cpp(123): DumpCallback started
D/countly_breakpad_cpp(123): DumpCallback ==> succeeded path=/Countly/CrashDumps/30f6d9b8-b3b2-1553-2efe0ba2-36588990.dmp

# when app is run again after the crash 

D/Countly (124): Initializing...
D/Countly (124): Checking for native crash dumps
D/Countly (124): Native crash folder exists, checking for dumps
D/Countly (124): Crash dump folder contains [1] files
D/Countly (124): Recording native crash dump: [30f6d9b8-b3b2-1553-2efe0ba2-36588990.dmp]

Pinned Certificate (Call this method before init)

Terminal

openssl s_client -connect try.count.ly:443 -showcerts

Run the above command and copy the content inside being certficate and end certificate.

Example file are here:
https://github.com/Countly/countly-sdk-react-native-bridge/blob/master/example/android.count.ly.cer
https://github.com/Countly/countly-sdk-react-native-bridge/blob/master/example/ios.count.ly.cer

Both files are different, android only needs the cert string, iOS needs the entire .cer file.

Android

cd AwesomeProject
ls
count.ly.cer
mkdir -p ./android/app/src/main/assets/
cp ./count.ly.cer ./android/app/src/main/assets/

iOS

open ./ios/AwesomeProject.xcworkspace
Right click on AwesomeProject and select `New Group` (ScreenShot 1)
Name it `Resources`
Drag and Drop count.ly.cer file under that folder (ScreenShot 2)
ScreenShot_Pinned_Certificate_1.png

Screenshot_Pinned_Certificate_2.png

JS

Countly.pinnedCertificates("count.ly.cer");

Note: "count.ly.cer" is the name of the file. Replace this file with the one you have.

Was this article helpful?
0 out of 0 found this helpful

Looking for help?