Ionic + Capacitor
Official @daertech/pushtifly-capacitor SDK on top of @capacitor/push-notifications, or integration via REST.
The official SDK @daertech/pushtifly-capacitor (Capacitor 8 or later) builds on @capacitor/push-notifications and adds what that plugin doesn't do:
- device registration with an offline queue;
- iOS environment detection (sandbox or production);
- the Android channel;
- notifications while the app is open, with buttons;
- reported opens and clicks;
- users, tags and topics.
Installation
npm install @daertech/pushtifly-capacitor @capacitor/push-notifications @capacitor/local-notifications
npx cap sync
@capacitor/local-notifications is optional: without it, notifications that arrive on Android while the app is open aren't shown, although they're still reported and reach onNotificationReceived.
- Android: copy
google-services.jsonintoandroid/app/. - iOS: enable Push Notifications and Background Modes > Remote notifications in Xcode.
Show the notification while the app is open on iOS from capacitor.config:
{ "plugins": { "PushNotifications": { "presentationOptions": ["badge", "sound", "alert"] } } }
Usage
import { Pushtifly } from '@daertech/pushtifly-capacitor';
await Pushtifly.init({
appKey: 'pk_live_YOUR_PUBLIC_KEY', // PUBLIC key only
environment: 'auto', // iOS: detected by the SDK
androidChannel: { id: 'general', name: 'General notices' },
});
// Ask for permission once the user understands what it's for (not on app launch)
const state = await Pushtifly.requestPermission(); // 'granted' | 'denied' | ...
Pushtifly.identify('customer-123'); // on sign-in
Pushtifly.setTags({ plan: 'gold', city: 'NYC' });
Pushtifly.subscribe('offers');
Pushtifly.onNotificationOpened((n) => {
// n.deepLink, n.actionId (tapped button), n.data (your data)
if (n.deepLink) router.navigateByUrl(new URL(n.deepLink).pathname);
});
Pushtifly.logout(); // on sign-out
Register onNotificationOpened when the app starts: if the app was opened from a notification, the SDK keeps that open and delivers it as soon as you subscribe.
Calls (identify, setTags, subscribe) don't wait for the network: they're stored in a persistent queue. They're sent as soon as there's a token and a connection, and retried with increasing backoff.
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. |
environment |
auto |
sandbox or production to force it on iOS. |
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); enables images and buttons on iOS. |
apiUrl |
https://api.pushtifly.com |
Only for testing. |
debug |
false |
Logs in the console. |
Test device
In Devices, the panel shows a 6-digit pairing code; in the app:
await Pushtifly.pairTestDevice('483920');
Images and buttons on iOS
iOS only shows media and buttons if the app includes a Notification Service Extension. The SDK ships one ready to use:
- In Xcode (
ios/App): File > New > Target > Notification Service Extension. - Replace the generated
NotificationService.swiftwithnode_modules/@daertech/pushtifly-capacitor/ios/NotificationService/NotificationService.swift. - Start the SDK with
iosNotificationServiceExtension: true.
On Android, images and buttons work with no extra steps.
Image carousel
On Android a send with a carousel shows as a notification with the first image (no extra steps). On iOS it can be shown in full:
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-capacitor/ios/NotificationContent/. Delete the generatedMainInterface.storyboard. - Also use the updated Service Extension template (
node_modules/@daertech/pushtifly-capacitor/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.
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. |
You see them in each send's details and in the app's integration status.
Without the SDK (REST)
If you use another plugin, register the token yourself with POST /v1/devices:
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: Capacitor.getPlatform(), environment: 'auto', framework: 'capacitor' }),
});
The send's id arrives in data._phid and the link in data.deepLink. Report it to /v1/events on open.