Rich push notifications

With rich push, you can do more than just send a simple notification; you can send an image, open a deep link when someone taps your message, and more!

 Our mobile SDKs are in alpha and subject to change

While we’re very excited about our mobile SDKs, they’re still works in progress! If you want to try them out, contact product@customer.io

This page is part of an introductory series to help you get started with the essential features of our SDK. The highlighted step(s) below are covered on this page. Before you continue, make sure you've implemented previous features—i.e. you can't identify people before you initialize the SDK!

graph LR getting-started(Install SDK) -->B(Initialize SDK) B --> identify(identify people) identify -.-> track-events(Send events) identify -.-> push(Receive push) identify -.-> rich-push(Receive Rich Push) track-events --> testing-error-handling(handle errors) push --> testing-error-handling rich-push --> testing-error-handling click getting-started href "/docs/sdk/ios/getting-started" click B href "/docs/sdk/ios/getting-started/#initialize-the-sdk" click identify href "/docs/sdk/ios/identify" click track-events href "/docs/sdk/ios/track-events/" click push href "/docs/sdk/ios/push" click rich-push href "/docs/sdk/ios/rich-push" click testing-error-handling href "/docs/sdk/ios/testing-error-handling" style rich-push fill:#B5FFEF,stroke:#007069

Before you begin

You should set up APN or FCM push notifications and make sure that you can send yourself a test test push notification](/docs/push-getting-started/#sending-a-single-test-message) before you start implementing rich p.

While rich push generally entails a number of features, our SDK only supports deep links and images right now. If you want to include action buttons or other rich push features, you need to add your own custom code.

When writing your own custom code, we recommend that you use our SDK as it is much easier to extend than writing your own code from scratch. Read below for tips on how to extend the functionality of the SDK with features we do not yet support.

Set up rich push

  1. Create a Notification Service Extension in Xcode. Go to File > New > Target and select Notification Service Extension in the iOS section. Answer all of the questions to finish the process.

  2. You should now see a new file added to your Xcode project. The file is probably named NotificationService and looks like this.

    import UserNotifications
       
    class NotificationService: UNNotificationServiceExtension {
       
        override func didReceive(
            _ request: UNNotificationRequest,
            withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
        ) {
       
        }
       
        override func serviceExtensionTimeWillExpire() {
       
        }
    }
       
  3. Modify this file by calling the appropriate Customer.io functions.

    import CioMessagingPush
    import CioMessagingPushAPN
    import UserNotifications
       
    class NotificationService: UNNotificationServiceExtension {
       
        override func didReceive(
            _ request: UNNotificationRequest,
            withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
        ) {
            // For simple apps that only use Customer.io for sending rich push messages,
            // This 1 line of code is all that you need!
            MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
       
            // If you use a service other than Customer.io to send rich push,
            // you can check if the SDK handled the rich push for you. If it did not, you
            // know that the push was *not* sent by Customer.io and you can try another way.
            let handled = MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
            if !handled {
                // Rich push was *not* sent by Customer.io. Handle the rish push in another way.
            }
            // If you need to add features, like showing action buttons in your push, 
            // you can set your own completion handler.
            MessagingPush.shared.didReceive(request) { notificationContent in
                if let mutableContent = notificationContent.mutableCopy() as? UNMutableNotificationContent {
                    // Modify the push notification like adding action buttons!
                }
                contentHandler(notificationContent)
            }
        }
       
        override func serviceExtensionTimeWillExpire() {
            MessagingPush.shared.serviceExtensionTimeWillExpire()
        }
    }
       

Your app can now display rich push notifications in your app, including images, etc. However, if you want to enable deep links, you should continue to the Deep links section below.

After you set up rich push notifications you can enable deep links in rich push notifications.

  1. Modify your AppDelegate with the following information. This enables your app to launch a deep link URL when someone taps a notification.

    import CioMessagingPushAPN
    import CioTracking
    import Foundation
    import UIKit
       
    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
        ) -> Bool {
            CustomerIO.initialize(siteId: "YOUR SITE ID", apiKey: "YOUR API KEY", region: Region.US)
       
            // Must call this function in order for `UNUserNotificationCenterDelegate` functions
            // to be called.
            UNUserNotificationCenter.current().delegate = self
       
            // It's good practice to always register for remote push when the app starts.
            // This asserts that the Customer.io SDK always has a valid APN device token to use.
            UIApplication.shared.registerForRemoteNotifications()
       
            return true
        }
    }
       
    extension AppDelegate: UNUserNotificationCenterDelegate {
        func userNotificationCenter(
            _ center: UNUserNotificationCenter,
            didReceive response: UNNotificationResponse,
            withCompletionHandler completionHandler: @escaping () -> Void
        ) {
            let handled = MessagingPush.shared.userNotificationCenter(center, didReceive: response,
                                                                     withCompletionHandler: completionHandler)
       
            // If the Customer.io SDK does not handle the push, it's up to you to handle it and call the
            // completion handler. If the SDK did handle it, it called the completion handler for you.
            if !handled {
                completionHandler()
            }
        }
       
        // OPTIONAL: If you want your push UI to show even with the app in the foreground, override this function and call
        // the completion handler.
        @available(iOS 10.0, *)
        func userNotificationCenter(
            _ center: UNUserNotificationCenter,
            willPresent notification: UNNotification,
            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
        ) {
            completionHandler([.list, .banner, .badge, .sound])
        }
    }
       
  2. Setup deep linking in your app. There are two ways to do this, and you can do both if you choose.

    • Universal Links: universal links are great if you want to open your mobile app instead of a web browser when your goes to a page on your website. However, universal links take more time to setup. Follow this guide to setup Universal Links in your app.
    • App scheme: app scheme deep links are quick and easy to setup. However, they do not work if the mobile app is not installed, which is where universal links provide an advantage. To enable app scheme deep links. See the section below to enable app scheme deep links.

App scheme deep links only work if your audience has your mobile app installed. If you want to support cases where your audience might not already have your app, you can set up universal links.

  1. Open your Xcode project and go to your project’s settings. Select your app Target, click the Info tab, and then click URL Types > to create a new URL Type.

    visual of the typed instructions in the sentence above to create a new URL type
    visual of the typed instructions in the sentence above to create a new URL type

  2. Enter a unique value for your app for URL Schemes.

    visual of the typed instructions in the sentence above to enter a unique value for URL scheme
    visual of the typed instructions in the sentence above to enter a unique value for URL scheme

Test Rich Push

After you set up rich push, you should test your implementation. Use the payloads below to send a push in the Customer.io web app with a Custom Payload.

IN both of the test payloads below, you should:

  • Set the link to the deep link URL that you want to open when your tester taps your notification.
  • Set the image to the URL of an image you want to show in your notification. It’s important that the image URL starts with https:// and not http:// or the image might not show up.

APNs test payload
{
    "CIO": {
        "push": {
            "link": "remote-habits://deep?message=hello&message2=world",
            "image": "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpawsindoorssouthend.com%2Fwp-content%2Fuploads%2F2020%2F04%2Ftips-for-choosing-doggy-day-care.jpg"
        }
    },
    "aps": {
        "mutable-content": 1,
        "alert": {
            "title": "Title of your push goes here!",
            "body": "Body of your push goes here!"
        }
    }
}
FCM test payload
{
    "message": {
        "apns": {
            "payload": {
                "CIO": {
                    "push": {
                        "link": "remote-habits://deep?message=hello&message2=world",
                        "image": "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpawsindoorssouthend.com%2Fwp-content%2Fuploads%2F2020%2F04%2Ftips-for-choosing-doggy-day-care.jpg"
                    }
                },
                "aps": {
                    "mutable-content": 1,
                    "alert": {
                        "title": "Title of your push goes here!",
                        "body": "Body of your push goes here!"
                    }
                }
            }
        }
    }
}

Rich push payloads

To send a rich push in Customer.io, you need to use our Custom Payload editor, which takes a JSON structure. In the editor, you’ll select the type of device you want to send your message to: you can have separate payloads for Android and iOS. In our case, you’ll click iOS.

The custom payload editor for a push notification
The custom payload editor for a push notification

The top level of the payload changes slightly depending on your push provider, APNS or FCM. Otherwise, your JSON is split into two major objects:

  • an aps object, which contains the standard aspects of a push—the alert.title and alert.body of your message—and Apple’s push options.
  • a CIO object containing a the rich aspects of your message that the SDK will interpret. At present, it contains link and image strings.
{
    "aps": {
        // basic iOS message and options go here
        "mutable-content": 1,
        "alert": {
            "title": "string", //(optional) The title of the notification.
            "body": "string" //(optional) The message you want to send.
        }
    },
    "CIO": {
        "push": {
            "link": "string", //generally a deep link, i.e. my-app:://...
            "image": "string" //HTTPS URL of your image, including file extension
        }
    }
}
{
  "message": {
    "apns": {
      "payload": {
        "aps": {
          // basic iOS message and options go here
          "mutable_content": 1,
          "alert": {
            "title": "string", //(optional) The title of the notification.
            "body": "string" //(optional) The message you want to send.
           }
        },
        "CIO": {
          "push": {
            "link": "string", //generally a deep link, i.e. my-app:://...
            "image": "string" //HTTPS URL of your image, including file extension
          }
        }
      },
      "headers": {
        // headers defined in Apple Push Notification Service.
        "apns-priority": 10
      }
    } 
  }
}
Copied to clipboard!