React Native SDK

react-native-notify-sphere on npm. Push notifications, delivery tracking, campaign attribution, and user tags for Android and iOS, built on Firebase Cloud Messaging and Notifee.

Prerequisites#

  • React Native 0.70+
  • A Firebase project with Cloud Messaging enabled
  • A notifySphere account with an App ID and API Token. Grab these from your dashboard after creating an app.

Install#

npm install react-native-notify-sphere

# Peer dependencies (native, required in your app)
npm install @react-native-firebase/app @react-native-firebase/messaging
npm install @notifee/react-native
npm install @react-native-async-storage/async-storage@^1.23.1
npm install react-native-device-info react-native-install-referrer

cd ios && pod install && cd ..

The SDK declares these peer dependencies: @react-native-firebase/app and @react-native-firebase/messaging (^22.2.1), @notifee/react-native (^9.1.8), @react-native-async-storage/async-storage (^1.23.1), react-native-device-info (>=10.0.0), and react-native-install-referrer (>=1.0.0).

Android setup#

  1. Add google-services.json

    Download google-services.json from the Firebase Console and place it at android/app/google-services.json.

  2. Apply the Google Services plugin

    Add the Google Services classpath in android/build.gradle and apply the plugin as the last line of android/app/build.gradle.

  3. Update AndroidManifest.xml

    Add the POST_NOTIFICATIONS, INTERNET, and VIBRATE permissions, plus the default-icon and default-channel meta-data entries.

  4. Add a notification icon

    Drop an icon at android/app/src/main/res/drawable/ic_stat_onesignal_default.png. Android silently drops notifications with a missing small icon.

iOS setup#

  1. Add GoogleService-Info.plist

    Add GoogleService-Info.plist from the Firebase Console to your Xcode project (all targets, "Copy items if needed").

  2. Enable capabilities

    In Xcode → Signing & Capabilities, add Push Notifications and Background Modes → Remote notifications.

  3. Configure AppDelegate

    Configure Firebase and the notification center delegate in AppDelegate.mm.

Usage#

1. Register the background handler in index.js#

Register the background handler synchronously, before AppRegistry.registerComponent(). Don't wrap it in a promise or timeout. Otherwise notifications delivered while the app is backgrounded or killed get dropped, because no handler exists yet when the headless JS task starts.

index.js
import { AppRegistry } from 'react-native';
import App from './src/App';
import { name as appName } from './app.json';
import NotifySphere from 'react-native-notify-sphere';
import { APP_ID, API_TOKEN } from './src/App';

// Must run synchronously, before registerComponent().
NotifySphere.setBackgroundHandler({
  appId: APP_ID,
  apiKey: API_TOKEN,
});

AppRegistry.registerComponent(appName, () => App);

2. Initialize in App.tsx#

Initialize on mount and listen for notification events.

App.tsx
import { useEffect } from 'react';
import { Platform } from 'react-native';
import NotifySphere from 'react-native-notify-sphere';

export const APP_ID = 'your-notifysphere-app-id';
export const API_TOKEN = 'your-api-token';
const PUSH_TYPE = Platform.OS === 'android' ? 'AndroidPush' : 'IOSPush';

export default function App() {
  useEffect(() => {
    const init = async () => {
      const subscriptionId = await NotifySphere.initialize({
        applicationUserId: 123,
        type: PUSH_TYPE,
        appId: APP_ID,
        apiKey: API_TOKEN,
        name: 'John Doe',
        email: 'john@example.com',
        phone: '9876543210',
        tags: { userType: 'customer' },
        debug: __DEV__,
      });

      await NotifySphere.updateTags({
        applicationUserId: 123,
        type: PUSH_TYPE,
        tags: { lastLogin: new Date().toISOString() },
      });
    };
    init();

    NotifySphere.onNotification((notification, type) => {
      // type: 'received' | 'press' | 'opened' | 'initial'
    });

    return () => NotifySphere.destroy();
  }, []);

  // ...render your app
}

API reference#

initialize(config)#

Registers the device and sets up listeners. Returns Promise<string | undefined>, the server-assigned subscription_id.

FieldTypeRequiredDescription
applicationUserIdnumberYesYour internal user ID for this device
typestringYes'AndroidPush' or 'IOSPush'
appIdstringYesYour notifySphere App ID
apiKeystringYesBearer token from your dashboard
name / email / phonestringNoUser profile fields (phone as string, to preserve leading zeros)
tagsRecord<string,string>NoCustom segmentation tags
debugbooleanNoVerbose console logs (default false)

onNotification(callback)#

Registers a callback for all notification events: received, press, opened, initial.

postEvent(params)#

Attributes an in-app conversion (booking, purchase, sign-up) back to the campaign that drove the install or open. Requires initialize() to have run at least once.

javascript
await NotifySphere.postEvent({
  event: 'booking',
  nsClick: 'abc123', // optional, from a campaign deep-link
  data: { revenue: 2500, order_id: 'ORD123' },
});

updateTags(params)#

Updates user tags without re-registering the device.

setBackgroundHandler(config?)#

Registers the Firebase/Notifee background and terminated-state handler. Must be called synchronously in index.js. Pass appId and apiKey here. They aren't available in a killed-state launch because initialize() hasn't run yet.

destroy()#

Unsubscribes all listeners and resets internal state. Call on logout.

FCM payload format#

Send mixed payloads: a top-level notification block (so the OS auto-displays in background and killed state) plus a data block (for delivery tracking and routing).

json
{
  "notification": { "title": "Hello!", "body": "You have a new message." },
  "data": {
    "notification_id": "uuid-here",
    "sound": "default",
    "imageUrl": "https://example.com/image.jpg",
    "channelId": "channel_default"
  },
  "android": { "priority": "high" }
}

Troubleshooting#

Delivery receipt works in foreground but not background or killed#

Check two things: your FCM payload must include the top-level notification block (see above), and setBackgroundHandler() must run synchronously at the very top of index.js, never inside a promise or setTimeout.

401 Unauthorized#

Pass apiKey in both initialize() and setBackgroundHandler().

More fixes are in Troubleshooting.

Stuck or something unclear? Contact us and we'll help.