Push Notifications

Requirements


Configure handling Push Notifications in your application. See Apple Developer - Notifications.

Configuring Firebase


Google Firebase Cloud Messaging is necessary to handle Mobile Campaigns sent from Synerise.

  1. Follow the instructions in Firebase - Get Started on iOS.
  2. Integrate the Firebase with Synerise. See Integration section.

Setting up Firebase Cloud Messaging for Synerise SDK

Extend the Firebase Messaging Delegate so our SDK can receive the Firebase token that is required to deliver Push Notifications from Synerise:

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
   	FirebaseApp.configure()
   	Messaging.messaging().delegate = self

   	if #available(iOS 10, *) {
   		UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in

   		}
   	} else {
   		let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
   		application.registerUserNotificationSettings(settings)
   	}

   	application.registerForRemoteNotifications()
   }

   // MARK: - MessagingDelegate

   func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
   	Client.registerForPush(registrationToken: fcmToken, success: { (success) in
   		// success
   	}) { (error) in
   		// failure
   	}
   }

Make sure that the Firebase token is always up-to-date by implementing a suitable method from the SyneriseDelegate (see the section):

   // MARK: - SyneriseDelegate

   func snr_registerForPushNotificationsIsNeeded() -> Void {
   	guard let fcmToken = Messaging.messaging().fcmToken else {
   		return
   	}

   	Client.registerForPush(registrationToken: fcmToken, success: { (success) in
   		// success
   	}) { (error) in
   		// failure
   	}
   }

Configuring Notification Encryption


To enable encrypted Push Notifications, you must the change configuration of your business profile in the Synerise portal. See Google Firebase.

Note: iOS 10 or newer is required for this feature.

Set your Keychain Group Identifier (See this section) and set Synerise.settings.notifications.encryption to true in SDK settings:

Synerise.settings.sdk.keychainGroupIdentifier = "YOUR_KEYCHAIN_GROUP_IDENTIFIER"
Synerise.settings.notifications.encryption = true

Next: Configure Synerise Notification Service Extension.

Handling incoming Push Notifications


Note: You may disable handling Push Notifications in the SDK at any time. See Enable/disable notifications.

Documentation on how to prepare Push Notifications on app.synerise.com is available in our Mobile Knowledge Base.

In order to handle Synerise Push Notifications, you must pass the incoming push payload to the Synerise SDK.

Synerise payload

The following code shows how to handle Push Notifications in the AppDelegate:

// Support for Push Notifications on iOS 9
// Support for Silent Notifications

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)
  
  if isSyneriseNotification {
    Synerise.handleNotification(userInfo)
    completionHandler(.noData)
  }
}

func application(_ application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [AnyHashable : Any], completionHandler: @escaping () -> Void) {
  let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)
  
  if isSyneriseNotification {
    Synerise.handleNotification(userInfo)
    completionHandler()
  }
}

// Support for Push Notifications on iOS 10 and above

// MARK: - UNUserNotificationCenterDelegate

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
  let userInfo = response.notification.request.content.userInfo
  
  let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)
  
  if isSyneriseNotification {
    Synerise.handleNotification(userInfo)
    completionHandler()
  }
}

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
  let userInfo = notification.request.content.userInfo

  let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)
  
  if isSyneriseNotification {
    Synerise.handleNotification(userInfo)
    completionHandler(UNNotificationPresentationOptions.init(rawValue: 0))
  }
}
Important: All of these methods must be implemented to ensure proper handling of Push Notifications.

Custom payload

You may send custom Push Notifications or all custom campaigns on app.synerise.com. The code below of one sample delegate method checks if notification is not Synerise origin and then deal with it.

@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
  let userInfo = notification.request.content.userInfo

  let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)

  if isSyneriseNotification {
    Synerise.handleNotification(userInfo)
    completionHandler(UNNotificationPresentationOptions.init(rawValue: 0))
  }
}

Encrypted payloads

Synerise payload

If you handle Synerise notification, you do not have to do anything. The SDK decrypts Synerise notification’s payload:

Custom payload

Otherwise, if it is custom encrypted Push Notification sended by Synerise, there are two methods for dealing with them:

Synerise.isNotificationEncrypted(_:) - Checks if the notification payload is encrypted by Synerise.

Synerise.decryptNotification(_:) - Decrypts a notification payload.

class NotificationService: UNNotificationServiceExtension {

  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?

  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {]
    self.contentHandler = contentHandler
    self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    
    if let bestAttemptContent = self.bestAttemptContent {
      //...
      var userInfo = notification.request.content.userInfo
      let isSyneriseNotification: Bool = Synerise.isSyneriseNotification(userInfo)

      if isSyneriseNotification == false {
        let isNotificationEncrypted: Bool = Synerise.isNotificationEncrypted(userInfo)
        if isNotificationEncrypted == true {
          guard let userInfoDecrypted = Synerise.decryptNotification(userInfo) else {
            fatalError();
          }

          bestAttemptContent.title = userInfoDecrypted["aps"]?["alert"]?["title"]
          bestAttemptContent.body = userInfoDecrypted["aps"]?["alert"]?["body"]
          bestAttemptContent.userInfo = userInfoDecrypted;
        }
      }
      //...
      contentHandler(bestAttemptContent)
    }
  }
}
Important: You should use code above in Notification Service Extension to deal with standard Push Notification. For Silent Push Notification you could implement this in application.

‘Mutable-Content’ parameter

If you want to deal with push notification payload before application receives it, tick Mutable-Content option if you send the Simple Push campaign.

See (Apple Developer - UNNotificationServiceExtension) for more details.

‘Content-Available’ parameter

If you want to receive push notification in backround or resume state, tick Content-Available option if you send the Simple Push campaign.

See Apple Developer - Pushing Background Updates to Your App for more details.

Synerise Notification Service Extension


NotificationServiceExtension is an object that adds the notification functionality to the SDK. It works by implementing the UNNotificationServiceExtension that cooperates with the Application.

The Synerise Notification Service Extension facilitates some operations by automating them. This means a one-time implementation provides new functionalities, changes, and fixes, along with new versions of the SDK.

It implements the following operations:

  • Decrypting Push Notifications (but not Silent Notifications)
  • Tracking events from Simple Push
  • Improving the appearance of Simple Push notifications (Rich Media)

Configuration

  1. Add the Notification Service Extension to your iOS project (Apple Developer - UNNotificationServiceExtension).
  2. Configure App Group Identifier (see this section).
  3. Configure Keychain Group Identifier (see this section).
Note:
  • App Group Identifier configuration is for tracking purposes.
  • Keychain Group Identifier configuration is for decryption purposes.

Implementation

import UserNotifications
import SyneriseSDK

class NotificationService: UNNotificationServiceExtension {

  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?

  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    
    if let bestAttemptContent = self.bestAttemptContent {
        Synerise.settings.sdk.appGroupIdentifier = "YOUR_APP_GROUP_IDENTIFIER"
        Synerise.settings.sdk.keychainGroupIdentifier = "YOUR_KEYCHAIN_GROUP_IDENTIFIER"
        
        #if DEBUG
        NotificationServiceExtension.setDebugModeEnabled(true)
        #endif
        
        NotificationServiceExtension.setDecryptionFallbackNotificationTitleAndBody(title: "(Encrypted))", body: "(Encrypted)")
        NotificationServiceExtension.didReceiveNotificationExtensionRequest(request, withMutableNotificationContent: bestAttemptContent)
        
        contentHandler(bestAttemptContent)
    }
  }

  override func serviceExtensionTimeWillExpire() {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    
    if let contentHandler = self.contentHandler, let bestAttemptContent =  self.bestAttemptContent {
        contentHandler(bestAttemptContent)
    }
  }
}

See the examples Notification Service Extensions with implemented notification decryption:

Debug Mode

You can enable debug mode for Notification Service Extension logging and testing purposes.

WARNING: Do not use Debug Mode in a release version of your application.
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
  self.contentHandler = contentHandler
  self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

  //...
  NotificationServiceExtension.setDebugModeEnabled(true)
  //...
}

In debug mode, decryption process is always successful.

Your best attempt content (UNNotificationContent object) is modified - the notification displays the title and body with the problem that occurred during decryption. It may help you debug and find problems with the configuration.

Rich Media in Push Notifications


Configuration

To add this feature in your Simple Push Campaigns, you must:

  1. Configure the App Group that identifies the group used by applications the and extensions it belongs to.
    Documentation is available at Apple Developer - App Groups.
  2. Add the Notification Content Extension in your iOS project - separately for each type of our Rich Media extensions.
  3. Configure your application and the SDK.

Implementation

Synerise SDK does most of the work needed and provides classes for the Notification Content Extensions. When you create an extension, you only need to make it inherited from a suitable Synerise SDK class.

See the examples Notification Content Extensions with correct configuration:

Note: Remember about correct configuration in your extension’s \*.plist file. See Notification Content Extensions in the Sample Swift App.

Application implementation

Pass your app group identifier to the SDK (Set up App Group Identifier) and add custom categories in your application.

You have to create notifications categories with the right identifiers. The identifiers must be taken from the Synerise SDK constants. This does not affect button names.

Synerise.settings.notifications.appGroupIdentifier = "YOUR_APP_GROUP_IDENTIFIER"

let singleMediaCategory = UNNotificationCategory(identifier: SNRSingleMediaContentExtensionViewControllerCategoryIdentifier, actions: [], intentIdentifiers: [], options: [])

let carouselPrevious = UNNotificationAction(identifier: SNRCarouselContentExtensionViewControllerPreviousItemIdentifier, title: "Previous", options: [])
let carouselAction = UNNotificationAction(identifier: SNRCarouselContentExtensionViewControllerChooseItemIdentifier, title: "Go!", options: UNNotificationActionOptions.foreground)

let carouselNext = UNNotificationAction(identifier: SNRCarouselContentExtensionViewControllerNextItemIdentifier, title: "Next", options: [])

let carouselCategory = UNNotificationCategory(identifier: SNRCarouselContentExtensionViewControllerCategoryIdentifier, actions: [carouselPrevious, carouselAction, carouselNext], intentIdentifiers: [], options: [])

UNUserNotificationCenter.current().setNotificationCategories([singleMediaCategory, carouselCategory])

Single Media implementation

import UIKit
import UserNotifications
import UserNotificationsUI
import SyneriseSDK

class NotificationViewController: SingleMediaContentExtensionViewController, UNNotificationContentExtension {

  func didReceive(_ notification: UNNotification) {
    Synerise.settings.notifications.appGroupIdentifier = "YOUR_APP_GROUP_IDENTIFIER"

    self.contentViewIsScrollable = false
    self.imageContentMode = .scaleAspectFit

    setSyneriseNotification(notification)
  }

  func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
    setSyneriseNotificationResponse(response, completionHandler: completion)
  }
}
Parameter Type Default Description
contentViewIsScrollable Bool true This parameter specifies if vertical scroll is enabled. If false, content is adjusted to screen height.
imageContentMode UIViewContentMode UIViewContentModeScaleAspectFill This parameter sets the rendering mode of an image
import UIKit
import UserNotifications
import UserNotificationsUI
import SyneriseSDK

class NotificationViewController: CarouselContentExtensionViewController, UNNotificationContentExtension {

  func didReceive(_ notification: UNNotification) {
    Synerise.settings.notifications.appGroupIdentifier = "YOUR_APP_GROUP_IDENTIFIER"

    self.imageContentMode = .scaleAspectFit

    setSyneriseNotification(notification)
  }

  func didReceive(_ response: UNNotificationResponse, completionHandler completion: @escaping (UNNotificationContentExtensionResponseOption) -> Void) {
    setSyneriseNotificationResponse(response, completionHandler: completion)
  }
}
Parameter Type Default Description
imageContentMode UIViewContentMode UIViewContentModeScaleAspectFill This parameter sets the rendering mode of images
😕

We are sorry to hear that

Thank you for helping improve out documentation. If you need help or have any questions, please consider contacting support.

😉

Awesome!

Thank you for helping improve out documentation. If you need help or have any questions, please consider contacting support.