Skip to content

React Native

Integration

Kumulos provides an SDK in the form of an NPM package to ease the integration of the Kumulos Analytics, Push Notification, Crash Reporting and Build features into your React Native apps.

Installation & Linking

The Kumulos React Native module requires native features so should be installed in an ejected project.

To install & link the project, run the following commands:

npm install kumulos-react-native --save
pod install --project-directory=ios

Manual linking steps are required depending on platform. See the following sections for the necessary steps.

Android Linking Steps (required)

To complete the linking process for Android, you need to ensure your project uses the following versions for tools & libraries:

  • Gradle plugin v3.1.3 or greater
  • Build tools v23.0.3 or greater
  • Support library v27.+

In addition, if not present you must add the following to your android/app/build.gradle file:

android {
    // ...

    packagingOptions {
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/LICENSE'
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

Initialization

To configure the SDK for use you need to initialize it with your app's API credentials. This must be done in the following three places to ensure correct operation of the Kumulos SDK:

  1. In your app's JavaScript/TypeScript code
  2. In the iOS AppDelegate.m native code
  3. In the Android MainApplication.java native code

To initialize the SDK, add the following snippets in the appropriate locations.

1. In your App.js:

import Kumulos from "kumulos-react-native";

Kumulos.initialize({
  apiKey: "YOUR_API_KEY",
  secretKey: "YOUR_SECRET_KEY",
});

2. In your ios/AppDelegate.m application:didFinishLaunchingWithOptions: method:

#import <KumulosReactNative/KumulosReactNative.h>
...
KSConfig* kumulosConfig = [KSConfig
                                configWithAPIKey:@"YOUR_API_KEY"
                                andSecretKey:@"YOUR_SECRET_KEY"];

[KumulosReactNative initializeWithConfig:kumulosConfig];

3. In your android/app/src/main/java//MainApplication.java onCreate method:

import com.kumulos.android.KumulosConfig;
import com.kumulos.reactnative.KumulosReactNative;
...
KumulosConfig.Builder kumulosConfig = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY");
KumulosReactNative.initialize(this, kumulosConfig);

Your API Key and Secret Key can be obtained from the App Dashboard in your agency console.

Checking installs of your App

When you run your app on a simulator or install your app on a device, you can check that the SDK has been initialized correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install to see more information.

Recent installs

If you experience any difficulties integrating an SDK or initializing the Kumulos client, please don't hesitate to contact support who are standing by to help!

That's it, you're now good to go! Continue reading to learn more about analytics, configuring push notifications and calling Build API methods in your app.

Installation ID

When initialized for the first time, the Kumulos SDK will create a unique identifier for the current installation. This identifier can be used to target push notifications to a specific device via KScript or the Push Notifications API.

In order to retrieve this identifier, simply access the class variable:

const id = await Kumulos.getInstallId();

Once you have the installation ID, you can send it to your app's backend to be used later for push targeting. For more information about push targeting, please see the KScript Documentation or push notification documentation as appropriate.

Analytics

Kumulos provides concise and easy to consume analytics & reporting features. By initializing the SDK, you automatically get session & engagement reporting out the box.

Session Analytics

Kumulos records sessions based on application foreground and background events. When an app enters the background, Kumulos will wait for a configurable idle period. If there are no more foreground events during that idle period, the current session will be closed.

Session analytics

So long as you initialize the SDK at some point in your app's lifecycle, Kumulos will automatically record analytics data such as the device model, operating system version and more, available in Analytics & Reporting for your app.

Event Tracking

Kumulos allows you to track custom analytics events that can be used as a trigger to fire automation rules (e.g. to trigger a push notification) or as steps in a funnel to track conversion through key user journeys in your app.

Track conversion

To track a custom analytics event, use Kumulos.trackEvent as follows:

Kumulos.trackEvent("product.purchased", {
  productId: 404,
});

Each event and its properties must be less than 250 KiB in size for the event to be tracked.

Event tracking is available offline as all events are persisted locally before being synced to the server in batches in the background.

A similar method trackEventImmediately will immediately start an event sync rather than waiting for the next time the app is backgrounded.

Checking events from your App

When you run your app on a simulator or install your app on a device, you can check that the SDK is recording events correctly by selecting the app and clicking the Installs tab to see the ten most recent installs of your app. Click on any install and then click on the Events tab.

Install events

Alternatively, to see counts of all analytics events, including system events such as opened a push notification, recorded by installs of the app in the last 30 days, expand 'Analytics' and click 'Explore' in the left menu. For comparison, the total number of sessions in the same period is shown.

Analytics Explorer

User Association

Kumulos allows associating a user identifier with the current installation ID. This user identifier is useful for performing analytics aggregations & analyses at the user level, for example, funnels completed by users across multiple devices. You can also optionally associate a collection of attributes with the user.

To associate the current app installation with a user, you can use the helper method as shown below:

Kumulos.associateUserWithInstall('unique-user-id');

User association is time-aware, so say two different users log in to the app, their user IDs will be associated with the same install for the time between subsequent calls to the helper method. For example:

Kumulos.associateUserWithInstall("Bob");
// This event will belong to Bob
Kumulos.trackEvent("product.purchased", null);
Kumulos.associateUserWithInstall("Alice");
// This event will belong to Alice
Kumulos.trackEvent("product.purchased", null);

Attributes

You can optionally associate a collection of attributes with the user for targeting, personalization or attribution. To associate attributes with the user, pass a collection into the helper method as shown.

const attributes = {
  name: "Shawn",
  age: 25,
};

Kumulos.associateUserWithInstall("unique-user-id", attributes);

The collection of attributes for a given user must be less than 250 KiB in size.

If you do not have a user identifier, use the installation ID generated by the Kumulos SDK.

Location Tracking

You can send Kumulos location updates and use this to trigger events such as push notifications when an install enters a GeoFence.

Once you have configured location updates on the platform of choice you can send the updates to Kumulos via the helper method in the stats namespace.

Kumulos.sendLocationUpdate(-54.618946, -65.234551);

For information on receiving location updates, see the React Native Geolocation library.

Beacons

You can send Kumulos beacon proximity updates and use these to trigger automations such as sending a push notification when an install is in proximity to a beacon.

The Kumulos SDK provides helper methods to notify our services of proximity to a detected beacon.

You will need to integrate a suitable plugin to detect the beacon proximity events (for example, react-native-beacons-manager).

Eddystone Beacon Detection

Kumulos.trackEddystoneBeaconProximity({
    hexNamespace: 'namespace',
    hexInstance: 'instance',
    distanceMetres: 10
});

Beacon monitoring on Android typically requires a device with BLE, and API level 18+. You can read more about detecting beacons in the Android Nearby reference.

iBeacon Detection

iOS
Kumulos.trackiBeaconProximity({
  uuid: "vendor-uuid",
  major: 1,
  minor: 2,
});
Android
Kumulos.trackEventImmediately("k.engage.beaconEnteredProximity", {
  type: 1,
  uuid: "iBeacon UUID",
  major: 1,
  minor: 2,
  proximity: "iBeacon Proximity",
});

Messaging & Push Notifications

Kumulos provides powerful multi-channel messaging services to reach your users. By initializing the SDK you can quickly and easily receive both push notifications to re-engage your users as well as feature-rich In-App messages.

Configuration & Integration

The Kumulos SDK provides all functionality to handle push registration & notifications using FCM and APNS.

To fully integrate this, there are some steps required for each platform before you can consume pushes from the JS layer. The steps required for each platform are documented below.

Configuring APNS for iOS

To integrate Kumulos Messaging into your iOS project, you have to complete the following steps with either Key or Certificate based credentials.

  1. Set up APNs credentials in your Apple Developer account
  2. Configure Push in the Kumulos Agency Console
  3. Integrate SDK components with your iOS project & enable in-app messaging
  4. Register for push from the client app

Configure APNs

In order to generate a P8 key for Apple services first access your account at https://developer.apple.com/ and select 'Certificates, Identifiers & Profiles', then select 'Keys' on the left.

Apple Developer - Keys

Select 'Create a Key' and on the form 'Register a New Key' enter a meaningful name such as 'APNS Access Key' and check the 'Enable' checkbox for 'Apple Push Notifications service (APNs)', click 'Continue'.

Apple Developer - Register Key

On the confirmation screen double check the APNs enablement is set then click 'Register'

On the final screen take note of your KeyID and download the key. Note that you can only download the key once, if lost the key must be revoked and re-created.

Downloading the key will save a .p8 file with the access credentials.

You now have all the details to configure your Kumulos App, expand 'Messaging' in the left menu, select 'Configuration' and click the cog next to the Apple icon. Select APNs P8 and select your file, enter your other details and click 'Configure'.

Configuring APNs

Configure your app capabilities and entitlements

In your app project settings use the "+ capability" button to add the App Groups, Background Modes and Push Notifications capabilities, in Background Modes you should have the "Remote Notifications" mode checked.

The video below shows how to create a push certificate on your Apple Developer portal, configure these certificates in Kumulos, and how to then configure the necessary entitlements in your iOS Xcode project.

Configuring APNS for iOS with Kumulos

Note you must use a real device to test push notifications on iOS because simulators cannot register for push notifications.

Configuring FCM for Android

The video below shows how to create a Firebase project configuration to make use of FCM to send push notifications to Android devices.

Enabling Push Notifications for Android

The key points are:

  • Create a Firebase project for FCM
  • Upload FCM credentials to Kumulos via the your-project-firebase-adminsdk.json file
  • Download the google-services.json and add to your project's android/app directory
  • Add classpath 'com.google.gms:google-services:4.3.8' to your android/build.gradle buildscript dependencies section
  • Add dependencies to you android/app/build.gradle file. Kumulos supports [19.0.0, 22.99.99] Firebase Messaging version range, which corresponds to [20.0.0, 28.99.99] Bill of Materials version range.
dependencies {
    ...
    implementation platform('com.google.firebase:firebase-bom:28.2.0')
    implementation 'com.google.firebase:firebase-messaging'
}
  • Add apply plugin: 'com.google.gms.google-services' at the bottom of your android/app/build.gradle file

Please note it is the Google Service Account private key JSON file that needs to be uploaded to Kumulos, not the Google Services JSON file you include in your app project. The Google Service Account JSON file can be generated from the 'Service Accounts' section of the Firebase Developer console as is shown in the relevant section of the video above.

After this setup has been completed, you can continue with the client registration.

Enabling In-App Messaging

In your ios/AppDelegate.m application:didFinishLaunchingWithOptions: method:

#import <KumulosReactNative/KumulosReactNative.h>
...
KSConfig* kumulosConfig = [KSConfig
                                configWithAPIKey:@"YOUR_API_KEY"
                                andSecretKey:@"YOUR_SECRET_KEY"];
[kumulosConfig enableInAppMessaging:KSInAppConsentStrategyAutoEnroll];
[KumulosReactNative initializeWithConfig:kumulosConfig];

You should also enable Background Fetch in Background Modes capabilities section of your Xcode project.

In your android/app/src/main/java//MainApplication.java onCreate method:

import com.kumulos.android.KumulosConfig;
import com.kumulos.reactnative.KumulosReactNative;
...
KumulosConfig.Builder kumulosConfig = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY");
kumulosConfig.enableInAppMessaging(KumulosConfig.InAppConsentStrategy.AUTO_ENROLL);
KumulosReactNative.initialize(this, kumulosConfig);

The above configurations set up auto-enrollment for in-app messaging.

Registering for & Handling Push Notifications

The following sample code shows how to use Kumulos to handle push notifications for deep-linking and other common messaging tasks.

import Kumulos from "kumulos-react-native";

Kumulos.initialize({
  apiKey: "YOUR_API_KEY",
  secretKey: "YOUR_SECRET_KEY",
  pushReceivedHandler: (notification) => {
    // Called when a push is received with your app in the foreground
  },
  pushOpenedHandler: (notification) => {
    // Called when a user taps on a push notification
  },
  inAppDeepLinkHandler: (data) => {
    // Called when a user taps a deep-link action button from an in-app message
  },
});

// When you are ready to request the push token from the user, you would then call:
Kumulos.pushRequestToken();

If you want to unregister the token for the current installation, you can use Kumulos.pushRemoveToken().

Checking Push Registrations

When you run your app on a simulator or install your app on a device, you can check that the install has successfully registered for push notifications by selecting the app and clicking the Installs tab to see the ten most recent installs of your app.

Click on an install, click the 'Push' tab and click Send Test Push.

Install push details

If you do not receive the push notification, check the Error Log for any errors sending the push notification to the native push gateways. If you continue to experience problems, please don't hesitate to contact support who are standing by to help!

Supporting Pictures and Action Buttons in Notifications

When sending a push notification you can attach a picture or action buttons to it. They will show on iOS 10+ devices and Android devices with API level 16+.

Integrating Android

No extra steps needed.

Integrating iOS

The notification will expand upon swiping the notification on devices supporting 3D Touch. In order to enable this functionality you need open your iOS project in Xcode and add a Notification Service Extension to your application.

Make sure to correctly set up signing for the extension target.

Add the following to the Podfile generated by React Native and run pod install.

target 'KumulosNotificationServiceExtension' do
  pod 'KumulosSdkObjectiveCExtension', '4.6.0'
end

Then replace the contents of NotificationService.m with the following lines:

#import "NotificationService.h"
#import <KumulosSDKExtension/KumulosNotificationService.h>

@interface NotificationService ()
@end

@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
   [KumulosNotificationService didReceiveNotificationRequest:request withContentHandler: contentHandler];
}
@end

Advanced

Supporting push delivery tracking and badges

For push delivery tracking and badges to work correctly you need to

  1. Set up Notification Service Extension as described above
  2. Add App Groups capability to your App and Notification Service Extension targets
  3. Set group to group.{your.bundle.identifier}.kumulos for both targets

Note that due to iOS limitations badge is not set when app is in the foreground

Handling notification action buttons

When a user interacts with your push message the pushOpenedHandler defined as above is called. If a button was tapped, the notification object will contain an actionId property:

Kumulos.initialize({
    ...
    pushOpenedHandler: (notification) => {
        console.log(notification.actionId);
    },
});

If you would like your users to opt-in to receive In-App messages you can configure the SDK during initialization to make opt-in explicit by setting the strategy, then calling the SDK helper to manage their consent.

In your ios/AppDelegate.m application:didFinishLaunchingWithOptions: method:

#import <KumulosReactNative/KumulosReactNative.h>
...
KSConfig* kumulosConfig = [KSConfig
                                configWithAPIKey:@"YOUR_API_KEY"
                                andSecretKey:@"YOUR_SECRET_KEY"];
[kumulosConfig enableInAppMessaging:KSInAppConsentStrategyExplicitByUser];
[KumulosReactNative initializeWithConfig:kumulosConfig];

In your android/app/src/main/java//MainApplication.java onCreate method:

import com.kumulos.android.KumulosConfig;
import com.kumulos.reactnative.KumulosReactNative;
...
KumulosConfig.Builder kumulosConfig = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY");
kumulosConfig.enableInAppMessaging(KumulosConfig.InAppConsentStrategy.EXPLICIT_BY_USER);
KumulosReactNative.initialize(this, kumulosConfig);

Once the configs have been set, you can now manage consent from the JS layer:

import { KumulosInApp } from "kumulos-react-native";

KumulosInApp.updateConsentForUser(true);

Note managing consent explicitly with the AUTO_ENROLL strategy is not supported and will result in a runtime exception

Deep-linking for In-App

In-App messages allow you to hand-off to react-native application screens via deep-linking action buttons. When tapped, these buttons pass control to the defined deep-link handler, including their defined data payload (configured in the In-App message composer for the action button).

import Kumulos from 'kumulos-react-native';

Kumulos.initialize({
    ...,
    inAppDeepLinkHandler: (data) => {
        // Called when a user taps a deep-link action button from an in-app message
    }
});

Using the In-App Inbox

In-app messages can optionally be persisted in a user-level inbox for later retrieval. This allows you to build features such as loyalty rewards or expiring coupons into your app. Regardless of whether they are stored in the inbox, the maximum amount of in-apps stored on a device is 50 (the oldest messages exceeding this limit will be evicted).

Retrieve messages

To retrieve a list of messages from the user's inbox and present the first in the list, see the following example:

KumulosInApp.getInboxItems().then(function (items) {
  KumulosInApp.presentInboxMessage(items[0]);
});
Mark as read

To mark a single or all inbox messages as read:

//single
KumulosInApp.getInboxItems().then(function (items) {
  KumulosInApp.markAsRead(items[0]);
});

//all
KumulosInApp.markAllInboxItemsAsRead();
Delete message

You can also delete an in-app message from inbox:

KumulosInApp.getInboxItems().then(function (items) {
  KumulosInApp.deleteMessageFromInbox(items[0]);
});
Inbox updated handler

In order to be notified when inbox changes you may set up a handler. The handler fires when one of the following happens to an in-app with an inbox configuration:

  • message fetched from server
  • message opened
  • message marked as read
  • message deleted
  • message evicted (expires or limit of stored messages exceeded)

You can use it as follows:

KumulosInApp.setOnInboxUpdatedHandler(() => {
  //refresh your inbox
});

Note, you can do KumulosInApp.setOnInboxUpdatedHandler(null) when you stop being interested in inbox updates.

Get inbox summary

You can retrieve an inbox summary as follows:

KumulosInApp.getInboxSummary()
  .then((summary) => {
    console.log(
      "total: " + summary.totalCount + " unread: " + summary.unreadCount
    );
  })
  .catch(() => {
    console.log("failed to get inbox summary!");
  });
Get inbox item's image URL

Each inbox item may have an image associated with it. imageUrl returns a URL to the image resized to 300px width or null if there is no image.

KumulosInApp.getInboxItems().then(function (items) {
    // Image resized to 300px width
    const url = items[0].imageUrl;
}

Note if the message was created through the API (as opposed to Kumulos Messaging Dashboard) and contains a full URL to an image hosted elsewhere, imageUrl contains original URL without any resizing applied.

Channels

You can create and manage subscriptions to push channels from the SDK. Channels allow you to send push notifications to certain interest groups.

All channel management is performed through methods of the PushSubscriptionManager class.

const subManager = Kumulos.getPushSubscriptionManager();

The interface of the subscription manager is as follows:

export interface PushChannel {
    uuid: string;
    name?: string;
    subscribed: Boolean;
    meta?: any;
}

export interface ChannelSpec {
    uuid: string;
    subscribe: boolean;
    meta?: any;
    name?: string;
    showInPortal?: boolean;
}

interface PushSubscriptionManager {
    constructor(client: KumulosClient);
    /**
     * Subscribes to the channels given by unique ID
     */
    subscribe(uuids: string[]): Promise<Response>;
    /**
     * Unsubscribes from the channels given by unique ID
     */
    unsubscribe(uuids: string[]): Promise<Response>;
    /**
     * Sets the current installations channel subscriptions to those given by unique ID.
     *
     * Any other subscriptions will be removed.
     */
    setSubscriptions(uuids: string[]): Promise<Response>;
    /**
     * Clears all of the existing installation's channel subscriptions
     */
    clearSubscriptions(): Promise<Response>;
    /**
     * Lists the channels available to this installation along with subscription status
     */
    listChannels(): Promise<PushChannel[]>;
    /**
     * Creates a push channel and optionally subscribes the current installation.
     *
     * Name is optional, but required if showInPortal is true.
     */
    createChannel(channelSpec: ChannelSpec): Promise<PushChannel>;
}

When creating channels, the visibility and meta data can be controlled. Please make sure you understand these concepts when creating channels from the SDK.

Deferred Deep Linking

Deep linking allows users to reach app content by clicking a link. This can be achieved even if app is not installed.

To integrate deep linking into your React Native project, you have to complete the following steps.

Configuration & Setup (React)

Configure a deep link handler:

import Kumulos, {DeepLinkResolution} from 'kumulos-react-native';

Kumulos.initialize({
    apiKey: 'YOUR_API_KEY',
    secretKey: 'YOUR_SECRET_KEY',
    ...
    deepLinkHandler: (resolution, link, data) => {
      // Called when a user taps a deep-link which brings user to the app
      switch(resolution){
        case DeepLinkResolution.LinkMatched:
          console.log(data);
      }
    },
});

Configuration & Setup (iOS)

If your app doesn't use scenes, add to your AppDelegate.m:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
    return [Kumulos application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}

If your app uses scenes: add to SceneDelegate.m:

- (void) scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    [Kumulos scene:scene continueUserActivity: userActivity];
}

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions{
    if(![scene isKindOfClass:[UIWindowScene class]]){
        return;
    }

    // Deep links from cold starts
    NSUserActivity* userActivity = [[[connectionOptions userActivities] allObjects] firstObject];
    if (userActivity){
        [Kumulos scene:scene continueUserActivity: userActivity];
    }
}

Finally, you need to associate a domain with your app. Note that the subdomain you specify here should match the one you specified on the deep link configuration page on Kumulos Dashboard.

  1. Add the Associated Domains capability to your main app target
  2. Set 'domains' to applinks:{yourSubdomain}.lnk.click

Associated Domain capability

Configuration & Setup (Android)

Add an intent filter to your main activity:

<intent-filter android:label="deepLabel" android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <!-- Specify which URIs should be matched. Note, domain should be .lnk.click -->
    <data android:scheme="https" android:host="subdomain.lnk.click"/>
</intent-filter>

Note that the subdomain you specify above should match the one you specified on the deep link configuration page on the Kumulos Dashboard.

Note that setting android:autoVerify="true" will verify ownership of the domain, so, instead of offering a list of apps to select from your app will open automatically. No further actions are needed to enable this.

Add following overrides to the main activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Kumulos.seeIntent(this, getIntent(), savedInstanceState);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    Kumulos.seeInputFocus(this, hasFocus);
}

/*
 * If the main activity in AndroidManifest has android:launchMode="singleTop", add following lines as well.
 * It is advisable to have launch mode single top, as otherwise app link will create another copy of the
 * activity on top of the stack if activity is already running.
 */

//@Override
//protected void onNewIntent(Intent intent) {
//    super.onNewIntent(intent);
//    Kumulos.seeIntent(this, intent);
//}

Build

You can call API methods defined in the Kumulos Build service using the Kumulos.call method.

To talk to Kumulos, you need two things:

  • your method title (in lowerCamelCase)
  • an (optional) parameters object

Kumulos.call returns a promise, see example usage below:

const params = {
  user: "[email protected]",
};

try {
  const data = await Kumulos.call("yourMethodName", params);
} catch (err) {
  console.error(err);
}

And you're done! You can now make calls to Kumulos from your React Native application. The data object returned by Kumulos.call can be either an array of objects (in case of a select action) or a number in case of other actions.

Crash

Crash reporting allows you to track unhandled exceptions in your app, and optionally log any caught exceptions for further investigation. Crash reporting is not enabled by default. To enable this feature, simply modify your Kumulos configuration as follows:

In your App.js:

Kumulos.initialize({
  apiKey: "YOUR_API_KEY",
  secretKey: "YOUR_SECRET_KEY",
  enableCrashReporting: true,
});

In your ios/AppDelegate.m application:didFinishLaunchingWithOptions: method:

#import <KumulosReactNative/KumulosReactNative.h>
...
KSConfig* kumulosConfig = [KSConfig
                                configWithAPIKey:@"YOUR_API_KEY"
                                andSecretKey:@"YOUR_SECRET_KEY"];

[kumulosConfig enableCrashReporting];

[KumulosReactNative initializeWithConfig:kumulosConfig];

In your android/app/src/main/java//MainApplication.java onCreate method:

import com.kumulos.android.KumulosConfig;
import com.kumulos.reactnative.KumulosReactNative;
...
KumulosConfig.Builder kumulosConfig = new KumulosConfig.Builder("YOUR_API_KEY", "YOUR_SECRET_KEY");
kumulosConfig.enableCrashReporting();
KumulosReactNative.initialize(this, kumulosConfig);

That's it! Unhandled exceptions that lead to crashes will now be recorded automatically and shown in your App Delivery Console.

For React Native, the crash reporting feature includes both native code crash reporting, and JavaScript error reporting. Native code crash reporting would catch crashes of the React Native host process, whilst JavaScript error reporting catches unhandled errors in your application source code.

Source Mapping

When you build your React Native app for production, you will generate a minified JavaScript bundle.

In order to show source file locations for any JS error traces, you need to do the following:

  • Generate a source map for the main JavaScript bundle for each platform
  • Set the sourceMapTag field in the Kumulos initialization options
  • Upload source maps matching the version of the configured sourceMapTag

For example, during initialization:

Kumulos.initialize({
  apiKey: "YOUR_API_KEY",
  secretKey: "YOUR_SECRET_KEY",
  enableCrashReporting: true,
  // Configure the version for the source maps
  sourceMapTag: "1.0.0-rc1",
});

To build the minified JS bundles with source maps, the following command can be used:

react-native bundle --dev false --platform ios --entry-file index.js --bundle-output main.jsbundle --sourcemap-output main.jsbundle.map

Now you would upload the source maps for version 1.0.0-rc1 to the Crash Dashboard in your App Delivery Console.

If you are automating your builds, you can upload the source maps from your CI environment. See the following sample script for reference.

#!/bin/sh
## TODO set version to match the configured sourceMapTag in the SDK init options
VERSION=''

## TODO set up the keys from your App Dashboard
API_KEY='YOUR_API_KEY'
SERVER_KEY='YOUR_SERVER_KEY'

## TODO customize the archiving step to include your source maps
zip -r maps.zip main.jsbundle.map

UPLOAD_URL='https://crash.kumulos.com/sourcemaps'

curl --fail --retry 3 --retry-delay 3 --user "$API_KEY:$SERVER_KEY" -X POST -F version="$VERSION" -F file="@maps.zip" "$UPLOAD_URL"
rm maps.zip

N.B. Due to an issue with the Metro bundler, source maps generated by React Native < 0.56 with minification enabled may not be processed correctly

Troubleshooting

iOS: Duplicate Symbol Errors when Using Other Crash Reporting Tools

If you intend to use a third party crash reporting tool instead of Kumulos, you may encounter duplicate symbol errors during the iOS project build step.

This happens when the other crash reporting tool also depends on the KSCrash library which Kumulos uses for native exception handling.

In order to resolve the duplicate symbol issue, you can strip the KSCrash symbols from the Kumulos static library with the following script.

Once the script has been run, it will produce a libKumulosSDKiOS-nocrash.a library which can then be linked in the React Native iOS project instead of the libKumulosSDKiOS.a library file.

#!/bin/sh

## This script strips out KSCrash symbols from the Kumulos SDK static library.
## This is necessary when using another crash reporting tool based on KSCrash.
#
## The script should be run from the directory of the Kumulos library file.
## After running, it will produce a -nocrash.a library file. This file can then
## be linked in the project instead of the default library.

COMBINED_LIB="libKumulosSDKiOS.a"
ARCHS="armv7 arm64 x86_64 i386"

if [ ! -f $COMBINED_LIB ]; then
    echo "$COMBINED_LIB not found, aborting!"
    exit 1
fi

ROOT="$PWD"
WRK_DIR=`mktemp -d -t k`

for arch in $ARCHS; do
    echo "Processing architecture $arch"

    ARCH_DIR="$WRK_DIR/$arch"

    # Split out the architecture slice from the library
    mkdir -p $ARCH_DIR
    ARCH_LIB="$ARCH_DIR/libKumulosSDKiOS-$arch.a"
    lipo -thin $arch $COMBINED_LIB -output $ARCH_LIB

    # Extract the object files
    cd $ARCH_DIR
    ar -x "libKumulosSDKiOS-$arch.a"

    # Remove KSCrash object files
    rm  KSCrash* \
        KSObjC.o \
        NSError+SimpleConstructor.o \
        Container+DeepSearch.o \
        KSCPU* \
        Demangle.o \
        KSCString.o \
        KSDate.o \
        KSDebug.o \
        KSDemangle* \
        KSDynamicLinker.o \
        KSFileUtils.o \
        KSID.o \
        KSJSON* \
        KSLogger.o \
        KSMach* \
        KSReachability* \
        KSStack* \
        KSSignal* \
        KSSymbolicator.o \
        KSSysCtl.o \
        KSThread.o \
        Punycode.o \
        NSData+GZip.o \
        NSMutableData+AppendUTF8.o \
        KSMemory.o \
        KSString.o

    # Combine back into a static library
    libtool -static *.o -o "/libKumulosSDKiOS-$arch-nocrash.a"
    cd $ROOT

done

## Bundle up a combined library with all architectures again
lipo -create "$WRK_DIR/"*-nocrash.a -output libKumulosSDKiOS-nocrash.a

## Cleanup
rm -rf "$WRK_DIR"

Changelog

7.0.0

Starting from Android 13, notifications permission is off by default. We have changed our existing API method Kumulos.pushRequestToken() to Kumulos.pushRequestDeviceToken(). In case the app is running on Android 13 and higher, the notifications are off and were never explicitly turned off, this new method is now causing the notification permission request prompt to appear. Consider calling this method when it is most appropriate to request the notification permission.

6.2.2

  • Fix in-app inbox item handling of null data payloads on iOS

6.2.1

  • Fix Promise rejection chains for push channel manager
  • Fix race condition on Android if a push is received during app launch
  • Apply NPM audit fixes

6.2.0

  • Add probability-based matching for Web-to-App Banners
  • Fix ANR when loading push media over slow/unstable connections on Android

6.1.0

  • Added support for notification channels on Android

6.0.0

  • Allow marking in-app messages as read
  • Allow setting onInboxUpdated handler, see docs above
  • Add getInboxSummary helper method, see docs above
  • Expose extra fields on InAppInboxItem: sentAt, data and imagePath
  • Use latest base SDKs
  • On Android depend on FM BoM added by SDK consumers instead of FM version range.

Upgrade Guide

  • Add the following lines to your app module's build.gradle. Check supported version range in the integration guide above.
dependencies {
    ...
    implementation platform('com.google.firebase:firebase-bom:28.2.0')
    implementation 'com.google.firebase:firebase-messaging'
}

5.4.0

  • Deep Linking (see integration guide)

5.3.2

  • Fix header include problems failing builds with RN 0.63

5.3.1

  • Update dependencies for latest NPM audit fixes

5.3.0

  • In-App inbox deletion

iOS

  • Delivery tracking
  • Incrementing badges

You need to set up App Groups and add Notification Service Extension as described above for delivery tracking and badges to work.

Android

  • Update to depend on AndroidX modules directly
  • Update Firebase packages to latest versions
  • Update ACRA to latest version
  • minSDK raised from 14 to 16
  • Support custom sounds for notification
  • Show "sent when" on notification
  • Set long text style for allowing reading longer messages

5.2.0

  • Support for in-app message expiry
  • Support pictures in push notifications
  • Support push action buttons

5.1.2

  • Fix type declarations for pushRequestToken method

5.1.1

  • Update iOS base dependency version for latest bugfixes

5.1.0

  • Update iOS base dependency version for latest bugfixes
  • Update Android base dependency version for latest bugfixes

5.0.0

  • Add In-App Messaging feature
  • Add native Push Notifications support
  • Update base SDKs

Upgrade Guide

  • Initialization is now required in native Android, native iOS, and JavaScript for full feature coverage
  • Kumulos.pushTrackOpen has been removed (now handled by the SDK)
  • Push registrations & notifications are now handled by the SDK so existing 3rd-party push plugins are no longer required

4.0.0

Updates for React Native 0.60:

  • Add podspec for iOS builds, stop depending on static library
  • Remove deprecated RNPM from package.json
  • Update android build.gradle for AndroidX & jetifier support

3.0.0

RN 0.59 updates dependencies on the support library to v28, and bumps okhttp to v3.12.x, which causes dependency conflicts.

With this, we exclude the dependencies from the base Kumulos SDK to allow using the versions included by RN 0.59.

2.1.0

  • Add helper to get currently associated user identifier
  • Add helper to clear any current user association
  • Update to Kumulos Android SDK 6.0.0
  • Update to Kumulos Objective-C SDK 1.7.0
  • Remove need to manually link the analytics data model file on iOS (now embedded in iOS library)

Update Steps

You no longer need to manually add the KAnalytics data model file to your iOS project. If you previously linked the data model file, it should now be deleted from your iOS project.

2.0.2

  • Add export of Kumulos to type definitions. Fixes #6

2.0.1

  • Pass in override target type for iOS

2.0.0

  • Wrap native SDKs in native modules to improve maintainability & feature parity
  • Add session analytics events
  • Add custom event tracking
  • Add user association with attributes
  • Add beacon proximity helpers

Breaking Changes

  • SDK interface now matches static singleton of other SDKs
  • Manual linking steps now required for iOS & Android
  • New Android tooling version dependencies

1.0.0

  • Initial release with Analytics, Push, and Build support for iOS & Android