AlgorithmX
Integrations14 min read

React Native Integration

Add AlgorithmX to your React Native app step by step: install the package, start it, identify customers, send events, connect push notifications, and open the right screen from campaigns.

This guide adds AlgorithmX to your React Native app in 8 steps. You keep your app's login, push setup, and navigation. You only add a few lines in places your app already has.

The package @algorithmxcloud/react-native-sdk connects JavaScript to the AlgorithmX Android and iOS SDKs. The work has two parts:

  • A few native lines in Android and iOS. They start the SDK and pass push notifications to it. This must be native, because a notification can start your app before JavaScript runs.
  • Everything else in JavaScript: customers, events, and navigation.

In the examples, names such as appRouter are your own code, not part of the package.

Before you start

Check that you have these:

  • React Native with Android minSdk 24 and iOS 15.1 or later. The package works with the New Architecture and was tested with React Native 0.87.
  • Android: Firebase Cloud Messaging set up. iOS: push notifications set up.
  • The API base URL from AlgorithmX, for example https://api.example.com.
  • The list of customer ID, events, deep links, and custom actions you agreed on with AlgorithmX. See the overview.

AlgorithmX needs the same push details as for native apps. Follow "Before you start" in the Android guide (Firebase project) and the iOS guide (Apple Developer account and APNs key).

Expo: the package has native code, so it does not run in Expo Go. Use a development build, and make sure the native changes in steps 2 and 5 survive prebuild, for example with a config plugin.

The steps

StepWhat you doWhere
1Install the packagepackage.json and ios/Podfile
2Start the SDKMainApplication, AppDelegate, and JavaScript startup
3Tell AlgorithmX who the customer isLogin, app start, logout
4Send eventsWhere actions happen, such as checkout
5Connect push notificationsYour Firebase code and iOS AppDelegate
6Open the right screenJavaScript startup
7Check in-app campaignsNo code
8TestReal Android and iOS phones

Step 1: Install the package

1. Install from npm:

bash
npm install @algorithmxcloud/react-native-sdk

2. Android: nothing more to do. The package brings the Android SDK (cloud.algorithmx:android-sdk) from Maven Central, which React Native projects already use.

3. iOS: add the iOS SDK to your app target in ios/Podfile:

ruby
target 'YourApp' do
  pod 'AlgorithmXSDK', :git => 'https://github.com/algorithmx-cloud/algorithmx-ios-sdk.git', :tag => '1.0.0'
  # Keep your existing pods and React Native setup.
end

Then run:

bash
cd ios && pod install

The pod comes from GitHub, because the public CocoaPods registry stops accepting new pods on December 2, 2026. Autolinking adds the package's own pod for you.

4. Rebuild the app (npx react-native run-android and run-ios, or from Android Studio and Xcode). A reload of JavaScript is not enough after installing native code.

Check: the app builds and starts on both platforms.

Step 2: Start the SDK

You start the SDK in three places: Android, iOS, and JavaScript. Use the same URL in all three.

2a. Android

In onCreate of MainApplication:

kotlin
import algorithmx.engage.core.AlgorithmX
import algorithmx.engage.rn.AlgorithmXReactNative

override fun onCreate() {
    super.onCreate()
    AlgorithmXReactNative.initialize(this, "https://api.example.com")
    AlgorithmX.setSmallIcon(R.drawable.ic_stat_notification) // Optional: your notification icon.
    // Keep your existing startup code, including loadReactNative(this).
}

2b. iOS

In application(_:didFinishLaunchingWithOptions:) of your AppDelegate, before React Native starts:

swift
import AlgorithmXReactNativeSDK
import AlgorithmXSDK

AlgorithmXReactNative.initialize(apiBaseUrl: "https://api.example.com")
UNUserNotificationCenter.current().delegate = self // Keep yours if you already set it.
application.registerForRemoteNotifications() // On every launch.
  • For delivery reports (optional, see step 5b), use initialize(apiBaseUrl: "https://api.example.com", appGroup: "group.com.example.shop") instead.
  • The examples use Swift, which React Native 0.77 and later create. With an older Objective-C AppDelegate, make the same calls from Objective-C.

2c. JavaScript

At the start of your app, before the first screen renders, add your listeners from step 6 first, then connect JavaScript to the SDK:

ts
import AlgorithmX from '@algorithmxcloud/react-native-sdk';

// 1. Add your listeners from step 6 here.

// 2. Connect JavaScript to the SDK that native code already started.
async function start() {
  await AlgorithmX.init('https://api.example.com');
}
start();
  • init fails with E_INIT if its URL is different from the native one.
  • Do not set SDK handlers in native code (such as deepLinkHandler or setNotificationClickListener). The package already sends them to JavaScript; setting them natively breaks that.
  • To see each SDK request while testing, call AlgorithmX.setLoggingEnabled(true) (Android) or AlgorithmX.shared.setLoggingEnabled(true) (iOS) in the native code.

Check: the app starts on both platforms without an E_INIT error.

Step 3: Tell AlgorithmX who the customer is

Until you do this, the SDK uses an anonymous ID for the phone.

At login, and when your app starts with a customer already logged in, call identify with your customer ID:

ts
AlgorithmX.identify('customer_123', { first_name: 'Amina', language: 'ar', loyalty_tier: 'gold' });

Do both places. The second one covers customers who are already logged in when they update to your first app version with AlgorithmX.

At logout, clear waiting campaigns first, so the next person does not see them:

ts
await AlgorithmX.clearWebViewQueue();
AlgorithmX.resetIdentity();

When one account replaces another without a logout:

ts
await AlgorithmX.clearWebViewQueue();
AlgorithmX.identify('customer_456', { language: 'en' });

The SDK remembers the customer after the app restarts. This does not replace your own login. It only tells AlgorithmX who is using the app.

Check: after login, the customer appears in AlgorithmX with the ID you sent.

Step 4: Send events

Send an event right after an action succeeds, for example after an order is confirmed. Put it next to your existing analytics calls.

ts
AlgorithmX.trackEvent('product_view', { product_id: 'SKU-123' });

AlgorithmX.trackEvent('add_to_cart', { product_id: 'SKU-123', quantity: 2 });

AlgorithmX.trackEvent('purchase', {
  order_id: 'ORDER-1001',
  total: 149.9,
  currency: 'SAR',
  items: [{ product_id: 'SKU-123', quantity: 2 }],
});

Rules for events:

  • Values: use text, numbers, true/false, arrays, and objects. Send dates as a timestamp or an ISO 8601 string.
  • Names: use simple names with letters and underscores, such as add_to_cart.
  • Offline: an event sent without internet is lost. It is not sent again later. Keep your own backend as the record of orders and payments.

Check: the event appears for the customer in AlgorithmX.

Step 5: Connect push notifications

You keep your push setup. On each platform you send the push token to AlgorithmX and pass AlgorithmX notifications to the SDK.

5a. Android

Choose the case that matches your app.

Case 1: your app has its own native FirebaseMessagingService. Add the AlgorithmX check at the top, exactly as in step 5 of the Android guide:

kotlin
override fun onMessageReceived(message: RemoteMessage) {
    super.onMessageReceived(message)
    if (AlgorithmX.isAlgorithmXPush(message.data)) {
        AlgorithmX.handleFcmMessage(
            applicationContext, message.data,
            message.notification?.title, message.notification?.body
        )
        return
    }
    // Your existing code for other messages.
}

override fun onNewToken(token: String) {
    super.onNewToken(token)
    AlgorithmX.registerDeviceToken(token)
}

Then also send the token on every app start, in MainApplication.onCreate:

kotlin
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
    AlgorithmX.registerDeviceToken(token)
}

Case 2: your app handles Firebase messages in JavaScript with @react-native-firebase/messaging. Pass AlgorithmX messages on from your existing handlers. Keep the background handler in index.js, outside any component, as Firebase requires:

ts
import { Platform } from 'react-native';
import messaging, { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
import AlgorithmX from '@algorithmxcloud/react-native-sdk';

async function forwardToAlgorithmX(message: FirebaseMessagingTypes.RemoteMessage) {
  const data = (message.data ?? {}) as Record<string, string>;
  if (data.engage_action === 'algo_show_notification' || data.engage_action === 'algo_trigger_webview') {
    AlgorithmX.handleFcmMessage(data, message.notification?.title, message.notification?.body);
  }
}

messaging().setBackgroundMessageHandler(async (message) => {
  await forwardToAlgorithmX(message);
  // Your existing background code.
});
messaging().onMessage(async (message) => {
  await forwardToAlgorithmX(message);
  // Your existing foreground code.
});

// Android only. On iOS, AlgorithmX needs the Apple token from step 5b.
if (Platform.OS === 'android') {
  messaging().getToken().then((token) => AlgorithmX.registerDeviceToken(token));
  messaging().onTokenRefresh((token) => AlgorithmX.registerDeviceToken(token));
}

In both cases, keep your own notification permission prompt; the SDK never asks for permission.

5b. iOS

iOS notifications go through your AppDelegate, so this part is native. It is the same as step 5 of the iOS guide. Add the AlgorithmX lines to these methods:

swift
// Send the Apple push token.
func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
    let apnsToken = deviceToken.map { String(format: "%02x", $0) }.joined()
    AlgorithmX.shared.registerDeviceToken(apnsToken)
}

// Hidden notifications. In-app campaigns arrive here.
func application(
    _ application: UIApplication,
    didReceiveRemoteNotification userInfo: [AnyHashable: Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
    if AlgorithmX.shared.isAlgorithmXPush(userInfo: userInfo) {
        AlgorithmX.shared.handleNotification(userInfo: userInfo) { completionHandler(.newData) }
        return
    }
    // Your existing code.
}

// A notification arrives while the app is open.
func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
    let userInfo = notification.request.content.userInfo
    if AlgorithmX.shared.isAlgorithmXPush(userInfo: userInfo) {
        AlgorithmX.shared.handleNotification(userInfo: userInfo) { completionHandler([.banner, .list, .sound]) }
        return
    }
    // Your existing code.
}

// The customer taps a notification or a button.
func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
) {
    let userInfo = response.notification.request.content.userInfo
    if AlgorithmX.shared.isAlgorithmXPush(userInfo: userInfo) {
        AlgorithmX.shared.handleNotificationResponse(
            actionIdentifier: response.actionIdentifier,
            userInfo: userInfo,
            completionHandler: completionHandler
        )
        return
    }
    // Your existing code.
}
  • Send the Apple (APNs) token, even if your app also uses Firebase on iOS.
  • If a library such as Firebase or Notifee takes over your notification delegate, send a real AlgorithmX notification while testing to check that these lines still run.
  • Turn on Background Modes, Remote notifications in Xcode. In-app campaigns need it.
  • Images and buttons (optional): follow step 9 of the iOS guide. React Native apps use CocoaPods, so add the SDK file EngageNotificationService.swift to the extension instead of the pod.

Check: ask your campaign team to send a test notification to each platform. It appears once.

Step 6: Open the right screen when a customer taps

When a customer taps an AlgorithmX notification, the SDK sends an event to JavaScript. Your listeners open the screens.

EventWhen it comesWhat to do
onDeepLinkThe campaign opens a screen with a link.Open the link with your router.
onCustomActionThe campaign runs a custom action.Open the screen for that action.
onActionButtonThe customer taps a notification button.Handle the button. The notification's main action does not run after it.
onNotificationClickEvery tap, for your information.Nothing. The SDK already runs the campaign's action, so do not navigate here too.

"Open a web page" and "open an in-app campaign" need no listener; the SDK does them.

ts
import AlgorithmX from '@algorithmxcloud/react-native-sdk';
import { appRouter } from './navigation/appRouter'; // Your existing navigation code.

AlgorithmX.addListener('onDeepLink', ({ url }) => appRouter.openUrl(url));

AlgorithmX.addListener('onCustomAction', ({ action, data }) => {
  const details = (data.parsedActionData ?? {}) as Record<string, unknown>;
  if (action === 'view_product' && typeof details.product_id === 'string') {
    appRouter.openProduct(details.product_id);
  } else if (action === 'view_cart') {
    appRouter.openCart();
  }
});

AlgorithmX.addListener('onActionButton', ({ actionText }) => {
  if (actionText === 'view_cart') appRouter.openCart();
});
  • Add all listeners together, at app start, before the first render, for example in index.js or a file it imports. Events that come before JavaScript is ready, such as the tap that started the app, are kept and delivered when the first listener is added. Listeners added later, inside a screen, can miss them.
  • Wait for your navigation. When a tap starts the app, events come before your navigation is ready. Keep the destination and open it when it is ready. With React Navigation, that is when navigationRef.isReady() is true, or in onReady.
  • Match buttons on their action text, not their title, because the title can be translated. Handle every button your campaigns use; a button with no case does nothing.
  • You do not need new links or screens. Give your campaign team the links and action names your released app supports, for example myapp://open/product?id=SKU-123.
  • Keep your normal login and permission checks before sensitive screens: a campaign only suggests where to go.

Check: send a test notification for each link, action, and button your app supports. The right screen opens once.

Step 7: Check in-app campaigns

In-app campaigns need no code. After steps 2 to 5:

  1. AlgorithmX sends a hidden message to the phone, and your native push code passes it to the SDK.
  2. The SDK saves the campaign.
  3. The next time the customer opens the app, the SDK shows the campaign over the current screen, at most one per visit. It closes with the campaign's close button, or with Back on Android.

Check these in your app:

  • Logout: clear waiting campaigns, as in step 3.
  • Your own pop-ups at start: a campaign can appear when the app opens, on top of a modal your app shows at the same time. Try them together.
  • Close button: iPhones have no Back button, so every campaign template needs a close button. Tell your campaign team.
  • Notification permission is not needed for in-app campaigns.
  • Delivery is not guaranteed if the customer force-stops the app (Android) or swipes it away (iOS). Messages then arrive only after the app is opened again.

To see impressions, clicks, and closes while testing, listen to onCampaignInteraction.

Step 8: Test before you release

Use real Android and iOS phones and a test customer. Test release builds, not only debug builds. On iOS, repeat the main checks with a TestFlight build, because store builds use a different Apple push server.

  • Update while logged in: install your current store version, log in, then update to the new build. The customer is recognized without logging in again.
  • Login, restart, logout, second account: events use the right customer each time. No campaign from the first account appears for the second.
  • Your existing notifications still work exactly as before.
  • AlgorithmX notification with the app open, in the background, and closed: a tap opens the right screen once, also when the tap starts the app.
  • Each deep link, custom action, and button opens the right screen.
  • In-app campaign: it appears the next time the app opens and closes with its close button.
  • Notifications turned off: in-app campaigns still arrive.
  • Events appear for the customer in AlgorithmX.

Quick reference

CallWhat it does
AlgorithmXReactNative.initialize(this, apiBaseUrl) (Android)Starts the SDK in MainApplication.onCreate.
AlgorithmXReactNative.initialize(apiBaseUrl:appGroup:) (iOS)Starts the SDK in the AppDelegate. The App Group is optional.
AlgorithmX.init(apiBaseUrl)Connects JavaScript to the SDK. Use the same URL as native code.
AlgorithmX.identify(userId, attributes)Sets the customer. Call at login and app start.
AlgorithmX.resetIdentity()Goes back to an anonymous customer. Call at logout.
AlgorithmX.trackEvent(name, properties)Sends an event.
AlgorithmX.registerDeviceToken(token)Sends a push token from JavaScript (Android).
AlgorithmX.handleFcmMessage(data, title, body)Android: gives an AlgorithmX message received in JavaScript to the SDK.
AlgorithmX.addListener(event, handler)Listens to onDeepLink, onCustomAction, onActionButton, onNotificationClick, onCampaignInteraction. Returns a subscription with remove().
AlgorithmX.clearWebViewQueue()Removes waiting in-app campaigns. Call at logout.
AlgorithmX.getDeviceFingerprint(), AlgorithmX.getWebViewQueueSize()Show the current customer ID and waiting campaigns, for testing.

The native calls in step 5 are the same as in the Android and iOS guides.

Something not working?

ProblemWhat to check
"Native module not found" at startRebuild the app after installing the package. On iOS, the AlgorithmXSDK pod line is in the Podfile and pod install ran.
init fails with E_INITJavaScript and native code use different URLs. Use the same URL in all three places of step 2.
No events in AlgorithmXThe native code in step 2 runs with the right HTTPS URL, and the phone is online.
No AlgorithmX notificationsSee "Something not working?" in the Android or iOS guide: token, sending permission, and passing messages to the SDK.
A tap does not reach JavaScriptListeners are added at app start, all together, before the first render. Native code does not set its own SDK handlers.
A tap that starts the app opens nothingYour router keeps the destination until navigation is ready.
A screen opens twice after a tapYou navigate in onNotificationClick and also in onDeepLink or onCustomAction. Navigate only in the specific listener.
A button does nothingYour onActionButton listener has no case for that action text.
In-app campaign never appearsStep 5 is in place, iOS Background Modes is on, the app was not force-closed, and you opened it again after the campaign was sent.
A previous account's campaign appearsCall clearWebViewQueue() at logout and when switching accounts.

Next steps

Create your first campaigns with In-App Push Campaigns and In-App View Campaigns. Go back to the overview for other platforms.