sirrus-react-native-sdk
v0.1.19
Published
Production-focused React Native SDK for Sirrus analytics, push notifications, deep links, deferred deep links, and in-app overlays.
Maintainers
Readme
sirrus-react-native-sdk
React Native SDK for Sirrus analytics, push notification workflows, deep links, deferred deep links, and in-app overlays.
Features
- Event tracking with batching, retry support, session tracking, and identity support
- Push token registration for FCM and APNs
- Push received, opened, and action-click tracking
- Foreground notification presentation with native Android and iOS support
- Rich push payload support for images, GIFs, videos, deep links, channels, categories, and action buttons
- Deep link and deferred deep link handling
- In-app overlays with optional HTML rendering through
react-native-webview - Firebase Messaging bridge for React Native apps using
@react-native-firebase/messaging
Installation
npm install sirrus-react-native-sdk @react-native-async-storage/async-storage react-native-webviewOr with pnpm:
pnpm add sirrus-react-native-sdk @react-native-async-storage/async-storage react-native-webviewFor iOS, install pods after adding the package:
cd ios
pod installQuick Start
Initialize the SDK once when your app starts.
Only apiKey is required for the network handshake. The SDK calls Sirrus SSO
internally, receives the JWT and ingestion URL, and then sends analytics,
push-token, deep-link, and overlay requests through its own transport. Do not
pass a custom networkClient in product apps unless you are deliberately
mocking the Sirrus backend for tests.
import AsyncStorage from "@react-native-async-storage/async-storage";
import {
createAsyncStorageAdapter,
sirrusReactNativeSDK,
} from "sirrus-react-native-sdk";
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
debug: __DEV__,
storage: createAsyncStorageAdapter(AsyncStorage),
appInfo: {
name: "My App",
version: "1.0.0",
buildNumber: "100",
environment: __DEV__ ? "development" : "production",
},
});Managed Campaign Setup
Use initSirrusManagedSdk when the app should let Sirrus manage campaign notifications, push token registration, notification open tracking, and overlay evaluation from one setup flow.
import AsyncStorage from "@react-native-async-storage/async-storage";
import messaging from "@react-native-firebase/messaging";
import {
createAsyncStorageAdapter,
initSirrusManagedSdk,
sirrusReactNativeSDK,
} from "sirrus-react-native-sdk";
const sirrusCampaigns = await initSirrusManagedSdk(
sirrusReactNativeSDK,
{
apiKey: "your-api-key",
debug: __DEV__,
storage: createAsyncStorageAdapter(AsyncStorage),
appInfo: {
name: "My App",
version: "1.0.0",
buildNumber: "100",
environment: __DEV__ ? "development" : "production",
},
notificationUI: {
defaultAndroidChannelId: "sirrus-marketing",
androidChannels: [
{
id: "sirrus-marketing",
name: "Sirrus Marketing",
importance: "high",
},
],
},
},
{
firebaseMessaging: messaging(),
topics: ["marketing"],
}
);This managed setup does the app-side work needed for dashboard-driven Sirrus campaigns:
- Initializes analytics and sessions
- Requests notification permission when configured
- Registers FCM tokens with Sirrus
- Processes the initial notification that opened the app
- Tracks Sirrus notification receives, opens, and action clicks
- Shows Sirrus foreground notifications through the native presenter
- Evaluates in-app overlays on app open and foreground
The Sirrus dashboard or backend is still responsible for creating campaigns and sending test notifications. The SDK is the app-side runtime that receives, displays, and tracks those campaigns.
Platform Notification Handling
The SDK includes native notification handling for both Android and iOS.
Android:
- Registers native notification channels from SDK config
- Requests Android 13+ notification permission when configured
- Includes a Sirrus FCM service for Sirrus-marked data messages
- Parses Sirrus dashboard payloads
- Shows foreground and background Sirrus notifications through the SDK renderer
- Tracks received, opened, and action-click events when the React Native bridge is available
- Stores pending notification interactions until the JS SDK starts
iOS:
- Requests notification permission when configured
- Registers notification categories and action buttons from SDK config
- Installs a
UNUserNotificationCenterDelegatethrough the native module - Parses Sirrus APNs payloads, including standard
aps.alertcontent - Shows foreground Sirrus notifications
- Tracks received, opened, and action-click events when the React Native bridge is available
- Stores pending notification interactions until the JS SDK starts
The host app still owns platform credentials and capabilities:
- Android Firebase project setup and
google-services.json - iOS APNs capability, entitlements, and
GoogleService-Info.plistif Firebase is used - iOS Notification Service Extension target for rich media attachments in background or killed state
If the Android app already has its own FirebaseMessagingService, keep that service and delegate incoming messages to SirrusPushMessagingHandler. The handler returns true only for Sirrus-owned payloads, so existing product notifications can continue through the app's current flow.
Dashboard Payload Contract
Your Sirrus dashboard or backend should send Sirrus-marked payloads. The SDK uses these markers to decide which notifications belong to Sirrus and should be displayed/tracked by this package.
For backend/dashboard code, the SDK exports helpers that produce the app-side payload shape:
import { buildSirrusPushDataPayload } from "sirrus-react-native-sdk";
const data = buildSirrusPushDataPayload({
campaignId: "cmp_123",
templateId: "tpl_456",
messageId: "msg_789",
title: "Festival Offer",
body: "Tap to view the offer",
imageUrl: "https://cdn.example.com/offers/festival.jpg",
deeplinkUrl: "myapp://offers/festival",
channelId: "sirrus-marketing",
actions: [
{
id: "open_offer",
title: "Open",
deeplinkUrl: "myapp://offers/festival",
foreground: true,
},
],
});The returned data object is designed for FCM data payloads. It includes markers such as source: "sirrus", sdk_source: "sirrus", and sirrus_campaign_id.
Example FCM HTTP v1 message shape:
{
"message": {
"token": "DEVICE_FCM_TOKEN",
"data": {
"source": "sirrus",
"sdk_source": "sirrus",
"sirrus_campaign_id": "cmp_123",
"sirrus_template_id": "tpl_456",
"sirrus_message_id": "msg_789",
"title": "Festival Offer",
"body": "Tap to view the offer",
"sirrus_image_url": "https://cdn.example.com/offers/festival.jpg",
"sirrus_deeplink_url": "myapp://offers/festival",
"sirrus_channel_id": "sirrus-marketing"
}
}
}For in-app overlays, your overlays API should return OverlayDefinition objects from the overlays evaluation endpoint. The SDK renders them through SirrusSdkRoot.
{
"overlays": [
{
"id": "overlay_123",
"title": "Festival Offer",
"message": "Unlock your offer today",
"htmlContent": "<div><h1>Festival Offer</h1><p>Tap below to continue.</p></div>",
"priority": 10,
"actions": [
{
"label": "Open Offer",
"action": "deep_link",
"deepLinkUrl": "myapp://offers/festival"
}
]
}
]
}Analytics
Track events, screens, and user identity.
await sirrusReactNativeSDK.track("product_viewed", {
productId: "p_123",
source: "home_feed",
});
await sirrusReactNativeSDK.screen("ProductDetails", {
productId: "p_123",
});
await sirrusReactNativeSDK.identify("user_456");Events are queued and batched automatically. Use persistent storage in production so visitor IDs, installation IDs, and queued events survive app restarts.
Push Notifications
Sirrus can register device tokens, track push lifecycle events, classify Sirrus-owned push payloads, show foreground notifications, and handle notification opens and action buttons.
The host app is still responsible for app-specific push setup:
- Firebase or APNs project configuration
google-services.jsonandGoogleService-Info.plist- iOS push capabilities and entitlements
- Android notification permissions and app manifest setup
- The push transport library, such as
@react-native-firebase/messaging
Register a Push Token
await sirrusReactNativeSDK.registerPushToken({
token,
provider: "fcm",
topics: ["marketing", "transactional"],
});Use provider: "apns" for APNs tokens.
Firebase Messaging Bridge
If your app uses @react-native-firebase/messaging, use the built-in bridge to register tokens and process receive/open events.
Most apps should use initSirrusManagedSdk above. Use bindFirebaseMessaging directly only when you want to manually control the push integration lifecycle.
import AsyncStorage from "@react-native-async-storage/async-storage";
import messaging from "@react-native-firebase/messaging";
import {
bindFirebaseMessaging,
createAsyncStorageAdapter,
sirrusReactNativeSDK,
} from "sirrus-react-native-sdk";
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
storage: createAsyncStorageAdapter(AsyncStorage),
notificationUI: {
handlingMode: "sirrus-only",
showForegroundNotifications: true,
useNativePresenter: true,
requestPermissionOnInit: true,
defaultAndroidChannelId: "sirrus-marketing",
androidChannels: [
{
id: "sirrus-marketing",
name: "Sirrus Marketing",
importance: "high",
},
],
},
});
const firebaseBridge = bindFirebaseMessaging(
sirrusReactNativeSDK,
messaging(),
{
topics: ["marketing"],
onUnhandledNotificationReceived: async (message) => {
// Handle non-Sirrus notifications in your existing app flow.
},
onUnhandledNotificationOpened: async (message) => {
// Handle non-Sirrus notification opens in your existing app flow.
},
}
);
await firebaseBridge.syncToken();
await firebaseBridge.processInitialNotification();Sirrus Push Payload Markers
By default, handlingMode is sirrus-only. In this mode the SDK handles notifications that include Sirrus markers such as:
source: "sirrus"sdk_source: "sirrus"vendor: "sirrus"provider: "sirrus"sirrus_campaign_idsirrusCampaignIdsirrus_template_idsirrusTemplateId
Notifications without these markers are ignored by the SDK and can continue through your existing notification handlers.
Foreground Notification Display
When notificationUI.showForegroundNotifications is enabled, the SDK can show Sirrus notifications while the app is active.
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
storage: createAsyncStorageAdapter(AsyncStorage),
notificationUI: {
showForegroundNotifications: true,
useNativePresenter: true,
defaultAndroidChannelId: "sirrus-marketing",
androidChannels: [
{
id: "sirrus-marketing",
name: "Sirrus Marketing",
importance: "high",
},
],
iosCategories: [
{
id: "sirrus-offer",
actions: [
{
id: "open_offer",
title: "Open",
foreground: true,
},
],
},
],
},
});You can also pass a custom notificationUI.presenter if your app already has a native notification presentation layer.
Manual Push Tracking
If you do not use the Firebase bridge, pass push payloads to the SDK manually.
await sirrusReactNativeSDK.processNotificationReceived({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
imageUrl: remoteMessage.data?.imageUrl,
deeplinkUrl: remoteMessage.data?.sirrus_deeplink_url,
campaignId: remoteMessage.data?.sirrus_campaign_id,
messageId: remoteMessage.messageId,
provider: "fcm",
rawPayload: remoteMessage.data,
});
await sirrusReactNativeSDK.processNotificationOpened({
title: remoteMessage.notification?.title,
body: remoteMessage.notification?.body,
deeplinkUrl: remoteMessage.data?.sirrus_deeplink_url,
campaignId: remoteMessage.data?.sirrus_campaign_id,
messageId: remoteMessage.messageId,
provider: "fcm",
rawPayload: remoteMessage.data,
});Testing Real Push Delivery
Push delivery should be triggered from Sirrus backend/dashboard, Firebase Console, Firebase Admin SDK, or FCM HTTP v1 API. The mobile SDK does not send notifications from the app. It receives, classifies, displays, and tracks Sirrus-owned notifications after the platform delivers them.
For Firebase Console tests, target the real FCM token registered by the SDK and include Sirrus markers in custom data:
{
"source": "sirrus",
"sdk_source": "sirrus",
"sirrus_campaign_id": "cmp_test",
"sirrus_message_id": "msg_test",
"title": "Sirrus Test",
"body": "Rendered by the Sirrus SDK",
"sirrus_deeplink_url": "myapp://offers/test"
}Payloads without Sirrus markers are ignored by the SDK and should be handled by the product app's existing notification code.
Rich Push Setup
Foreground rich notifications can be shown by the SDK's native presenter. Background or killed-state rich media still depends on the host app's native push setup.
iOS Notification Service Extension
For iOS remote push media attachments, add a Notification Service Extension target to the host app.
This package includes a template:
templates/ios/NotificationServiceExtension/SirrusNotificationService.swifttemplates/ios/NotificationServiceExtension/README.md
The extension template supports media keys such as:
sirrus_attachment_urlsirrus_image_urlsirrus_gif_urlsirrus_video_urlimageUrlgifUrlvideoUrlmediaUrl
Your APNs payload must include mutable-content: 1 for the service extension to modify the notification.
Android Background Data-Only Service
The SDK includes SirrusFirebaseMessagingService, which handles Sirrus-marked FCM data messages and renders them through the SDK notification renderer.
If the host app already has a Firebase messaging service, remove the SDK's auto service with manifest merge and delegate to SirrusPushMessagingHandler:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application>
<service
android:name="ai.sirrus.reactnativesdk.SirrusFirebaseMessagingService"
tools:node="remove" />
<service
android:name=".ProductFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>import ai.sirrus.reactnativesdk.SirrusPushMessagingHandler
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class ProductFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
if (SirrusPushMessagingHandler.handleRemoteMessage(applicationContext, remoteMessage)) {
return
}
// Existing product-app notification handling continues here.
}
override fun onNewToken(token: String) {
SirrusPushMessagingHandler.handleNewToken(applicationContext, token, "fcm")
// Existing product-app token sync can continue here.
}
}This package also includes a template if a host app wants a custom service:
templates/android/FirebaseMessagingService/ProductFirebaseMessagingService.kttemplates/android/FirebaseMessagingService/README.md
The template delegates notification rendering to the SDK's Android notification renderer, so foreground and background Sirrus notification behavior stays consistent.
Deep Links
Handle direct deep links:
const initialUrl = await sirrusReactNativeSDK.getInitialDeepLinkUrl();
if (initialUrl) {
await sirrusReactNativeSDK.handleDeepLink(initialUrl, {
source: "app_launch",
});
}Resolve deferred deep links through the Sirrus backend:
const deferredLink = await sirrusReactNativeSDK.resolveDeferredDeepLink({
source: "install_campaign",
campaign: "summer-launch",
});
if (deferredLink?.url) {
await sirrusReactNativeSDK.openDeepLink(deferredLink.url);
}Subscribe to resolved links:
const unsubscribe = sirrusReactNativeSDK.subscribeToDeepLinks((payload) => {
if (payload.url) {
// Route inside your app.
}
});In-App Overlays
Mount SirrusSdkRoot once near the top of your app tree. The SDK will use it to render in-app overlays.
import React from "react";
import { SirrusSdkRoot } from "sirrus-react-native-sdk";
export const App = () => {
return (
<SirrusSdkRoot>
<YourNavigation />
</SirrusSdkRoot>
);
};Enable automatic overlay evaluation:
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
storage: createAsyncStorageAdapter(AsyncStorage),
overlayUI: {
autoShowOnAppOpen: true,
autoEvaluateOnForeground: true,
appOpenTrigger: "app_open",
},
});Evaluate overlays manually after important events:
await sirrusReactNativeSDK.evaluateOverlays("screen_focus", "screen_view", {
screenName: "Home",
});HTML Overlays
Overlay payloads can include htmlContent. The SDK renders HTML with react-native-webview.
Example overlay response:
{
"id": "offer_001",
"title": "Festival Offer",
"htmlContent": "<div style='padding:16px'><h1>Big Sale</h1><p>Tap below to continue.</p></div>",
"actions": [
{
"label": "Open Offer",
"action": "deep_link",
"deepLinkUrl": "myapp://offers/festival"
}
]
}For custom HTML rendering, pass overlayUI.renderHtmlContent during SDK initialization.
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
storage: createAsyncStorageAdapter(AsyncStorage),
overlayUI: {
renderHtmlContent: (overlay) => {
return <YourHtmlRenderer html={overlay.htmlContent ?? ""} />;
},
},
});PII Encryption
If your React Native runtime does not expose WebCrypto, pass a custom piiEncryptor.
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
storage: createAsyncStorageAdapter(AsyncStorage),
piiEncryptor: async (publicKey, payload) => {
return encryptedBase64;
},
});Configuration Reference
await sirrusReactNativeSDK.init({
apiKey: "your-api-key",
ssoUrl: "https://auth.example.com",
debug: false,
storage: createAsyncStorageAdapter(AsyncStorage),
appInfo: {
name: "My App",
version: "1.0.0",
buildNumber: "100",
bundleId: "com.example.app",
environment: "production",
},
endpoints: {
pushRegister: "/v1/sdk/push/register",
deepLinkResolve: "/v1/sdk/deeplinks/resolve",
overlaysEvaluate: "/v1/sdk/overlays/evaluate",
},
notificationUI: {
handlingMode: "sirrus-only",
showForegroundNotifications: true,
useNativePresenter: true,
requestPermissionOnInit: true,
},
overlayUI: {
autoShowOnAppOpen: true,
autoEvaluateOnForeground: true,
htmlWebViewEnabled: true,
},
});Notes
- Persistent storage is recommended in production.
react-native-webviewis required for HTML overlays.- The SDK can register tokens and track notification events, but Firebase/APNs credentials and app-specific native files belong to the host app.
- Rich remote push media on iOS requires a Notification Service Extension in the host app.
- Android background data-only notification rendering uses the SDK's included service unless the host app already has its own service; existing services should delegate Sirrus payloads to
SirrusPushMessagingHandler. - Endpoint paths can be overridden through
init({ endpoints }).
