React Native (Bridge)

Follow

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.3

# Linking the library to your app

# react-native < 0.60. For both Android and iOS
react-native link countly-sdk-react-native-bridge
# 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");

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 function:

Countly.isInitialized();

Checking if onStart has been called

For some applications there might a use case where the developer would like to check if the Countly sdkonStart function has been called. For that they can use the following call:

Countly.hasBeenCalledOnStart();

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 Setup and Usage of Push Notifications

To have notifications in Android we need to bridge to the Firebase Cloud Messaging (FCM) integration provided in our Android SDK. We provide a sample app that combines the following instructions given here and sometimes refer to files in there.

  • Create a react native app as described above and link it to our countly-sdk-react-native-bridge package.

  • Now we need to complete FCM integration. Copy your Firebase config file google-services.json into android/app.

  • Prepare your manifest file (android/app/src/main/AndroidManifest.xml) for messaging service by adding the following. Here DemoFirebaseMessagingService is the name of the class we will add later and can be changed.

<application>
        <service android:name=".DemoFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>
</application>
  • Prepare your gradle files to download our Android SDK package and other required Google packages by adding the following:
// File: android/build.gradle

buildscript {
    dependencies {
        classpath 'com.google.gms:google-services:3.2.0'
    }
}
// File: android/app/build.gradle

dependencies {
    implementation 'com.google.firebase:firebase-messaging:17.3.0'
    implementation 'ly.count.android:sdk-messaging-fcm:19.02.1'
}

// Then at the very bottom of this file
apply plugin: 'com.google.gms.google-services'
  • Copy DemoFirebaseMessagingService.java, CountlyReactNativePushPackage.java, and CountlyReactNativePush.java found here under android/app/src/main/java/<YOUR_PACKAGE_PATH>. This is the folder where react-native init created MainActivity.java automatically. Change the package name at the top of these files to match your package name. In your MainApplication.java you need to link to push specific native module CountlyReactNativePush:
@Override
protected List getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List packages = new PackageList(this).getPackages();
    // ...
    // you need this line also to link to CountlyReactNativePush     
    packages.add(new CountlyReactNativePushPackage());
    return packages;
}

If you need to customize interaction with your notifications DemoFirebaseMessagingService.java is the file you need to modify. This file includes a call to Android SDK's displayMessage method and you need to provide a notification logo resource (R.drawable.ic_message below) for that call:

Boolean result = CountlyPush.displayMessage(getApplicationContext(), message, R.drawable.ic_message, intent);

You can find the ic_message image file referred in our example code here and copy it into android/app/src/main/res/drawable to run our sample app (create drawable folder if necessary).

In your App.js, include the following code to setup notifications:

import { DeviceEventEmitter } from 'react-native';
import {NativeModules} from 'react-native';

const CountlyPush = NativeModules.CountlyReactNativePush;

if (Platform.OS.match("android")) {
  var options = { channelName: "Demo App Notifications", channelDescription: ""}
  CountlyPush.setupPush(Countly.messagingMode.DEVELOPMENT, options);
  DeviceEventEmitter.addListener('push_notification', payload => {
    console.log("Notification received", payload);
  });
}

CountlyPush.setupPush method above will do the necessary tasks to get your Firebase token and send it to Countly server so notifications from your Countly server will be delivered to that user. As described in our Push Notifications Guide, you can send notifications to test users or to your production users. Simple change the messaging mode to Countly.messagingMode.PRODUCTION to mark a user as an production user. If you don't need to receive notification data in your JS code for customization, you can just remove the parts related to DeviceEventEmitter from the above code. Otherwise fill in the callback of the listener according to your needs.

IOS Setup and Usage of Push Notifications

For setting up push notifications for iOS, you will need to follow these instructions: https://resources.count.ly/docs/countly-sdk-for-ios-and-os-x#section-rich-push-notifications-ios10-only-

Rich Push Notifications (iOS10+ only)

Rich push notifications lets you send image, video or audio attachments, as well as customized action buttons on iOS10+. You need to set up Notification Service Extension to use it.

While main project file is selected, please click Editor > Add Target... menu in Xcode, and add a Notification Service Extension target.

Using Product Name field name the Notification Service Extension target as you wish (for example: CountlyNSE). And make sure Team is selected also.

Note: If Xcode asks a question about activating the scheme for newly added Notification Service Extension target, you can choose Cancel.

Under Build Phases > Compile Sources section of newly added extension target, click on + sign.

Go to node_modules/countly-sdk-react-native-bridge/ios/src

Drag and drop CountlyNotificationService.m and CountlyNotificationService.h into your project.

Select CountlyNotificationService.m and then CountlyNotificationService.h in the list.

Then find NotificationService.m file (NotificationService.swift in Swift projects) in extension target. It is a default template file added by Xcode automatically. Inside this file import CountlyNotificationService.h

#import "CountlyNotificationService.h"

And add the following line at the end of didReceiveNotificationRequest:withContentHandler: method as shown below:

- (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.

Provisional Permission for Push Notifications (iOS12+ only)

iOS12 has a new feature called Provisional Permission for push notifications, and it is granted by default for all users. Without showing the notification permission dialog, without requiring users to accept anything, it let's you send notifications to the users.

But these notifications are little bit different, they do not actually notify the users. There are no alerts, no banners, no sounds, or no badges. Nothing informing the users at the moment of notification delivery. Instead, these notifications directly go to Notification Center and they pile up in the list silently. Only when the user goes to Notification Center and checks the list he/she sees them.

In this case, go to https://github.com/Countly/countly-sdk-js/tree/master/src/ios/sdk. Drag and drop "Countly.xcdatamodeld" folder into your plugins folder, and then build it using Xcode.

If you would like to set logging, use code snippet below in your code.

Ratings and Feedbacks is a plugin which helps collect, store, search and track user feedback from web and mobile applications. For more information about this plugin, see this document.

Manual linking:

Manually link the PushNotificationIOS library

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]
Was this article helpful?
0 out of 0 found this helpful

Looking for help?