diff --git a/docs/Point SDK/Android/Overview.md b/docs/Point SDK/Android/Overview.md index f0acd1fe..2aa891a9 100644 --- a/docs/Point SDK/Android/Overview.md +++ b/docs/Point SDK/Android/Overview.md @@ -13,6 +13,7 @@ The following pages provide a guide to integrating the Point SDK with your Andro * [Quick Start Guide](./Quick%20Start.md) * [Geo-triggering](./Geo-triggering.md) * [Tempo](./Tempo.md) +* [Push Notifications](./Push%20Notifications.md) * [Location Permission & Notifications Best Practices](./Location%20Permission%20&%20Notifications%20Best%20Practices.md) * [Best Practices & Recommendations](./Best%20Practices%20&%20Recommendations.md) * [Guide to Submitting Apps With Location Services](../../Implementation%20and%20Best%20Practices%20Guides/Submitting%20apps%20with%20location%20services%20guide.md) @@ -28,4 +29,5 @@ For further information on the classes and methods discussed within the followin ### Compatibility  Notes -* **Moshi:** Android PointSDK v15.0.0+ is compatible with Moshi up to 1.9.3. \ No newline at end of file +* **Moshi:** Android PointSDK v15.0.0+ is compatible with Moshi up to 1.9.3. +* Since v18.0.0 the PointSDK is compiled using the Java 21 toolchain. diff --git a/docs/Point SDK/Android/Push Notifications.md b/docs/Point SDK/Android/Push Notifications.md new file mode 100644 index 00000000..30e15b43 --- /dev/null +++ b/docs/Point SDK/Android/Push Notifications.md @@ -0,0 +1,177 @@ +# Bluedot Push Notifications Module — Integration Guide + +**SDK version:** 18.0.0 +**Module artifact:** `au.com.bluedot:pushnotifications` + +## Overview + +Starting from version 18.0.0, push notification support is delivered as a **separate, optional module** — `pushnotifications`. + +The module: +- Handles FCM token registration with the backend automatically. +- Displays notifications when a push message is received. +- Lets you customise the look of notifications. +- Provides callbacks for received and clicked notifications via a `PushNotificationsEventReceiver`. + +## Requirements + +| Requirement | Value | +|---|---| +| Min SDK | 29 (Android 10) | +| Compile SDK | 36 | +| Firebase Cloud Messaging | `com.google.firebase:firebase-messaging:25.0.1` | +| Core Point SDK | `au.com.bluedot:pointsdk:18.0.0` | + +> Using non-compatible versions of the Firebase dependencies may lead to runtime crashes or unexpected behaviour. + +## Prerequisites + +Configure Android Push Notifications credentials and campaign in Canvas. + +![](../../assets/canvas_push_settings_android.png) + +Setup Push Notifications campaign in Canvas. + +![](../../assets/canvas_push_campaign.png) + +## Step 1 — Add the dependency + +Follow [Quick Start](https://docs.bluedot.io/Point%20SDK/Android/Quick%20Start#import-the-sdk) guide to set up the core SDK first, including the project configuration URL and initialisation. + +In your **app-level** `build.gradle`, add the `pushnotifications` module alongside the core SDK: + +```groovy +dependencies { + // ... + implementation 'com.gitlab.bluedotio.android:point_sdk_push:18.0.0' +} +``` + +## Step 2 — Firebase setup + +The `pushnotifications` module uses **Firebase Cloud Messaging (FCM)** to receive push notifications. If your app doesn't use Firebase yet, follow the [official Android documentation](https://firebase.google.com/docs/cloud-messaging/android/get-started) to set it up. + +> On Android 13 (API 33) and above, you must declare `POST_NOTIFICATIONS` permission in your manifest **and** request it at runtime. Follow official [Android documentation](https://developer.android.com/training/permissions/requesting) for details. + +## Step 3 — Implementation of FirebaseMessagingService + +As part of Firebase Cloud Messaging integration you have implemented your own `FirebaseMessagingService` subclass. Now we are going to use it to bridge FCM events into the `pushnotifications` module. + +```kotlin +class MyFirebaseMessagingService : FirebaseMessagingService() { + + override fun onNewToken(token: String) { + ServiceManager.getInstance(this).pushNotificationsManager.onNewFcmToken(token) + } + + override fun onMessageReceived(remoteMessage: RemoteMessage) { + // use convenient extension functions from the pushnotifications module to check if the message is from Rezolve and convert it to RezolvePushData + if (remoteMessage.isRezolvePushNotification()) { + ServiceManager.getInstance(this).pushNotificationsManager.onMessageReceived(remoteMessage.toRezolvePushData()) + } else { + // Handle your own notifications here + } + } +} +``` + +Register the service in `AndroidManifest.xml`: + +```xml + + + + + +``` + +## Step 4 — Listen for notification events + +To receive callbacks when a notification is received or tapped by the user, create a `BroadcastReceiver` that extends `PushNotificationsEventReceiver`: + +```kotlin +class MyPushNotificationsEventReceiver : PushNotificationsEventReceiver() { + override fun onNotificationReceived(rezolvePushData: RezolvePushData, context: Context) { + // Called when a Rezolve push notification arrives + // Use rezolvePushData.campaignId, .zoneId, .notificationId, .data + } + + override fun onNotificationClicked(rezolvePushData: RezolvePushData, context: Context) { + // Called when the user taps the notification + } +} +``` + +Register the receiver in `AndroidManifest.xml`: + +```xml + + + + + +``` + +### NotificationData fields + +| Field | Type | Description | Example value | +|---|---|---|------------------------------------------| +| `title` | `String` | Notification title (empty string if absent) | `"Title defined in Canvas Campaign"` | +| `body` | `String` | Notification body text (empty string if absent) | `"Body defined in Canvas Campaign"` | +| `pushVersion` | `String` | Push schema version | `"1.0"` | +| `campaignId` | `String` | Campaign UUID | `"b70e49c0-f12e-4ff1-b9f3-9d53767dc5b9"` | +| `zoneId` | `String` | Zone UUID | `"89060cba-a910-481a-aeb5-816182fdf01f"` | +| `notificationId` | `String` | Notification UUID | `"01J1ZQK8R4F9W6M0X9C1JZ7N2B"` | +| `data` | `Map` | All remaining custom key-value pairs from the payload | `{"custom_key":"custom_value"}` | + +--- + +## Step 5 — (Optional) Customise the notification appearance and behaviour + +By default the module displays a standard notification using a built-in icon and the `IMPORTANCE_DEFAULT` channel. +On notification click the SDK sends the broadcast to the receiver defined in Step 4 and starts the default launcher activity defined for the app. + +To override the appearance or behaviour, supply your own `NotificationCompat.Builder` **before** the first message arrives: + +```kotlin +val channel = NotificationChannel( + CUSTOM_PUSH_CHANNEL_ID, + "Custom Push Notifications", + NotificationManager.IMPORTANCE_HIGH +) +val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager +notificationManager.createNotificationChannel(channel) + +val contentIntent = PendingIntent.getActivity( + context, + 0, // request code — unique integer to distinguish this PendingIntent from others; + // use different values if you create multiple distinct PendingIntents + Intent(context, YourCustomActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP + // Optionally pass data: + putExtra("my_custom_id", "1234") + }, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE +) + +val customBuilder = NotificationCompat.Builder(context, CUSTOM_PUSH_CHANNEL_ID) + .setSmallIcon(R.drawable.your_notification_icon) + .setColor(ContextCompat.getColor(context, R.color.your_brand_color)) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setContentIntent(contentIntent) + .setAutoCancel(true) + +ServiceManager.getInstance(context) + .pushNotificationsManager + .setCustomPushNotification(customBuilder) +``` + +> PendingIntent is a system-managed token that dies with the process. Make sure to set the custom builder early in the app lifecycle (e.g. in Application.onCreate) so it is available when the first notification arrives. If the module receives a message before you set the custom builder, it will create and use a default one. + +> The module fills in `.setContentTitle()` and `.setContentText()` automatically from the message payload, so you do not need to set them in your builder. + diff --git a/docs/Point SDK/iOS/Overview.md b/docs/Point SDK/iOS/Overview.md index 39641ea1..cce8ed42 100644 --- a/docs/Point SDK/iOS/Overview.md +++ b/docs/Point SDK/iOS/Overview.md @@ -13,6 +13,7 @@ The following pages provide a guide to integrating the Point SDK with your iOS a * [Quick Start Guide](./Quick%20Start.md) * [Geo-triggering](./Geo-triggering.md) * [Tempo](./Tempo.md) +* [Push Notifications](./Push%20Notifications.md) * [Location Permission best practices](./Location%20Permission%20Best%20Practices.md) * [Guide to Submitting App With Location Services](../../Implementation%20and%20Best%20Practices%20Guides/Submitting%20apps%20with%20location%20services%20guide.md) * [SDK Features](./Features/App%20restart%20notification.md) diff --git a/docs/Point SDK/iOS/Push Notifications.md b/docs/Point SDK/iOS/Push Notifications.md new file mode 100644 index 00000000..f10e6ff7 --- /dev/null +++ b/docs/Point SDK/iOS/Push Notifications.md @@ -0,0 +1,240 @@ +Push Notifications +================== + +**Point SDK** can receive and process **Push Notifications** received from Location Events. + +Requirements +------------ + +| Requirement | Value | +| --- | --- | +| Minimum version | iOS 15+ | +| Point SDK | Embedded and initialized in the app | +| APNs Setup | APNs enabled for the App ID and its Provision Profile | + +Setup Checklist +--------------- + +* Point SDK is setup & initialized. +* Push Notifications feature is enabled in the Xcode's app target. +* A valid `aps-environment` entitlement is included in the app's Provision Profile. +* At least one Push Notifications campaign is configured in Canvas. + +Overview +-------- + +1. Configure iOS Push Notifications credentials in Canvas. +2. Request user permission and register for remote notifications. +3. Register the device push token with Point SDK. +4. Forward received and clicked notifications to Point SDK. +5. (Optional) Listen for Point SDK notification events. + +Step 1 — Setup APNs Credentials in Canvas +----------------------------------------- + +Before **Push Notifications** can be delivered to the application, Apple Push Notification Service (APNs) credentials must be entered in **Canvas**. + +Go to `Project Settings -> Push Notification Settings -> iOS (APNs)`, and upload the required Apple Push Notifications credentials. Use the Canvas Push Notification Settings screen (iOS (APNs) tab) to confirm the iOS credential set is selected before saving. + +![Canvas Push Notification Settings for iOS (APNs)](../../assets/push-notification-settings-ios-apns.png) + +_Canvas Push Notification Settings screen with the iOS (APNs) tab selected._ + +### Required fields + +| Field | Description | +| --- | --- | +| **Signing key (.p8)** | Upload the APNs authentication key downloaded from the Apple Developer portal | +| **Team ID** | Your Apple Developer Team ID | +| **Bundle ID** | The bundle identifier of your iOS application | +| **Key ID** | The Key ID associated with your APNs authentication key | + +Once saved, Rezolve uses these credentials to deliver **Push Notifications**. + +Step 2 — Request Permission +--------------------------- + +The application must request **Push Notifications** permission from the user. + +```swift +UNUserNotificationCenter.current().requestAuthorization( + options: [.alert, .sound, .badge] +) { granted, error in + guard error == nil, granted else { + // Handle permission error/denial + return + } + + DispatchQueue.main.async { + UIApplication.shared.registerForRemoteNotifications() + } +} +``` + +Remote Notifications +-------------------- + +After permission is granted, register the application for remote notifications. + +```swift +UIApplication.shared.registerForRemoteNotifications() +``` + +Configure the notification center delegate during application startup. + +```swift +func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? +) -> Bool { + + UNUserNotificationCenter.current().delegate = self + + return true +} +``` + +Step 3 — Forward Push Notification Token to SDK +----------------------------------------------- + +When a device token is provided, forward it to **Point SDK**. + +```swift +func application(_ application: UIApplication, + didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + + BDLocationManager.instance()?.pushNotifications.register(deviceToken: deviceToken) +} +``` + +**APNs Tokens** can change over time; for example after a restore, or a reinstall of the app. Make sure to forward the latest **Token** whenever iOS provides a new one. + +Step 4 — Forward Push Notifications to the SDK +---------------------------------------------- + +When a **Push Notification** is received, forward the event to the SDK so it can process Rezolve-specific notifications. + +### Notification received + +```swift +func userNotificationCenter( + _ center: UNUserNotificationCenter, + willPresent notification: UNNotification +) async -> UNNotificationPresentationOptions { + + let handled = BDLocationManager.instance()? + .pushNotifications + .handleForeground(notification) ?? false + + return handled ? [.banner, .sound] : [] +} +``` + +### Notification clicked + +```swift +func userNotificationCenter( + _ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void +) { + + BDLocationManager.instance()?.pushNotifications.handleResponse(response) + completionHandler() +} +``` + +Step 5 — (Optional) Listen for Notification Events +-------------------------------------------------- + +The SDK exposes callbacks when a Rezolve **Push Notification** is received or clicked. + +```swift +BDLocationManager.instance()?.pushNotifications.onNotificationReceived = { payload in + print("Rezolve push received. zoneID: \(payload.zoneID ?? \"unknown\")") +} + +BDLocationManager.instance()?.pushNotifications.onNotificationClicked = { payload in + print("Rezolve push clicked. zoneID: \(payload.zoneID ?? \"unknown\")") +} +``` + +These callbacks can be used to update the UI, app navigation, or perform other actions. The callback content can include standard notification content and custom data configured in **Canvas**. + +Complete Example +---------------- + +```swift +class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + + UNUserNotificationCenter.current().delegate = self + + UNUserNotificationCenter.current().requestAuthorization( + options: [.alert, .sound, .badge] + ) { granted, error in + guard error == nil, granted else { return } + DispatchQueue.main.async { + UIApplication.shared.registerForRemoteNotifications() + } + } + + BDLocationManager.instance()?.pushNotifications.onNotificationReceived = { payload in + print("Push received. zoneID: \(payload.zoneID ?? \"unknown\")") + } + + BDLocationManager.instance()?.pushNotifications.onNotificationClicked = { payload in + print("Push clicked. zoneID: \(payload.zoneID ?? \"unknown\")") + } + + return true + } + + func application(_ application: UIApplication, + didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + + BDLocationManager.instance()?.pushNotifications.register(deviceToken: deviceToken) + } + + func userNotificationCenter( + _ center: UNUserNotificationCenter, + willPresent notification: UNNotification + ) async -> UNNotificationPresentationOptions { + + let handled = BDLocationManager.instance()? + .pushNotifications + .handleForeground(notification) ?? false + + return handled ? [.banner, .sound] : [] + } + + func userNotificationCenter( + _ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void + ) { + + BDLocationManager.instance()?.pushNotifications.handleResponse(response) + completionHandler() + } +} +``` + +Notes +----- + +**Point SDK** works alongside the app's existing **Push Notifications** setup. Your app continues to control permission prompts and APNs registration, while the SDK focuses on handling Rezolve notifications and providing callbacks that can be used for UI updates, app navigation, or perform other actions. + +Troubleshooting +--------------- + +If notifications are not received as expected, check: + +* The APNs credentials in Canvas match the app's **Team ID** and **Bundle ID**. +* The app build uses a **Provision Profile** that contains the `aps-environment` entitlement. +* Push Notifications permission has been granted from the user and remote notifications are active. +* The latest and updated APNs Token has been forwarded to Point SDK. \ No newline at end of file diff --git a/docs/Push Notifications/Overview.md b/docs/Push Notifications/Overview.md new file mode 100644 index 00000000..b2ffcd7e --- /dev/null +++ b/docs/Push Notifications/Overview.md @@ -0,0 +1,217 @@ +# Overview + +Not all push notifications are equal. Generic promotional messages have trained customers to ignore - or opt out of - notifications entirely. Location-triggered, transactional notifications sent at the exact moment of relevance are a different proposition: they deliver information the customer actually needs, exactly when they need it, without requiring any action on their part. + +For Click & Collect, that moment is arrival. Today, most teams bridge it with manual staff processes, static SMS, or customer-triggered check-ins. These approaches are slow, error-prone, and depend entirely on the customer taking action. When timing is off - an order handed out too early, a notification sent too late - both the customer experience and operational efficiency suffer. + +Push Notifications is a feature of the Point SDK that closes this loop. When a customer enters a geofence zone configured in Canvas, the SDK detects the event and Rezolve delivers a push notification to their device in real time - no customer action required. + +--- + +## How It Works + +Push Notifications integrates into the existing Rezolve Geo location stack. No separate infrastructure is required. + +``` +Customer's app (Point SDK) + | + | Zone entry detected + v +Rezolve backend + | + | Evaluates configured campaigns in Canvas + v +Push delivery (APNs / FCM) + | + v +Customer's device - notification displayed +``` + +1. Point SDK is embedded in your app and detects when a customer enters a configured geofence zone. +2. The SDK sends the entry event to the Rezolve backend, which evaluates active push notification campaigns configured in Canvas. +3. If a matching campaign is found, Rezolve delivers the notification via Apple Push Notification service (APNs) for iOS or Firebase Cloud Messaging (FCM) for Android. +4. The notification appears on the customer's device. The SDK provides callbacks your app can use to handle the notification - updating the UI, navigating to a specific screen, or logging the event. + +Push Notifications works alongside your app's existing notification setup. Your app remains in full control of permission prompts and device token registration; the SDK handles Rezolve-specific delivery and provides structured callbacks. + +--- + +## End-User Permissions + +Push Notifications depends on two permissions that the end user must grant. If either is missing, notifications will not be delivered. + +| Permission | Why it's needed | What happens without it | +| --- | -- | --- | +| **Location (Always / When in Use)** | The Point SDK must be able to detect when a user enters a geofence zone. Without location access, the SDK cannot fire zone entry events and the delivery pipeline never starts. | No zone events are triggered. No notifications are sent, regardless of campaign configuration. | +| **Push Notifications** | The device must be registered to receive push notifications via APNs (iOS) or FCM (Android). | The device token cannot be registered. Notifications are not delivered even if a zone entry is detected. | + +Both permissions must be granted by the user. Neither can be forced - they can only be requested through your app's standard permission prompts. + +### What this means for your app + +Your app is responsible for requesting both permissions at the right moment and with the right context. Users who understand *why* a permission is needed are significantly more likely to grant it. Consider: + +- **Explaining the value before prompting** - e.g. *"Allow location access so we can notify you when your order is ready to collect - no need to check the app."* +- **Requesting push permission after location** - the user has already committed to the experience; the second prompt feels natural +- **Handling denial gracefully** - if a user denies either permission, surface an in-app prompt that directs them to device Settings to enable it later + +On **Android 13+**, push notification permission (`POST_NOTIFICATIONS`) must also be explicitly requested at runtime in addition to being declared in the manifest. + +--- + +## Requirements + +| Requirement | iOS | Android | +| --- | -- | --- | +| Minimum OS | iOS 15+ | Android 10 (API 29+) | +| Point SDK | 18.x, embedded and initialised | Core SDK 18.x + `pushnotifications` module 18.x | +| Push service | APNs enabled for App ID + Provision Profile | Firebase project with FCM enabled (`firebase-messaging:25.x`) | +| Canvas configuration | APNs credentials uploaded + campaign configured | FCM credentials uploaded + campaign configured | + +:::info +**Android:** Push Notifications is delivered as a separate, optional module (`au.com.bluedot:pushnotifications`) starting from SDK 18.x. It must be added to your app-level `build.gradle` alongside the core Point SDK. +::: + +--- + +## Quick Start + +Getting from zero to first value requires completing four steps: + +1. **Upload push credentials to Canvas** - Configure platform credentials in **Project Settings -> Push Notification Settings**: APNs credentials for iOS, FCM credentials for Android (or both if supporting both platforms). This authorises Rezolve to deliver notifications on behalf of your app. Then create a campaign and assign it to the zones that should trigger notifications. + +2. **Add the SDK module** - On iOS, Push Notifications is built into the core Point SDK. On Android, add the separate `pushnotifications` module to your app-level `build.gradle` alongside the core SDK. + +3. **Bridge push service events to the SDK** - On iOS, forward the APNs device token and received notifications to Point SDK. On Android, bridge FCM token and message events via your `FirebaseMessagingService`; the module uses `isRezolvePushNotification()` to filter only Rezolve messages so your own notifications are unaffected. + +4. **(Optional) Handle SDK callbacks** - Use `onNotificationReceived` and `onNotificationClicked` (iOS) or extend `PushNotificationsEventReceiver` (Android) if you need to react to notifications in-app - for example to update the UI or navigate to a specific screen. The SDK delivers the notification without these callbacks; they are only needed if your app requires custom behaviour on receipt or tap. + +For detailed implementation steps, see the platform-specific guides below. + +--- + +## Platform Implementation Guides + +### iOS + +-> [Push Notifications - iOS](../Point%20SDK/iOS/Push%20Notifications.md) + +Covers APNs credential setup, permission requests, device token registration, foreground and background notification handling, SDK callbacks, a complete `AppDelegate` example, and troubleshooting. + +### Android + +-> [Push Notifications - Android](../Point%20SDK/Android/Push%20Notifications.md) + +Covers FCM credential setup, `FirebaseMessagingService` integration, device token registration, foreground and background notification handling, SDK callbacks, a complete example, and troubleshooting. + +--- + +## Canvas Configuration + +Canvas is the control plane for Push Notifications. There are two areas to configure: **Credentials** and **Campaigns**. Campaign management via the Config API is not supported at this time. + +### Step 1 - Push Notification Credentials + +Go to **Project Settings -> Push Notification Settings**. Credentials are configured per platform under separate tabs. + +**iOS (APNs) tab:** + +![Canvas Push Notification Settings - iOS APNs tab](../assets/push-notification-settings-ios-apns.png) + +| Field | Description | +| --- | -- | +| **Signing key (.p8)** | APNs authentication key downloaded from the Apple Developer portal | +| **Team ID** | Your Apple Developer Team ID | +| **Key ID** | The Key ID associated with your APNs authentication key | +| **Bundle ID** | The bundle identifier of your iOS application | +| **Environment** | Select Development (for testing and debug builds) or Production (for App Store and TestFlight builds) | + +**Android (FCM) tab:** + +![Canvas Push Notification Settings - Android FCM tab](../assets/push-notification-settings-android-fcm.png) + +| Field | Description | +| --- | -- | +| **Service Account JSON** | Upload the FCM service account JSON file downloaded from the Firebase Console | + +### Step 2 - Push Notification Campaigns + +Campaigns are created and managed from the **Push Notifications** section in Canvas. Click **+ New Campaign** to open the campaign wizard, which walks through three steps. + +:::info +**Note:** Push notification campaigns are scoped to the project currently selected in Canvas. If you need to create a campaign for a different project, navigate to another page in Canvas first, select the correct project from the top navigation, then return to Push Notifications. +::: + +**Step 2.1 - Compose Message** + +![Canvas New Campaign - Compose Message](../assets/push-notification-campaign-compose.png) + +Campaigns in the current release are triggered on zone entry. Enter the notification content: + +| Field | Limit | Description | +| --- | -- | --- | +| **Title** | 50 characters | The notification title displayed on the device | +| **Body** | 100 characters | The notification message body | + +A live preview updates as you type, showing how the notification will appear on the device. + +**Step 2.2 - Select Zones** + +![Canvas New Campaign - Select Zones](../assets/push-notification-campaign-zones.png) + +Search for and select the geofence zones that should trigger this campaign. At least one zone must be selected before proceeding. + +**Step 2.3 - Review & Launch** + +![Canvas New Campaign - Review & Launch](../assets/push-notification-campaign-review.png) + +Review the campaign summary - trigger type, zones, and message content - then either **Save as Draft** or **Activate Message**. Only active campaigns deliver notifications. + +**Activating a campaign** + +Once you click **Activate Message**, Canvas confirms the campaign is live with a message summary showing the title, trigger type, zone count, and status. + +![Canvas - Message Activated confirmation](../assets/push-notification-campaign-activated.png) + +**Managing campaigns** + +The Push Notifications list shows all campaigns with their status, zone count, trigger type, and creation date. Each campaign can be **Edited**: **Duplicated**, **Paused**, or **Deleted** from the action menu. + +![Canvas - Push Notifications campaign list](../assets/push-notification-campaigns-overview.png) + +![Canvas - Campaign action menu](../assets/push-notification-campaign-actions.png) + +--- + +## Need Something Custom? + +Most Click & Collect use cases can be implemented using the standard SDK and Canvas setup. If you have requirements outside of the standard configuration, contact the Rezolve Customer Success team at [support@rezolve.com](mailto:support@rezolve.com). + +--- + +## Troubleshooting + +| Symptom | Check | +| --- | -- | +| Notifications not delivered | Credentials in Canvas match the app's signing configuration (Team ID / Bundle ID for iOS; FCM project for Android) | +| No notifications despite active campaign | Confirm the end user has granted both location permission and push notification permission on their device | +| Notifications stopped after app update or OS upgrade | User may have been re-prompted and denied a permission; check device Settings for location and notification status | +| Notifications not delivered on Android 13+ | Confirm `POST_NOTIFICATIONS` permission is declared in the manifest and has been granted at runtime | +| Notifications received but SDK callbacks not firing | Confirm that received and clicked notifications are being forwarded to the SDK | +| Device token not registering | Ensure the latest token from APNs / FCM is being passed to the SDK on every launch; tokens can change after reinstalls or restores | +| Notifications received in wrong campaign zone | Verify zone configuration in Canvas; confirm SDK is initialised before zone entry | +| Customer receiving repeated notifications for the same zone | Check the **minimum retrigger time** configured on the zone in Canvas. Each time the zone's retrigger threshold is met, a new entry event fires and a notification is sent. Adjusting this setting on the zone controls how frequently the same device can trigger the campaign. | + +For platform-specific troubleshooting, see the relevant implementation guide. + +--- + +## Good to Know + +**Saved credentials are not displayed after upload** + +For security reasons, APNs and FCM credentials are not shown after they have been saved. However, Canvas does not currently indicate whether credentials have been configured for a given platform. If you are unsure whether credentials are in place, upload them again to overwrite, or contact [support@rezolve.com](mailto:support@rezolve.com) to confirm. + +**No dedicated push notification analytics** + +Campaign delivery and engagement metrics are not available in Canvas at this time. If you need visibility into notification delivery, this can be tracked via the SDK callbacks in your app. diff --git a/docs/assets/canvas_push_campaign.png b/docs/assets/canvas_push_campaign.png new file mode 100644 index 00000000..814fac6e Binary files /dev/null and b/docs/assets/canvas_push_campaign.png differ diff --git a/docs/assets/canvas_push_settings_android.png b/docs/assets/canvas_push_settings_android.png new file mode 100644 index 00000000..faae5e83 Binary files /dev/null and b/docs/assets/canvas_push_settings_android.png differ diff --git a/docs/assets/push-notification-campaign-actions.png b/docs/assets/push-notification-campaign-actions.png new file mode 100644 index 00000000..570a070b Binary files /dev/null and b/docs/assets/push-notification-campaign-actions.png differ diff --git a/docs/assets/push-notification-campaign-activated.png b/docs/assets/push-notification-campaign-activated.png new file mode 100644 index 00000000..6fa27801 Binary files /dev/null and b/docs/assets/push-notification-campaign-activated.png differ diff --git a/docs/assets/push-notification-campaign-compose.png b/docs/assets/push-notification-campaign-compose.png new file mode 100644 index 00000000..ae1598e4 Binary files /dev/null and b/docs/assets/push-notification-campaign-compose.png differ diff --git a/docs/assets/push-notification-campaign-review.png b/docs/assets/push-notification-campaign-review.png new file mode 100644 index 00000000..d9a9c9b3 Binary files /dev/null and b/docs/assets/push-notification-campaign-review.png differ diff --git a/docs/assets/push-notification-campaign-zones.png b/docs/assets/push-notification-campaign-zones.png new file mode 100644 index 00000000..c1afd4b4 Binary files /dev/null and b/docs/assets/push-notification-campaign-zones.png differ diff --git a/docs/assets/push-notification-campaigns-overview.png b/docs/assets/push-notification-campaigns-overview.png new file mode 100644 index 00000000..f12ee316 Binary files /dev/null and b/docs/assets/push-notification-campaigns-overview.png differ diff --git a/docs/assets/push-notification-settings-android-fcm.png b/docs/assets/push-notification-settings-android-fcm.png new file mode 100644 index 00000000..5c20bf6c Binary files /dev/null and b/docs/assets/push-notification-settings-android-fcm.png differ diff --git a/docs/assets/push-notification-settings-ios-apns.png b/docs/assets/push-notification-settings-ios-apns.png new file mode 100644 index 00000000..9d62c922 Binary files /dev/null and b/docs/assets/push-notification-settings-ios-apns.png differ diff --git a/sidebars.js b/sidebars.js index a0d0f9e7..09247710 100644 --- a/sidebars.js +++ b/sidebars.js @@ -241,6 +241,27 @@ const sidebars = { "Canvas/How to authenticate with Config API", ], }, + { + type: "category", + label: "Push Notifications", + link: { + type: "doc", + id: "Push Notifications/Overview" + }, + items: [ + "Push Notifications/Overview", + { + type: "doc", + label: "Android", + id: "Point SDK/Android/Push Notifications" + }, + { + type: "doc", + label: "iOS", + id: "Point SDK/iOS/Push Notifications" + } + ] + }, { type: "category", label: "Chat AI",