npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sirrus-react-native-sdk

v0.1.80

Published

Lightweight React Native SDK for Sirrus event ingestion and push notification handling.

Readme

Sirrus React Native SDK

Sirrus React Native SDK adds Sirrus event ingestion and Sirrus push notification handling to a React Native app.

It is designed to live alongside Firebase, MoEngage, Notifee, or an app's own notification code. The SDK handles only notifications that are explicitly marked for Martech handling.

What The SDK Handles

  • Initializes with a Sirrus SDK API key.
  • Calls Sirrus SSO init internally and uses the returned org/project IDs, ingestion URL, notification URL, JWT, and PII public key.
  • Creates and persists visitor, installation, and session IDs using storage provided by the host app.
  • Tracks custom events and screen views through the Sirrus ingestion API.
  • Registers the app's Firebase token as a userToken event after login.
  • Receives and displays Sirrus push notifications.
  • Supports rich push images and dynamic action buttons.
  • Sends Sirrus push receive/open/action analytics to the notificationUrl returned by SSO init.

What The Host App Owns

The SDK does not replace the app's Firebase/APNs setup.

The host app must:

  • Configure Firebase and APNs.
  • Add google-services.json / GoogleService-Info.plist.
  • Request notification permission.
  • Get the Firebase token.
  • Pass the token to registerToken after the user is logged in.
  • Keep existing handling for notifications that are not owned by this SDK.
  • Add the required native extension/service setup for rich push where needed.

Installation

yarn add sirrus-react-native-sdk

or:

npm install sirrus-react-native-sdk

For local tarball testing:

yarn add file:./sirrus-react-native-sdk-<version>.tgz

After installing, rebuild the native app. For iOS, run pods:

cd ios
pod install

Quick Start

Initialize the SDK once when the app starts. Pass persistent storage from your app, such as MMKV or AsyncStorage.

import {
  initSirrusManagedSdk,
  sirrusReactNativeSDK,
} from "sirrus-react-native-sdk";

const sirrusStorage = {
  getItem: async (key: string) => mmkv.getString(key) ?? null,
  setItem: async (key: string, value: string) => {
    mmkv.set(key, value);
  },
  removeItem: async (key: string) => {
    mmkv.remove(key);
  },
};

await initSirrusManagedSdk(
  sirrusReactNativeSDK,
  {
    apiKey: "SIRRUS_SDK_API_KEY",
    storage: sirrusStorage,
    debug: __DEV__,
    appInfo: {
      name: "Your App",
      version: "1.0.0",
      buildNumber: "100",
      bundleId: "com.example.app",
      environment: "production",
    },
  },
  {
    firebaseMessaging: {
      onMessage: (listener) => messaging().onMessage(listener),
      onNotificationOpenedApp: (listener) =>
        messaging().onNotificationOpenedApp(listener),
      getInitialNotification: () => messaging().getInitialNotification(),
    },
  },
);

The default notification setup is usually enough:

  • The SDK handles only Martech-marked notifications.
  • Android uses a high-importance channel named Sirrus Marketing with ID sirrus-marketing.
  • iOS foreground Sirrus notifications use the native iOS notification path.
  • Android data-only Martech messages are rendered by the SDK native service when the SDK service is the active FCM receiver.

Use notificationUI only when your app needs custom Android channels, custom iOS categories, a custom presenter, or custom source matching.

For Android, product apps can pass channel IDs during init. The SDK creates those channels on the device, and incoming Martech notifications can target them with data.android_channel_id.

await initSirrusManagedSdk(sirrusReactNativeSDK, {
  apiKey: "SIRRUS_SDK_API_KEY",
  storage: sirrusStorage,
  notificationUI: {
    androidChannelIds: ["Promotion", "Updates"],
  },
});

Register The User Token

Call registerToken after login, when your app has both the Firebase token and the logged-in user details.

token, userId, and phone are required. userId and phone are sent unencrypted because the backend needs them as plain root fields.

await sirrusReactNativeSDK.registerToken({
  token: fcmToken,
  userId: loggedInUserId,
  phone: loggedInPhoneNumber,
});

This sends an immediate ingestion request using the normal Sirrus batch envelope with a single userToken event.

The SDK also stores userId and phone in the provided storage and includes them in later event payloads.

You can update or clear user details explicitly:

await sirrusReactNativeSDK.setUserInfo({
  userId: loggedInUserId,
  phone: loggedInPhoneNumber,
});

await sirrusReactNativeSDK.setUserInfo(null);

Track Events

await sirrusReactNativeSDK.track("booking_started", {
  entryPoint: "home",
});

await sirrusReactNativeSDK.screen("Home", {
  role: "customer",
});

Events are queued, persisted, batched, retried, and flushed through the ingestion URL returned by SSO init.

Each event includes device context and context.device.sdkVersion so the backend can identify which SDK version produced the payload.

Optional PII Data

Use setPii only for extra PII values that should be encrypted before being sent to Sirrus.

sirrusReactNativeSDK.setPii({
  email: "[email protected]",
  name: "Example User",
});

sirrusReactNativeSDK.setPii(null);

The SDK encrypts this object with the PII public key returned by SSO init and sends it as the root pii field on ingestion batches.

If the React Native runtime does not provide WebCrypto, pass your own encryptor:

await sirrusReactNativeSDK.init({
  apiKey: "SIRRUS_SDK_API_KEY",
  storage: sirrusStorage,
  piiEncryptor: async (publicKey, payload) => {
    return encryptWithYourNativeCrypto(publicKey, payload);
  },
});

Notification Ownership

The backend must mark SDK-owned notifications with data.source set to martech.

Notifications without the Martech marker are ignored by the SDK, so Firebase, MoEngage, Notifee, or your app's existing notification code can continue to handle them.

Notification Analytics

SSO init returns two important URLs:

  • ingestionUrl for normal analytics events and token registration.
  • notificationUrl for Sirrus push lifecycle events.

The SDK sends notification analytics for:

  • received when a Sirrus notification is received.
  • click when the notification body is opened.
  • reply when an action button is clicked.

For action buttons, the SDK includes the clicked action value and label when available. Campaign metadata is forwarded only when it is present in the notification data. The SDK does not invent campaign metadata.

All SDK API requests include these headers:

client_id: TCG-WEB-APP
application_platform: TCG-DXP-APP

Android Setup

If Your App Does Not Have A FirebaseMessagingService

The SDK includes SirrusFirebaseMessagingService in its Android library manifest. If your app does not declare another FirebaseMessagingService, Android can merge and use the SDK service automatically.

Your app still needs:

  • Firebase configured in the app.
  • google-services.json in the Android app.
  • Notification permission requested by the app on Android 13+.
  • A valid notification channel ID in the notification payload.

If Your App Already Has A FirebaseMessagingService

Use one deterministic FCM receiver. In that receiver, let the SDK check the message first. If the SDK handles it, return immediately. Otherwise continue with your existing notification logic.

import ai.sirrus.reactnativesdk.SirrusPushMessagingHandler
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class AppFirebaseMessagingService : FirebaseMessagingService() {
  override fun onMessageReceived(remoteMessage: RemoteMessage) {
    if (SirrusPushMessagingHandler.handleRemoteMessage(applicationContext, remoteMessage)) {
      return
    }

    // Existing non-Sirrus handling, such as MoEngage, Notifee, or app logic.
  }

  override fun onNewToken(token: String) {
    SirrusPushMessagingHandler.handleNewToken(applicationContext, token, "fcm")

    // Existing product token handling.
  }
}

Declare your app service and remove the SDK auto service from the final merged manifest:

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools">

  <application>
    <service
      android:name=".AppFirebaseMessagingService"
      android:exported="false">
      <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
      </intent-filter>
    </service>

    <service
      android:name="ai.sirrus.reactnativesdk.SirrusFirebaseMessagingService"
      tools:node="remove" />
  </application>
</manifest>

Android Payload Rules

For Android rich media and action buttons, the backend should send SDK-owned pushes as data-only FCM messages.

Do not include the top-level FCM notification object for Android SDK-owned pushes. Do not include android.notification. If Firebase renders the notification itself, the SDK cannot attach native action buttons.

Coordinate with the backend team to include data.source = "martech", a unique message ID, title/body, optional raw image URL, optional action list, and a valid Android channel ID.

Android Notification Channels

Android will drop or hide notifications that target a channel that does not exist on the device.

By default, the SDK creates:

channel id: sirrus-marketing
channel name: Sirrus Marketing
importance: high

If your backend sends a different android_channel_id, create that channel during SDK init.

For simple channels, pass only the IDs:

await sirrusReactNativeSDK.init({
  apiKey: "SIRRUS_SDK_API_KEY",
  storage: sirrusStorage,
  notificationUI: {
    androidChannelIds: ["Promotion", "Updates"],
  },
});

The android_channel_id value in the notification data must match the channel ID exactly:

android_channel_id: Promotion

If a user disables that channel in Android notification settings, Android will block notifications for that channel. The SDK does not override user notification settings.

For custom names or importance, pass full channel objects:

await sirrusReactNativeSDK.init({
  apiKey: "SIRRUS_SDK_API_KEY",
  storage: sirrusStorage,
  notificationUI: {
    defaultAndroidChannelId: "marketing",
    androidChannels: [
      {
        id: "marketing",
        name: "Marketing",
        importance: "high",
      },
    ],
  },
});

Use stable channel IDs. Android does not allow an app to change a channel's importance after the channel has been created on the device.

iOS Setup

The main iOS app must have:

  • Firebase/APNs configured.
  • GoogleService-Info.plist added to the app target.
  • Push Notifications capability enabled.
  • Notification permission requested by the app.
  • Sirrus initialized from React Native.
  • Firebase token passed to registerToken after login.

iOS Rich Push Extension

iOS requires a Notification Service Extension for rich media and dynamic action buttons in background or killed state.

Create one extension target per app bundle ID. For example:

Main app bundle ID: com.example.app
Extension bundle ID: com.example.app.SirrusNotificationService
Extension target: SirrusNotificationService

If your app has separate Dev, Staging, and Production bundle IDs, each app target needs its own embedded extension target:

com.example.app.dev.SirrusNotificationService
com.example.app.staging.SirrusNotificationService
com.example.app.SirrusNotificationService

Recommended Extension Source Setup

Add the SDK notification-service source file to the extension target's Compile Sources:

node_modules/sirrus-react-native-sdk/ios/NotificationService/SirrusNotificationServiceExtension.swift

Then keep the extension's NotificationService.swift small:

import UserNotifications

final class NotificationService: SirrusNotificationServiceExtension {}

This method keeps the extension independent from React Native and avoids linking the full SDK framework into the extension.

When using this source-file method, do not also add a separate Podfile target for sirrus-react-native-sdk/NotificationService; the extension compiles the notification-service source directly.

The extension Info.plist must point to the service class:

<key>NSExtension</key>
<dict>
  <key>NSExtensionPointIdentifier</key>
  <string>com.apple.usernotifications.service</string>
  <key>NSExtensionPrincipalClass</key>
  <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
</dict>

Make sure the extension target is embedded in the main app target under Embed App Extensions and is signed with the correct team/profile.

iOS Notification Tap Forwarding

If your app owns UNUserNotificationCenterDelegate, forward notification taps to Sirrus before your other push handling. This lets Sirrus send click/action analytics even when a notification opens the app from killed state.

import SirrusReactNativeSdk
import UserNotifications

func application(
  _ application: UIApplication,
  didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
  UNUserNotificationCenter.current().delegate = self
  _ = SirrusNotificationResponseBridge.handleLaunchOptions(launchOptions)
  return true
}

func userNotificationCenter(
  _ center: UNUserNotificationCenter,
  didReceive response: UNNotificationResponse,
  withCompletionHandler completionHandler: @escaping () -> Void
) {
  if SirrusNotificationResponseBridge.handleNotificationResponse(response) {
    completionHandler()
    return
  }

  // Existing non-Sirrus notification handling.
  completionHandler()
}

iOS Payload Rules

iOS rich notifications need:

  • A visible APNs alert.
  • mutableContent: true.
  • Image URL in apns.fcmOptions.imageUrl.
  • The same image URL in data.imageUrl.
  • data.actions as a JSON string when action buttons are needed.

Use raw image URLs. Do not send Markdown link strings like [https://...](https://...).

Coordinate with the backend team to include data.source = "martech", a unique message ID, a visible APNs alert, mutableContent: true, optional raw image URL, and optional action list.

Notification Interaction Listener

Use this when the product app wants to navigate or react after a Sirrus notification body/action click.

const unsubscribe = sirrusReactNativeSDK.onNotificationInteraction((event) => {
  const data = {
    ...(event.payload.rawPayload ?? {}),
    ...(event.payload.data ?? {}),
  };

  if (event.type === "opened") {
    // User tapped the notification body.
  }

  if (event.type === "action_pressed") {
    // User tapped an action button.
    console.log(event.actionId, event.action);
  }
});

If a notification opens the app before React Native subscribes, the SDK stores the interaction briefly and delivers it to the first listener.

React Root Wrapper

SirrusSdkRoot is available as a compatibility wrapper. It does not render overlays.

import { SirrusSdkRoot } from "sirrus-react-native-sdk";

export const App = () => {
  return (
    <SirrusSdkRoot>
      <Navigation />
    </SirrusSdkRoot>
  );
};

Using the wrapper is optional unless your app already relies on it.

Setup Helper

The package includes a helper that can inspect common native setup issues.

npx sirrus-react-native-sdk setup

Use --apply only after reviewing what it will change:

npx sirrus-react-native-sdk setup --apply

Native projects differ a lot, especially when Firebase, MoEngage, Notifee, or multiple app targets are present. Always review generated native changes before committing.

Useful APIs

sirrusReactNativeSDK.init(config);

sirrusReactNativeSDK.track(eventName, properties);
sirrusReactNativeSDK.screen(screenName, properties);

sirrusReactNativeSDK.registerToken({
  token,
  userId,
  phone,
});

sirrusReactNativeSDK.setUserInfo({ userId, phone });
sirrusReactNativeSDK.setUserInfo(null);

sirrusReactNativeSDK.setPii({ email, name });
sirrusReactNativeSDK.setPii(null);

sirrusReactNativeSDK.onNotificationInteraction((event) => {
  // Handle Sirrus notification body/action clicks.
});

sirrusReactNativeSDK.flush();
sirrusReactNativeSDK.shutdown();

Troubleshooting

Foreground notification received but not displayed:

  • Confirm the payload has source: "martech".
  • Confirm the app has notification permission.
  • On Android, confirm the message is data-only.
  • On iOS, confirm the notification delegate forwards Sirrus notifications or the SDK delegate is active.

Android image or action buttons missing:

  • Do not send a top-level notification object for Android SDK-owned pushes.
  • Do not send android.notification.
  • Confirm android_channel_id exists on the device.
  • Confirm data.actions is a JSON string.

iOS image or action buttons missing:

  • Confirm the Notification Service Extension target is embedded in the app target you are running.
  • Confirm the extension bundle ID is prefixed by the main app bundle ID.
  • Confirm mutableContent: true is present.
  • Confirm apns.fcmOptions.imageUrl and data.imageUrl are raw URLs.
  • Use a direct .jpg or .png URL for the simplest rich-image test.

Other notifications affected:

  • Confirm the SDK only receives messages with source: "martech".
  • If your app has its own FirebaseMessagingService, call SirrusPushMessagingHandler.handleRemoteMessage(...) first and continue existing logic only when it returns false.

Release Checklist

Before publishing a new SDK version:

  • Run pnpm lint.
  • Run pnpm build.
  • Run pnpm test.
  • Run git diff --check.
  • Test Android foreground, background, and killed-state Sirrus notifications.
  • Test iOS foreground, background, and killed-state Sirrus notifications.
  • Verify image rendering and action buttons.
  • Verify notification receive/open/action analytics.
  • Verify non-Sirrus notifications still work.