Customer IO
In your AppDelegate.swift
, the following changes are needed:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
// Update the CustomerIO profile attribute to set if background processing is allowed
// (replace this with your existing `identify` call, if you have this somewhere else, that is okay also)
CustomerIO.shared.identify(userId: email, traits: ["ctx_background_push_allowed": UIApplication.shared.backgroundRefreshStatus == .available])
// If you don't already have this line
UNUserNotificationCenter.current().delegate = self
// Your other code here
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
{
let userInfo = response.notification.request.content.userInfo
// You can call this for every notification, we automatically filter out the ones not relevant
ContextManager.handleNotificationClicked(userInfo: userInfo)
completionHandler()
}
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
{
// Update the CustomerIO profile attribute "ctx_last_processed" to be the current date
CustomerIO.shared.identify(userId: email, traits: ["ctx_last_processed": round(Date().timeIntervalSince1970)])
if application.applicationState == .background || application.applicationState == .inactive {
if let title = userInfo["ctx_title"] as? String,
let body = userInfo["ctx_body"] as? String,
let collapseId = userInfo["ctx_collapse_id"] as? String,
let flowName = userInfo["ctx_flow_name"] as? String,
let notificationDeadlineH = userInfo["ctx_notification_deadline_h"] as? Int
{
let pushContent = UNMutableNotificationContent()
pushContent.title = title
pushContent.body = body
ContextManager.deliverNotificationIfGoodMoment(
flowName: flowName,
collapseId: collapseId,
notificationContent: pushContent,
notificationDeadlineH: notificationDeadlineH,
completionHandler: completionHandler
)
} else {
print("Error parsing userInfo of notification: \(userInfo)")
completionHandler(.failed)
}
} else {
// Your app is already running, you can still decide to show the notification
}
}
Enable Remote Notification
entitlement
In your Xcode project, go to Signing & Capabilities
and enable the Remote Notification
capability in the Background Modes
section.
Update your push notification payload
Update your push notification payload of your push notification provider to include the following details:
{
"aps": {
"alert": {
},
"content-available": 1
},
"ctx_title": "Daily Reminder",
"ctx_body": "Get back to learning, {{ customer.name }}",
"ctx_flow_name": "daily_reminder",
"ctx_collapse_id": "{{ 'now' | date: "%B %-d, %Y" }}",
"ctx_notification_deadline_h": 12
}
Explanation of the fields:
ctx_title
&ctx_body
: The title and body of the notification. This isn't used by ContextSDK directly, but is used by you in thedidReceiveRemoteNotification
method to create theUNMutableNotificationContent
. You can add any other fields you need to create your notification (e.g. attachments, sound, etc.)ctx_flow_name
: The name of the flow (e.g.daily_reminder
) describing what type of notification this is. You will get a custom model for eachctx_flow_name
you use in your appctx_collapse_id
: The collapse ID of the notification, which is used to only show a single notification perctx_collapse_id
at the perfect time. For a daily reminder you'd change this every day, for re-engagement campaigns you may change this every time you change your content.ctx_notification_deadline_h
: The time span in which the notification should be shown in hours. The latest time the notification will be shown isctx_notification_deadline_h
hours after the first background push notification was received on the users device. Keep in mind that this still doesn't guarantee the user will see the notification.
For example, if you want to leverage context-aware push notifications for your daily reminders, you should use the current date as the ctx_collapse_id
and the ctx_flow_name
to daily_reminder
. If your logic is to show the notification anytime between 9am to 9pm, you'd set ctx_notification_deadline_h
to 12 and start sending the notifications hourly at 9am.
Things to consider
- The message will be delayed by around 5 seconds, due to the app detecting the real-world context
- Due to the nature of iOS push notifications, there is no guarantee that your app gets woken up for every notification. We recommend setting a
ctx_last_processed
attribute in your user profile to track the last time a notification was processed. This way, you can fallback to static notifications if the user hasn't opened the app in a while.
Go Live
Now all that's left is to ship your update to the App Store to start calibrating your model