Skip to content

iOS message delivery tracking

There is an API method in Pushwoosh that tracks the delivery of push notifications. iOS apps do not support this method out of the box, because push notifications on iOS are handled by the OS, not by the Pushwoosh SDK. You can add delivery tracking by adding a Notification Service Extension to your project. This page shows how to implement message delivery tracking for iOS apps.

Add Notification Service Extension

Anchor link to
  1. In Xcode, select File > New > Target…

  2. Select Notification Service Extension and press Next.

Xcode target template picker with Notification Service Extension selected
  1. Enter the product name and press Finish.
  1. Press Cancel on the Activate scheme prompt.
Activate scheme prompt with Cancel highlighted

By canceling, you keep Xcode debugging your app instead of the extension you just created. If you activated it by accident, you can switch back to debugging your app within Xcode.

Dependencies for the Notification Service Extension (CocoaPods only)

Anchor link to

If you use Swift Package Manager to manage dependencies, you can skip this step, as the dependencies are added automatically.

Open your Podfile and add the dependency for the target:

Podfile
target 'NotificationServiceExtension' do
use_frameworks!
pod 'PushwooshXCFramework'
end

Run the following commands in the terminal to install the dependencies:

Terminal window
rm -rf Podfile.lock
pod deintegrate
pod setup
pod repo update
pod install

Add code for tracking message delivery events

Anchor link to

Make your extension a subclass of PushwooshNotificationServiceExtension. An empty subclass is enough: Pushwoosh sends the message delivery event, sets the badge, downloads the media attachment, and handles the timeout fallback automatically.

Replace the generated contents of your NotificationService file:

import UserNotifications
import PushwooshFramework
class NotificationService: PushwooshNotificationServiceExtension {}

Since 7.1.0 the extension inherits Pushwoosh_APPID (and other Pushwoosh_* keys) from the host app’s Info.plist, so you no longer need to duplicate it in the extension. Add Pushwoosh_APPID to the extension Info.plist only when you want to override the host value:

NotificationService/Info.plist
<key>Pushwoosh_APPID</key>
<string>XXXXX-XXXXX</string>

App Group (badge and reverse proxy)

Anchor link to

An App Group shared between the app and the extension is needed to sync the badge count and to read reverse-proxy settings that the host app stores.

  1. Add the App Groups capability to the extension target and enable the same group there as in the host app. This is required — without the shared container the badge count and reverse-proxy settings cannot be synced.

  2. Provide the App Group name. Like Pushwoosh_APPID, the extension inherits PW_APP_GROUPS_NAME from the host app’s Info.plist since 7.1.0, so if you already set it there for badges you do not need to add it to the extension. Set it in the extension Info.plist only to override the host value, or provide it programmatically by overriding pushwooshAppGroupsName.

App Info.plist
<key>PW_APP_GROUPS_NAME</key>
<string>group.com.example.app</string>

Customize the notification (optional)

Anchor link to

The base class exposes a few override points, from least to most control. Pushwoosh still runs the delivery event, badge, attachment, and timeout fallback in every case.

Set the App Group programmatically instead of using the Info.plist key:

override func pushwooshAppGroupsName() -> String? {
"group.com.example.app"
}

Run asynchronous preparation before Pushwoosh processes the push — for example, prefetching Push Stories media — without overriding the standard didReceive. Call completion exactly once, on the main thread:

override func pushwooshPrepare(for request: UNNotificationRequest,
completion: @escaping () -> Void) {
// async work here
completion()
}

Modify the content before it is shown by overriding didReceive. Call super with your own content handler, mutate the content inside it, then forward it to the original handler:

override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
super.didReceive(request) { content in
let mutable = (content.mutableCopy() as? UNMutableNotificationContent) ?? content
// customize `mutable` here
contentHandler(mutable)
}
}

Legacy integration

Anchor link to

This low-level API drives the same processing (delivery event, badge, attachment) from a plain UNNotificationServiceExtension:

import UserNotifications
import PushwooshFramework
class NotificationService: UNNotificationServiceExtension {
override func didReceive(_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
PWNotificationExtensionManager.sharedManager()
.handleNotificationRequest(request, contentHandler: contentHandler)
}
}

Share your feedback with us

Anchor link to

Your feedback helps us create a better experience, so we would love to hear from you if you have any issues during the SDK integration process. If you face any difficulties, please do not hesitate to share your thoughts with us via this form.