This is an unmaintained SDK
You are suggested to use React Native (bridge) SDK instead. This SDK will be declared as end-of-life very soon.
This tutorial shows you how to include Countly SDK in your React Native application. It is based on the following:
- react-native-cli: 2.0.1
- react-native: 0.49.1
There are other ways to create a react Native application. Our SDK works with all methods, but in this document we are going to show react-native cli.
Creating a new application
Before creating a new application, please look at the documentation here. Make sure you click the tab called Building Projects with Native Code
and follow instructions.
Enter following commands to install react-native-cli
and configure your environment.
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 SDK
Run the following snippet in the root of your react native project to install the npm dependencies and link the native libraries.
# Add dependencies
npm install --save react-native-device-info
npm i react-native-background-timer --save
npm i react-native-restart
react-native link
# Include the Countly Class in the file that you want to use.
npm install --save countly-sdk-react-native
You can also review example usage of SDK for Android and for iOS.
SDK Usage
Please see below on how to initialize and start Countly SDK.
// In your javascript code
import Countly from 'countly-sdk-react-native';
Countly.isDebug = true; // Set to true to see the logs
// example for initalization and start session in first go.
// deviceId is optional field. If you are using a service
// different from try.count.ly (e.g your own or another test
// server by Countly), mention it below. Double check http
// or https connectivity.
Countly.begin("https://try.count.ly","app_key","deviceId")
.then((result) => {
// do your stuff on session start
})
.catch((err) => {
// returns cause of failed initialization
});
// From second session and further start session
Countly.start()
.then((result) => {
// do your stuff on session start
})
.catch((err) => {
// returns cause of failing operation
});
// stop session
Countly.stop().then((result) => {
// session stops successfully
});
NOTE: Countly.begin
method will automatically start the session for the first time. Countly.stop
method can be called on any events on which you want to end the current session. If you have called the Countly.stop
method to end the session, then you need to call Countly.start
method to start new session else you need not worry about Countly.start
method as Countly.begin
will automatically start the session.
If you want to initialize and start session separately you can do like shown below.
// In your javascript code
import Countly from 'countly-sdk-react-native';
// example for initializing countly
Countly.isDebug = true; // Set to true to see the logs
// deviceId is an optional field.
Countly.init("https://try.count.ly","app_key","deviceId")
.then((result) => {
// Now start session
Countly.start()
.then((result) => {
// do your stuff
})
.catch((err) => {
// reason for failure
});
})
.catch((err) => {
// reason for failure
});
If you omit deviceID above, automatically generated deviceID will be used. If you provide a deviceID, then it will take that as DeviceId. For example, you can use hashed value of user's email as a deviceID.
Sending events
You can send events with segmentations using following examples.
Example for sending a basic event:
var event = {"key":"basic_event","count":1};
Countly.recordEvent(event);
Example for sending event with sum:
var event = {"key":"event_sum","count":1,"sum":"0.99"};
Countly.recordEvent(event);
Example for sending event with a segmentation value (in this case, Germany and Age):
var event = {"key":"event_segment","count":1};
event.segmentation = {"Country" : "Germany", "Age" : "28"};
Countly.recordEvent(event);
Example for sending event with segmentation value and sum:
var event = {"key":"event_segment_sum","count":1,"sum":"0.99"};
event.segmentation = {"Country" : "Turkey", "Age" : "28"};
Countly.recordEvent(event);
Example for sending a timed event. It tracks how long a specific event takes to complete. If you send a timed event, then under Countly dashboard you will see its duration (in seconds).
Countly.startEvent("timedEvent");
Countly.endEvent("timedEvent");
Duration of the event will be calculated automatically when endEvent
method is called.
Push Notifications
This section requires setting up either APNS (Apple Push Notification Services) or FCM (Firebase Cloud Services). For APNS, you need to get push credentials and upload to Countly. This document explains how to retrieve and upload push credentials for APNS.
First, install react-native-firebase plugin to implement push notifications.
npm install --save react-native-firebase
// Link Firebase
react-native link react-native-firebase
If you are developing in android you would require to setup FCM in android. You can follow the below given steps to guide you through.
- Setup google-services.json
- A google-services.json file contains all of the information required by the Firebase Android SDK to connect to your Firebase project. To automatically generate the json file, follow the instructions on the Firebase console to "Add Firebase to your app".
Once downloaded, place this file in the root of your project at android/app/google-services.json. In order for Android to parse this file, add the google-services gradle plugin as a dependency to your project in the project level build.gradle file (android/build.gradle):
buildscript {
repositories {
google() // < Check this line exists and is above jcenter.
jcenter()
}
dependencies {
...
classpath 'com.android.tools.build:gradle:3.2.0' // Just to make sure.
classpath 'com.google.gms:google-services:4.0.1'
...
}
}
Now setup gradle dependencies in your android/app/build.gradle file :
dependencies {
...
//These should be already present in your gradle file.
implementation project(':react-native-firebase')
//Add these lines
implementation "com.google.android.gms:play-services-base:16.0.1"
implementation "com.google.firebase:firebase-core:16.0.6"
implementation "com.google.firebase:firebase-messaging:17.3.4"
}
//Make sure you put this to the bottom most of your build.gradle
apply plugin: 'com.google.gms.google-services'
Now go to your MainApplication.java and add these imports if not present.
//add these imports if not present.
import io.invertase.firebase.RNFirebasePackage;
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
...
@Override
protected List getPackages() {
return Arrays.asList(
new MainReactPackage(),
//Make sure these files are present
new RNFirebasePackage(),
new RNFirebaseMessagingPackage(),
new RNFirebaseNotificationsPackage()
);
}
Add these lines to your Android Manifest file
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
....
<application>
......
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />
</application>
Add these lines in settings.gradle:
include ':react-native-firebase'
project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')
Now go again to your android/app/build.gradle and add this line:
dependencies {
compile project(':react-native-firebase')
...
}
If your Installing in iOS, follow the given steps to guide you through. but before we proceed please make sure you have generated your certificates properly.
- Setup GoogleService-Info.plist
- A GoogleService-Info.plist file contains all of the information required by the Firebase iOS SDK to connect to your Firebase project. To automatically generate the plist file, follow the instructions on the Firebase console to "Add Firebase to your app".
Once downloaded, add the file to your iOS app using 'File > Add Files to "[YOUR APP NAME]"…' in XCode.
- Initialize Firebase
- To initiaize the native SDK in your app, add the following to your ios/[YOUR APP NAME]/AppDelegate.h file:
//At the begining of your file
#import
...
//At the beginning of the didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method add the following line:
[FIRApp configure];
...
Now, Install Firebase Library using cocoapods. For this, go to your IOS project and run command pod init
and then add Firebase/Core and Firebase/Messaging as shown below:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'ReactPushNotifications' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for ReactPushNotifications - Add these lines
pod 'Firebase/Core'
pod 'Firebase/Messaging'
target 'ReactPushNotificationsTests' do
inherit! :search_paths
# Pods for testing
end
end
Now open your project on Xcode from and goto Capabilities and do the following:
- Turn on Push Notifications
- Turn on Background modes
- Check Remote notifications
Now, go to Build Phases. Click on the “+” under “Link Binary With Libraries” to add a new library. Add UserNotifications.framework. This framework is required since iOS 10 for push notifications handling. Go to Build Settings, find Header Search Path, double click its value and press “+” button. Add following line there.
$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase
Go to AppDelegate.h and add those lines:
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;
@end
Now Add Firebase package in your AppDelegate.m as follows:
#import "AppDelegate.h"
//Add these lines
#import
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
[RNFirebaseNotifications configure];
NSURL *jsCodeLocation;
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"FCMPushTest"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
[[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
[[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}
-(void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
[[RNFirebaseMessaging instance] didReceiveRemoteNotification:response.notification.request.content.userInfo];
completionHandler();
}
@end
For push notification action support in iOS device, install this plugin (https://github.com/nodexpertsdev/react-native-ios-notification-actions) and follow the instructions to setup push notification action. This step should only be performed for iOS project only else it will generate an error.
# For push notifications action support in iOS
npm install --save https://github.com/nodexpertsdev/react-native-ios-notification-actions
react-native link
# Note: string you set in the identifier of
# NotificationActions.category must match to the 'category'
# of the push notification payload
To initialize push notification, use the following:
// To initialize the push notification.
// For Android we have two types of users i.e test and production users
// For test mode use Countly.TEST
// For production mode use Countly.PRODUCTION
// For IOS we have three types of users
// For adhoc mode use Countly.ADHOC
// For test mode use Countly.TEST
// For production mode use Countly.PRODUCTION
// Add this import at the top
import firebase from 'react-native-firebase';
// example within an App compontent
componentDidMount(){
///For android only --start
if (Platform.OS === 'android') {
const channel = new firebase.notifications.Android.Channel('your_channel_id', 'your_channel_name', firebase.notifications.Android.Importance.Max)
.setDescription('Your_channel_description');
firebase.notifications().android.createChannel(channel);
}
///For android only --END
Countly.initMessaging(Countly.DEVELOPMENT,'your_channel_id');
}
// For unregistering listeners
componentWillUnmount() {
Countly.UnmountNotificationListeners();
}
// If you have not installed the dependencies and use above config settings your app will start crashing.
//For handlink the deep linking data you can get your Actions link here as mentioned below.
constructor(props) {
super(props);
Countly.deepLinkHandler = {
handler1: url => console.log(url), //Here you would get your action url's
}
// for getting json from data-only message /data
Countly.jsonHandler = {
handler: json => console.log(json),
}
}
Countly.initMessaging retrieve token from APNS/FCM and then pass it to Countly server. After getting the token, your dashboard is ready to send push notifications to that device.
Add below lines in index.js for enabling background messaging.
import Countly from 'countly-sdk-react-native';
const id = 'your_channel_id';
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => {
return message => Countly.bgMessaging(message, id);
});
User Profiles
Enterprise Edition Feature
This feature is only available with Enterprise Edition subscription.
You can see detailed user information under User Profiles section of Countly dashboard by recording user details. You can record default and custom properties of user details like this:
Countly.setUserData({
"name": "Name Surname",
"username": "xyz",
"email": "xyz@gmail.com",
"organization": "XYZ Technologies",
"phone": "9999999999",
//Web URL to picture
"picture": "https://URL/file/pic250x250.png",
"gender": "M", //M or F
"byear": 1989, //birth year
"custom": {
"key1": "value1",
"key2": "value2"
}
});
In addition, you can use custom user details modifiers like this:
Countly.userData.setProperty("setPropertyKey", "setPropertyKeyValue");
Countly.userData.increment("incrementKey");
Countly.userData.incrementBy("incrementByKey", 10);
Countly.userData.multiply("multiplyKey", 20);
Countly.userData.saveMax("saveMaxKey", 100);
Countly.userData.saveMin("saveMinKey", 50);
Countly.userData.setOnce("setOnceKey", 200);
Manual Tracking of View (Screen)
You can record (track) view as well as the time for which user has visited the particular screen.
// Example for recording view
Countly.recordView(ViewName); // ViewName will be your screen name
You can also track (record) the action performed on the view.
// To record an action:
Countly.recordViewActions(actionType, touchCoordinate);
// where actionType may be 'touch', 'swipe' etc... and
// TouchCoordinate is the x, y axis of touch point.
Crash Reporting
Countly can send automated crash reporting to a Countly server. Below you can see how to enable it.
First, add dependencies to your application:
npm i react-native-exception-handler --save
npm i react-native-restart
react-native link
Then, outside the root component add the following and enable crash reporting feature.
// Outside the root component add the following line.
// Setting first parameter to true will enable crash
// reporting in production mode.
Countly.enableCrashReporting(true);
In order to enable the crash reporting in development mode, use the following line. Here, second parameter is optional which will be false by default. It is recommended not to use crash reporting in development mode - it is used to hide the internal error from user and send the issue to the developer.
Countly.enableCrashReporting(true, true);
If the crash occurred, SDK sends the crash data to Countly and shows an alert box having the crash message and a Restart button. Restart button will restart the application.
If you want to customize the default alert box functionality and message you can do so by changing in config variable as shown below.
// Config variable to customize default alert box.
Countly.defaultAlert = {
// default value will be false.
enable: false,
// Title of the alert box
title: 'Application Error',
// Message in alert box
message: 'Application will be restarted',
// Alert box button title
buttonTitle: 'Restart',
// Default method will restart the application.
// You can change the methods according your requirement.
onClick: () => this.restartApp(),
};
Further, if you think that you want to create your own custom crash log method you can do so by following the below instructions.
// create your custom method
const crashMethod = () => {
// This is optional. If you want to send your custom
// data to the dashboard with crashLog Data, use this:
const crash = { 'customData': test }
// Required. This is required if you do not call this
// method Countly will not send the crash log to the dashboard.
Countly.addCrashLog(crash);
/* Do your stuff */
}
// Then assign this function in the Countly config show below.
// This will disable default crash method and enable your crash method.
Countly.customCrashLog = crashMethod;
Important note
All crash method definition and crash config assignment will be done in root component file of your application (which will be index.js/ index.android.js/ index.ios.js/ App.js) and outside the React class.
Parameter Tampering
This is one of the preventive measures of Countly. If someone in the middle intercepts the request, it would be possible to change the data in the request and make another request with other data to the server, or simply make random requests to the server through retrieved App Key.
To prevent that, SDK provides an option to send a checksum along the request data. For this, you should provide a random string as SALT to SDK as parameter or configuration options.
You can set optional secretSalt
to be used for calculating checksum of request data, which will be sent with each request using &checksum256
field. You need to set exactly the same secretSalt on Countly under Management > Applications>"your_app">Salt for checksum
. If secretSalt
on Countly Server is set, all requests would be checked for validity of &checksum256
field before being processed.
npm install crypto-js;
and from your app use below lines to set your secret salt
// set salt in Countly SDK config
Countly.secretSalt = 'XYZ';
If SALT is not provided, SDK makes ordinary requests without any checksums.
Star Rating
For the rating purpose of your application, you can use star rating component of Countly by implementing steps.
// Dependency to use Countly Star Rating feature
npm install --save react-native-modal
react-native link
For importing star rating component from Countly:
import { StarRating } from 'countly-sdk-react-native';
Then use star rating component as follows:
this.setState({isVisible: false})} // required
/>
// Default values for optional field:
// noOfStars = 5
// message = 'How would you rate the app?'
// dismissButtonTitle = Dismiss
Other SDK usage scenarios
Using custom device ID
If you want to use custom device ID, you can change it as follows. Note that once set, device ID will be persistently stored in device on the first launch, and will not change even after app delete and re-install, unless you change it explicitly.
Countly.changeDeviceId("654321");
Change DeviceId on server
If you want to change the device ID on Countly server, follow steps below.
// First parameter is onServer
let onServer = ture;
// Then call the setNewDeviceId method to set the new Device Id
Countly.setNewDeviceId(onServer, newDeviceId);
// By default the onServer method will be false. Both the parameters are required.
// If onServer is false then current session will be end and the new session starts with new DeviceId.
// If onServer is true than the new session metrics will contain new DeviceId and the old deviceId data will be merged with the new DeviceId.
Force SDK to make POST request by default
// Call method setHttpPostForced with parameter true, as shown below
Countly.setHttpPostForced(true);
SSL Certificate Pinning
To secure the request from "Man in the Middle" attack, you can implement SSL Certificate Pinning in your application. Below are the steps to implement SSL Certificate Pinning.
// Install dependencies
npm i react-native-pinch
// Link the libraries using the following command
react-native link react-native-pinch
After that, you need to put the SSL certificate file (having the extension .cer
) into src/main/assets/
for Android and for iOS place your .cer
files in your iOS Project. Don't forget to add them in your Build Phases > Copy Bundle Resources, in Xcode.
Then you need to set the name of the .cer
file in Countly.cerFileName
config flag as shown below.
// Notice the file name you should set to the config flag
// doesn't have an extension.
Countly.cerFileName = "fileName";
Note: If you set the file name in the Countly.cerFileName
flag and forgot to put the file at the required location, Countly SDK will stop sending the request to the dashboard. Also, the SSL certificate must be globally accepted and not be self-signed.
If you face any challenges to implement, there is a working demo / example in this repository.
We welcome all issues and bug reports - please send them here and we will respond very quickly.