Introduction

The Kumulos SDK is an open source project hosted on Github and can be found at https://github.com/Kumulos/KumulosSdkSwift.

This guide assumes you have completed the steps from the introduction and have configured your Apple Identifier, Capabilities and Provisioning Profile from that guide and covers the following integration steps:

  1. Integrate the SDK and configuring your project for APNS capability

  2. Initializing the SDK components within your project and register for push notifications

  3. Register the Kumulos InstallationID with your backend to provide a link between the device and your users represented in your CRM backend for later targeting of notifications.

  4. Sending a test push notification from your Unica app and receiving on the device.

  5. Custom analytics events

  6. Optional advanced behavior for native push notifications

  7. Optional advanced behavior for rich In-App messages

Integration

Both Carthage and CocoaPods integration instructions are available in the GitHub repo.

Get started with Cocoapods

Get started with Carthage

Get started with Swift Package Manager

Simply follow the instructions for your preferred dependency manager to add the KumulosSDK framework to the project.

Add a Notification Service extension

In order to support all the features of the Apple Push Notifications Service your app must have a notification service extension in order to allow some limited processing of the notification on receipt, before the operating system presents it to the user.

This is a second build target added to your existing xcode project by going to your project info screen and clicking the '+' button at the footer.

Build targets

From the popup window, select the Notification Service Extension template for your new project and click 'Next'.

Service Extension Template

On the final window add an appropriate name for your extension and click 'Finish'.

Service Extension Configuration

If using CocoaPods, add the following to your Podfile and run pod install.

target 'KumulosNotificationServiceExtension' do
  pod 'KumulosSdkSwiftExtension', '~> 8.4.0'
end

The template for the project will have created a file named NotificationService.swift automatically, replace its content with the following lines:


import UserNotifications
import KumulosSDKExtension

class NotificationService: UNNotificationServiceExtension {
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        KumulosNotificationService.didReceive(request, withContentHandler: contentHandler)
    }
}

The Kumulos SDK helper functions will automatically add picture attachments and buttons to the notification content.

Configure your app capabilities and entitlements

In your app project settings use the "+ capability" button to add the App Groups, Background Modes and Push Notifications capabilities.

In your Notification Extension use the "+ capability" button to add the App Groups capability.

In both projects the App Groups capability should be configured to share the same group, this must exactly match the group defined in your Identifiers capabilities earlier.

group.{your.bundle.identifier}.kumulos

In your app project the Background Modes should have the "Remote Notifications" mode checked.

Test your configuration

At this point you can test deploy your app onto a device to ensure that your entitlements and capabilities are configured correctly.

Initialization

To configure the SDK for use you need to initialize it with your app's credentials, this should be done early in your application startup.

import UIKit
import KumulosSDK

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    let builder = KSConfigBuilder(apiKey: "your-api-key", secretKey: "your-secret-key")
        .enableInAppMessaging(inAppConsentStrategy: InAppConsentStrategy.AutoEnroll)

    Kumulos.initialize(config: builder.build())

    // Override point for customization after application launch.
    return true
  }
}

The Kumulos SDK automatically supports badges, buttons and image content, although please note that due to iOS limitations badges are not set when app is in the foreground.

Registering for push notifications

iOS requires explicit user permission to receive notifications, when you consider it appropriate you can trigger the prompt to allow notifications by calling:

Kumulos.pushRequestDeviceToken()

This helper will prompt the OS to request the user to accept push notifications with the badge, alert, and sound options.

When the user accepts, the Kumulos SDK will automatically handle registration of the push token with the Kumulos backend.

Registering with your CRM

Installation ID

When initialized for the first time, the Kumulos SDK will create a unique identifier for the app installation that initialized the SDK, this identifier can be used later to target push notifications to a specific device.

In order to retrieve this installation ID, simply access the class variable:

let installId = Kumulos.installId;

Once you have the installation ID, you can send it to your app's CRM backend to be used later for push targeting.

User Association

If your app makes use of an identifier to uniquely tell which user is signed into a device (for example a primary key integer or UUID, or an email address), you can send this identifier to Kumulos for later push targeting via the same key.

Kumulos.associateUserWithInstall(userIdentifier: "unique-user-identifier")

Sending a test

TODO: Unica system / screenshots.

Event Tracking

Kumulos allows you to track custom analytics events in order to observe your users activity in your app, allowing you to analyse behavior and optimize journeys to ensure your users are getting the full benefit of your app's features.

To track a custom analytics event, use Kumulos.trackEvent as follows:

Kumulos.trackEvent(eventType: "product.purchased", properties: [
    "productId": 404
])

Each event and its properties must be less than 250 KiB in size for the event to be tracked.

Event tracking is available offline as all events are persisted locally before being synced to the server in batches in the background.

A similar method trackEventImmediately will immediately start an event sync rather than waiting for the next time the app is backgrounded.

Push Notification Advanced features

Handling notification opened events

When a user interacts with your push message, either by tapping the notification itself, or an included action button, the pushOpenedHandlerBlock will be called, in this block you can provide further behavior to handle custom actions.

 let builder = KSConfigBuilder(apiKey: "your-api-key", secretKey: "your-secret-key")
    .setPushOpenedHandler(pushOpenedHandlerBlock: { (notification : KSPushNotification) -> Void in
        //- Inspect notification data and do work.
        if let action = notification.actionIdentifier {
            print("User pressed an action button.")
            print(action)
            print(notification.data)
        } else {
            print("Just an open event.")
        }
    })

Kumulos.initialize(config: builder.build())

Handling background data pushes

When you send a push with the content-available flag set on the notification this will allow your app to be woken up to process the push notification in the background, triggering any required behavior in your app without launching into the foreground.

If you set a title & message then the notification will be silent and nothing will be shown to the user in the notification center, however you can also provide a title and message in order to trigger behavior and then notify the user.

The content-available flag will trigger the application:didReceiveRemoteNotification:fetchCompletionHandler: application delegate, from here you can inspect the notification payload and perform any actions required.

// iOS9 handler for push notifications
// iOS9+10 handler for background data pushes (content-available)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // userInfo["aps"]["content-available"] will be set to 1
        // userInfo["custom"]["a"] will contain any additional data sent with the push

        completionHandler(UIBackgroundFetchResult.noData)
    }

In-App Advanced Features

If you would like your users to opt-in to receive In-App messages you can configure the SDK during initialization to make opt-in explicit by setting the strategy, then calling the SDK helper to manage their consent.

// Set the strategy to require explicit user consent when initializing the SDK
let builder = KSConfigBuilder(apiKey: "your-api-key", secretKey: "your-secret-key")
    .enableInAppMessaging(inAppConsentStrategy: InAppConsentStrategy.ExplicitByUser)
Kumulos.initialize(config: builder.build())

// Call this method to update consent based on user preferences / settings screen etc.
KumulosInApp.updateConsent(forUser: true)

Deep-linking for In-App

In-App messages allow you to hand-off to native application screens via deep-linking action buttons. When tapped, these buttons pass control to the defined deep-link handler, including their defined data payload (configured in the In-App message composer for the action button).

If you want to handle deep-links with custom data payloads as part of an In-App message you can add a handler block to your configuration options during SDK initialization.

let builder = KSConfigBuilder(apiKey: "your-api-key", secretKey: "your-secret-key")
    .enableInAppMessaging(inAppConsentStrategy: InAppConsentStrategy.AutoEnroll)
    .setInAppDeepLinkHandler(inAppDeepLinkHandlerBlock: { buttonPress in
        let deepLink = buttonPress.deepLinkData
        let messageData = buttonPress.messageData

        // TODO: Inspect the deep link & message data to perform relevant action
    })

Using the In-App Inbox

In-app messages can optionally be persisted in a user-level inbox for later retrieval. This allows you to build features such as loyalty rewards or expiring coupons into your app. Regardless of whether they are stored in the inbox, the maximum amount of in-apps stored on a device is 50 (the oldest messages exceeding this limit will be evicted).

Retrieve messages

To retrieve a list of messages from the user's inbox and present the first in the list, see the following example:

let inboxItems = KumulosInApp.getInboxItems()
KumulosInApp.presentInboxMessage(item: inboxItems[0])

Mark as read

To mark a single or all inbox messages as read:

//single
let inboxItems = KumulosInApp.getInboxItems()
KumulosInApp.markAsRead(item: inboxItems[0])

//all
KumulosInApp.markAllInboxItemsAsRead()

Delete message

You can also delete an in-app message from inbox:

let inboxItems = KumulosInApp.getInboxItems()
KumulosInApp.deleteMessageFromInbox(item: inboxItems[0]);

Inbox updated handler

In order to be notified when inbox changes you may set up a handler. The handler fires on the main thread when one of the following happens to an in-app with inbox:

  • message fetched from server
  • message opened
  • message marked as read
  • message deleted
  • message evicted (expires or limit of stored messages exceeded)

You can use it as follows:

KumulosInApp.setOnInboxUpdated(inboxUpdatedHandlerBlock: {() -> Void in
    let inboxItems = KumulosInApp.getInboxItems()

    //refresh your inbox
});

Note, you can do KumulosInApp.setOnInboxUpdated(inboxUpdatedHandlerBlock: nil) when you stop being interested in inbox updates.

Get inbox summary

You can retrieve inbox summary as follows:

 KumulosInApp.getInboxSummaryAsync(inboxSummaryBlock: {(summary:InAppInboxSummary?) -> Void in
    if let inboxSummary = summary {
        print("total: \(inboxSummary.totalCount) unread: \(inboxSummary.unreadCount)")
    }
});

The method runs asynchronously and calls back on the main thread.

Get inbox item's image URL

Each inbox item may have an image associated with it. getImageUrl returns a URL to the image of specified width or nil if there is no image.

let inboxItems = KumulosInApp.getInboxItems()

let url = inboxItems[0].getImageUrl();

Changelog

1.1.0

  • Add In-App messaging to configuration
  • Add analytics event tracking
  • Break out advanced features into In-App and Push Notification headings, add In-App advanced config and Inbox features.
  • Standardize headings

1.0.0

  • Initial integration guide