Push Notification Analytics
The MovableInk SDK provides automatic tracking for push notification opens. This allows you to measure engagement and attribute conversions to your push campaigns.
Setup
Call handlePushNotificationOpened(_:) when a user opens a push notification to allow the SDK to check if it is a MovableInk
notification and track the open event.
Using UserNotifications Framework (Recommended)
If your app uses the UserNotifications framework, implement the delegate method in your
UNUserNotificationCenterDelegate:
import UserNotifications
import MovableInk
class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
// Track the notification open with MovableInk
MIClient.userNotificationCenter(center, didReceive: response)
// Your app's notification handling logic here
completionHandler()
}
}
UIApplicationDelegate
Alternatively, if you aren't using the UserNotifications framework, you'll need to use the UIApplicationDelegate method:
import MovableInk
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]
) {
MIClient.handlePushNotificationOpened(userInfo)
// Your app's notification handling logic here
}
Manual Tracking | Without SDK
If you're not using the SDK, you can still track this event by manually making a request to the URL in the payload.
Using UserNotifications Framework
If your app uses the UserNotifications framework, you can extract the URL from the notification payload and make a request when the notification is opened.
import UserNotifications
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
guard let userInfo = response.notification.request.content.userInfo as? [String: Any] else {
completionHandler()
return
}
// Try to extract URL from either "mi" or "data" container
var urlString: String?
// First, check for the standard "mi" container format
if let miContainer = userInfo["mi"] as? [String: Any] {
urlString = miContainer["url"] as? String
}
// Also check for "data" container format (mi_url and mi_source)
if urlString == nil, let dataContainer = userInfo["data"] as? [String: Any] {
urlString = dataContainer["mi_url"] as? String
}
// If we found a URL string, resolve it
if let urlString = urlString, let url = URL(string: urlString) {
Task {
let _ = try await URLSession.shared.data(for: URLRequest(url: url))
}
}
}
Without UserNotifications Framework
If you're not using the UserNotifications framework, you can extract the URL from the notification payload in the UIApplicationDelegate method.
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]
) {
// Try to extract URL from either "mi" or "data" container
var urlString: String?
// First, check for the standard "mi" container format
if let miContainer = userInfo["mi"] as? [String: Any] {
urlString = miContainer["url"] as? String
}
// Also check for "data" container format (mi_url and mi_source)
if urlString == nil, let dataContainer = userInfo["data"] as? [String: Any] {
urlString = dataContainer["mi_url"] as? String
}
// If we found a URL string, resolve it
if let urlString = urlString, let url = URL(string: urlString) {
Task {
let _ = try await URLSession.shared.data(for: URLRequest(url: url))
}
}
}