React Native
Official @daertech/pushtifly-react-native SDK on top of @react-native-firebase/messaging, or integration via REST.
The official SDK @daertech/pushtifly-react-native works with React Native 0.76 or later, with the new architecture. It builds on @react-native-firebase/messaging and adds:
- device registration, with an offline queue;
- the Android channel;
- notifications while the app is open on Android, with image and buttons, without Notifee;
- reported opens and clicks, including the tapped button on iOS, which RNFB doesn't report;
- users, tags and topics.
The token is FCM on both platforms. You need:
- the Firebase credential in Pushtifly;
- the APNs key inside Firebase (iOS via FCM).
Using Expo? See Expo.
Installation
npm install @daertech/pushtifly-react-native @react-native-firebase/app @react-native-firebase/messaging
cd ios && pod install
- Android: add
google-services.jsoninandroid/app/, as RNFB explains. - iOS: add
GoogleService-Info.plist, enable Push Notifications and Background Modes > Remote notifications. RNFB requiresuse_frameworks! :linkage => :staticin thePodfile.
Usage
import { Pushtifly } from '@daertech/pushtifly-react-native';
// Outside components, once at startup
Pushtifly.init({
appKey: 'pk_live_YOUR_PUBLIC_KEY', // PUBLIC key only
androidChannel: { id: 'general', name: 'General notices' },
});
Pushtifly.onNotificationOpened((n) => {
// n.deepLink, n.actionId (tapped button), n.data (your data)
if (n.deepLink) Linking.openURL(n.deepLink);
});
// Ask for permission once the user understands what it's for (on Android 13+ it asks for POST_NOTIFICATIONS)
const state = await Pushtifly.requestPermission();
Pushtifly.identify('customer-123'); // on sign-in
Pushtifly.setTags({ plan: 'gold' });
Pushtifly.subscribe('offers');
Pushtifly.logout(); // on sign-out
You can subscribe to onNotificationOpened before init. If the app was opened from a notification, the open is still delivered.
Calls don't wait for the network: they're stored in a persistent queue. They're sent when there's a token and a connection, and retried when the user comes back to the app.
init options
| Option | Default | Description |
|---|---|---|
appKey |
— | Public key pk_live_… or pk_test_…. The SDK rejects secret keys. |
appId |
— | Only if the key isn't restricted to one app. |
autoRegister |
false |
Ask for permission at launch. |
foregroundDisplay |
true |
Show notifications while the app is open. |
androidChannel |
— | Channel the SDK creates; it must match the app's default channel in Pushtifly. |
iosNotificationServiceExtension |
false |
The app includes the extension (see below). |
debug |
false |
Logs in the console. |
On iOS, notifications while the app is open are shown by the system according to messaging_ios_foreground_presentation_options in RNFB's firebase.json.
Test device
await Pushtifly.pairTestDevice('483920'); // 6-digit code from the Devices section
Images and buttons on iOS
- In Xcode: File > New > Target > Notification Service Extension.
- Replace its
NotificationService.swiftwithnode_modules/@daertech/pushtifly-react-native/ios/NotificationService/NotificationService.swift. - Start the SDK with
iosNotificationServiceExtension: true.
With Expo, the SDK's plugin does these steps for you.
Image carousel
A send with a carousel (2 to 5 images) looks like this with the SDK; without these steps, the phone shows only the first image.
Android
The carousel arrives as a data message and the SDK draws it, even when the app is closed. Register the background handler in index.js (outside your components) and turn on androidCarousel:
import { getMessaging, setBackgroundMessageHandler } from '@react-native-firebase/messaging';
import { Pushtifly } from '@daertech/pushtifly-react-native';
setBackgroundMessageHandler(getMessaging(), async (message) => {
await Pushtifly.handleBackgroundMessage(message);
});
Pushtifly.init({ appKey: 'pk_live_…', androidCarousel: true });
iOS
The carousel needs, besides the Service Extension, a Notification Content Extension:
- In Xcode: File > New > Target > Notification Content Extension.
- Replace its
NotificationViewController.swiftandInfo.plistwith the package's:node_modules/@daertech/pushtifly-react-native/ios/NotificationContent/. Delete the generatedMainInterface.storyboard. - Also use the updated Service Extension template (
node_modules/@daertech/pushtifly-react-native/ios/NotificationService/): it downloads all the images. - Start the SDK with
iosNotificationServiceExtension: trueandiosNotificationContentExtension: true.
On long press the carousel appears; the View button opens the app with the visible image's link.
Firebase Installation ID
If you turn on Firebase's Installation ID mode in the app, the SDK detects it and registers the FID instead of the registration token, with no changes to your code. See Firebase Installation ID.
What the SDK reports
| Event | When |
|---|---|
received |
The notification arrives while the app is open. |
opened |
The user taps the notification. |
clicked |
The user taps a button (includes actionId). |
permission_granted / permission_denied |
The permission changes. |
Without the SDK (REST)
import { getMessaging, getToken } from '@react-native-firebase/messaging';
const token = await getToken(getMessaging());
await fetch('https://api.pushtifly.com/v1/devices', {
method: 'POST',
headers: { Authorization: 'Bearer pk_live_YOUR_PUBLIC_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ token, platform: Platform.OS, provider: 'fcm', framework: 'react_native' }),
});
The send's id arrives in data._phid and the link in data.deepLink. Report it to /v1/events on open.