In-App Messaging & Rich Push

This topic provides steps for configuring your mobile app to handle In-App Messaging and Rich Push. When completed, In-App campaigns and Push campaigns with Rich Message content can be managed from within Responsys without requiring further app updates, and these messages will display properly in your mobile app.

In this topic:

About In-App Messaging and Rich Push

In-App Messaging is a great way to connect with users who are engaged with your app. It provides you an opportunity to drive conversion at a moment of your choosing. For example, during a user’s birthday week, you could provide the user with a congratulatory promotion should the user open your app. Another example might be presenting the user with a free shipping offer when the user comes into your app to check the shipping status of a previous order.

Marketers can also enhance their Push campaigns by choosing to have the mobile app open a Rich Push message when a user opens the notification. Push notifications with a Rich Push message are useful when you want to prompt a user to open the app and view the message, rather than relying on a different user action. For example, instead of relying on the user going into the app during his or her birthday week, a "Happy Birthday" push notification sent on the user's birthday could cause the user to tap the notification and display the congratulatory promotion.

How Does In-App Messaging Work?

Depending on the version of the SDK you are using, and that your mobile app users have installed, In-App Messaging works a bit differently.

How message delivery works for Responsys 19A / 6.40.0 SDK Update and later

Oracle Responsys and the SDK have changed how In-App Campaign Messaging works for mobile apps built with the 6.40.0 and onwards SDK versions. In 19A, we enhanced the Responsys server and SDK infrastructure to use a pull-based mechanism from the SDK instead of relying on "Silent Push Notifications". The trigger for the SDK to retrieve messages from the Responsys servers is an "App Launch" (when a user brings the app to the foreground). The SDK enforces a five minute interval between "In-App Message retrievals" from the Responsys servers. Retrieved messages are cached locally and displayed whenever an In-App event is triggered.

For example:

  • If a user launches the app at 12:00PM after the app was closed for more than 24 hours on the previous day, the SDK makes an In-App Message Retrieval call to the Responsys servers to retrieve all pending In-App Messages for the app user and caches the messages locally. The next time the SDK can make an In-App Message Retrieval call to the Responsys servers is at 12:05PM, and only if the user launches the app again.

  • If the next time the user launches the app is at 1:00PM, all In-App Messages sent to this user between 12:00PM and 1:00PM are retrieved by the SDK and cached locally. The next In-App Messages Retrieval call by the SDK to the Responsys servers will be on the next app launch, if the app launch occurs after 1:05PM.

Some of the benefits of this feature include:

  • Size of the Rich HTML creative content used in In-app campaigns is no longer limited to 3.5 KB.

  • In-app messages will be delivered to mobile apps on iOS devices, even if the mobile app has been "force quit" by the mobile app user.

To enable this feature:

  1. Request access to the "Redesigned In-app Backend" feature by contacting your Customer Success Manager or logging in to My Oracle Support and creating a service request. This feature is currently released under our Controlled Availability program.

  2. You must build your mobile app with the 19A/6.40.0 SDK or greater.

How message delivery works before Responsys 19A / 6.40.0 SDK Update

In mobile apps built with an SDK released before the 19a / 6.40.0 SDK Update, In-App Messages are delivered to your app on the user’s device by Responsys via a silent push notification. (Backward compatibility is preserved for mobile app users who have not upgraded their mobile apps to those using the 6.40.0 or later SDK.) Upon receipt, the Push IO SDK saves the message content, the time range that the message is valid, and the name of the trigger that causes the message to display.

This feature was released in 18D. If your app was built with the 18D SDK, you need to enable the feature in your code, using the SDK's setInAppFetchEnabled method (as described in Step 5 of the Steps for Integrating In-App Messaging and Rich Push into Your iOS App section below). and in 18D you needed to turn on the below step was required. In 19A, we enabled this by default in the SDK.

How it works after the message is present on the mobile device

When a user engages with the mobile app, the app has your In-App Message ready for display. Five presentation styles are supported:

Note: Interstitial, Banner-Header, and Banner-Footer InApp views will be available in Oracle Responsys SDK 6.52 and later.

  • Fullscreen style messages take up the entirety of the device's screen.

Fullscreen IAM image

Alert-style IAM image

  • Interstitial style messages take up the entirety of the device's screen without any padding.

Interstitial IAM image with status bar

  • Banner-Header style messages are banner views at the top of the device's screen with a default height of 100px.

Banner-Header IAM image with status bar

  • Banner-Footer style messages are banner views at the bottom of the device's screen with a default height of 100px.

Banner-Footer IAM image

Within the Responsys In-App Message designer, the presentation style is selected. The SDK takes care of displaying the message in the appropriate manner, once the trigger action occurs. Also, at that time, the message is removed from the user’s device and won’t be displayed again.

There are standard mobile app events built-in to the SDK, that will be triggered automatically. For example, when a user opens your app, the $ExplicitAppOpen event will be triggered.

You can also define custom triggers associated to events that occur in your mobile app code. To avoid app updates, it’s a good idea to work with your marketing team to determine what set of custom triggers should be coded into the app. For example, a commerce app might have an "add_to_cart" trigger or a game might have a "reached_level_10" trigger.

How Does Rich Push Work?

"Rich Push" refers to the combination of a Push notification and a rich content message. When a marketer uses the Push campaign designer to create the Push notification message, the marketer can choose a notification action of "Open Rich Message." The marketer composes the Rich Push message in HTML format and may also include images and personalization, as long as the entire Push notification does not exceed the provider's limit.

Unlike In-App Messages, which are sent silently, a Rich Push is a standard push notification that contains an action that is triggered immediately when the app user taps that notification. When the user taps the notification, the system opens the app (if it is not already open), brings it to the foreground, and then displays the Rich Push message similarly to a "splash screen."

Steps for Integrating In-App Messaging and Rich Push into Your iOS App

As an app developer, there are a few steps you will need to take to fully integrate In-App Messaging and Rich Push into your iOS app. We will cover each of these steps in detail:

  1. Set up a special Push IO URL Scheme and forward URL handling to the Push IO SDK.
  2. Enable In-app Messaging: Perform either step [2.1] Receive In-app messages through silent push or step [2.2] Let SDK pre-fetch In-app messages.
  3. Define optional custom triggers (In-App Messaging only).

Step 1 - Set up the URL Scheme and Forward URL Handling to the Push IO SDK

When an app event is triggered, the corresponding action is passed through inter-app communication using custom URL schemes. The action URI is invoked with the openURL system call. This section describes how your application will tell iOS that it handles the URL scheme expected by the Push IO SDK, and forward handling of that URL to the Push IO SDK.

Note: You may have other reasons to use custom URL schemes in your app, such as supporting deep-linking to specific areas of your app. Importantly, please do not use the Push IO URL scheme for these other purposes. You may set up your own URL scheme for such purposes.

The Push IO URL scheme contains your Push IO API Key and takes the format of pio-YOUR_API_KEY. For example, if your API Key is njj1jjNNGg then the application identifier would be: pio-njj1jjNNGg.

Note: You can look up the Push IO API Key in the config_pushio.json or config_debug_pushio.json file. You can also find it by accessing the Mobile App Developer Console, where the API Key is displayed alongside your platforms. (Legacy API Keys may have an underscore followed by additional characters; for example, njj1jjNNGg_abc123. If using a legacy API Key, remove the underscore and any characters that follow it.)

The SDK will only handle a URL if it matches the Push IO URL scheme and if the caller of openURL is a trusted source. By default, sources are untrusted except when originating from within your app.

For your app to respond to a URL scheme, you must first add the Push IO scheme to your app's Info.plist. You can add it in Xcode by going to your project, selecting the target for your app, selecting the Info tab, and finding URL Types:

Adding custom URL Scheme, screenshot

Now that iOS knows how to find your app via the custom URL scheme, you need to implement handling for the openURL system call. Implement the following method in your application delegate and call the corresponding forwarding method provided by the SDK:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
   BOOL handled = [[PushIOManager sharedInstance] openURL:url options:options];
   return handled;
}						
func application(_ app: UIApplication, open url: URL,options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool 
{ 
    let handled = PushIOManager.sharedInstance().open(url, options: options)
    return handled;
}				

In Scene-based apps, you need to implement handling for the openURLContext system call. Implement the following method in your scene delegate and call the corresponding forwarding method provided by the SDK:

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
 {
    [[PushIOManager sharedInstance] openURLContexts:URLContexts];
 }					
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
 {
     PushIOManager.sharedInstance().openURLContexts(URLContexts)
 }	

Note: This API is available for the Oracle Responsys SDK 6.50.0 and later.

As you use In-App Messaging to open the In-App dialogs in the application, you will need to update your application’s plist to handle the changes in canOpenURL. (When omitted, the mobile app can't display In-App Messages or Rich Push content correctly.) This is described in the Apple Developer video topic Privacy and Your App.

Add the following to your application’s plist (replace _PUSHIO_API_KEY_ with your own API key):

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>
        pio-PUSHIO_API_KEY
    </string>
</array>				

OR add visually (in plist) by adding LSApplicationQueriesSchemes as an array and add pio-PUSHIO_API_KEY as first item in it (replace _PUSHIO_API_KEY_ with your own API key):

iOS upgrade adding app ID to LSApplicationQueriesSchemes image

For more information on URL schemes and inter-app communication, refer to Apple's Inter-App Communication guide.

Step 2 - Enable In-app Messaging

To enable your mobile app for In-app Messaging, use the steps below.

  • For mobile apps built with SDK versions before 6.40.0, use step 2.1.
  • For mobile apps built with SDK version 6.40.0 or greater, use step 2.2. (This is for mobile apps that are newly using In-app Messaging. It is also for mobile apps that are being upgraded to the latest SDK. In both cases, your Responsys account must be enabled for the "Redesigned In-app Backend" feature.)

[2.1] Receive In-app messages through silent push: Enable Background Remote Notifications (for mobile apps using versions of the SDK before 6.40.0/19A)

In-App Messages are sent to your app silently, in the background, so that app events are ready to be triggered when the user returns to the app. On iOS, background push notification functionality is disabled by default. To opt your app into receiving push notifications in the background, you must enable Remote Notifications as a background mode. This allows your app to be launched in the background to receive a notification.

You can enable it in Xcode by going to your project, selecting the target for your app, selecting the Capabilities tab, turning on Background Modes, and checking Remote Notifications:

Enabling remote notifications, screenshot

The entry point in your App Delegate for Remote Notifications received in background mode is different than for other types of push notifications. Add the new callback to your App Delegate so the SDK properly receives the In-App Message.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
  [[PushIOManager sharedInstance] didReceiveRemoteNotification:userInfo fetchCompletionResult:UIBackgroundFetchResultNewData fetchCompletionHandler:completionHandler];
}						
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Swift.Void){
    PushIOManager.sharedInstance().didReceiveRemoteNotification(userInfo, fetchCompletionResult: UIBackgroundFetchResult.newData, fetchCompletionHandler: completionHandler)
}				

iOS has some unique characteristics pertaining to Remote Notifications and Background Modes. This type of notification, when the steps in this section are implemented, does not require explicit end user opt-in the way a normal iOS push notification does. This is because silent push notifications do not present user interface elements. Your users can, however, disable Background App Refresh in the iOS Settings, under the settings for your app. If Background App Refresh is turned off they will not receive In-App Messages from you.

Additionally, to receive silent push notifications (and thus In-App Messages), your app must be running in the foreground or background. This means that if a user quits your app via the iOS app switcher ("force quits" your app), then the In-App Message will not be saved on the device for that user. After a force-quit, the user must launch the app again for the app to become eligible to receive the next silent notification.

[2.2] Let SDK pre-fetch In-app messages (for mobile apps using versions of the SDK 6.40.0/19A and greater)

As of the 6.40.0/19A version, the SDK is capable of fetching In-App Messages from Responsys after an In-App Message campaign launches. Thus, when an In-App trigger happens in the mobile app, it is fetched from the locally stored In-app messages.

Fetching In-App Messages is preferred over receiving the In-App Messages through push notifications (steps mentioned above), because the silent push method requires the application to run (either in foreground or in background) at the time that the silent push notification is triggered from the Responsys server.

Important: Before you begin, ensure that the "Redesigned In-app Backend" feature is enabled for your account. If you update your mobile app to SDK version 6.40.0 or later, but do not enable the "Redesigned In-app Backend" feature in your app, then this will impact your marketers' ability to target all mobile app users immediately once you finally enable the "Redesigned In-app Backend" feature. Mobile app users will have to update their app to the app version that implements "Redesigned In-app Backend" feature before In-app Messages can be delivered to them.

To enable In-app message fetching: Your mobile application must call the setInAppMessageFetchEnabled API to let the SDK pre-fetch the In-app messages. It must be called after SDK is successfully configured.

[[PushIOManager sharedInstance] setInAppMessageFetchEnabled:YES]; // pass NO to disable the inApp pre-fetch						
PushIOManager.sharedInstance().setInAppMessageFetchEnabled(true) //// pass false to disable the inApp pre-fetch				

 

Step 3 - Define Custom Triggers (In-App Messaging Only)

As described earlier, In-App Messages are displayed when the associated trigger occurs in your app. The Push IO SDK offers a standard trigger, called $ExplicitAppOpen, which tracks when a user opens your app directly.

You can also develop custom triggers, which are named mobile app events that you track in the code. These triggers are activated when the user takes a specific action in your mobile app. Custom trigger names are case sensitive and they should not start with a "$", which is reserved namespace for standard triggers.

For example, perhaps you want to define a custom trigger for when the user visits the "Sign In" page of your app. This might give your marketing team an opportunity to show an In-App Message articulating the benefits of signing in. In this example, you would define the custom trigger like this:

[[PushIOManager sharedInstance] trackEvent:@"signup_page"];
PushIOManager.sharedInstance().trackEvent("signup_page")

Your Responsys Account Administrator needs to know the case sensitive name of the custom trigger, so that they can be added to the Responsys Manage Push App Configuration Page. This step is required for the custom triggers to be available within the Responsys In-App Campaign Workbook.

In the above example, you tell your Responsys Account Administrator that when a user enters the app's sign-in page, the custom trigger signup_page is activated.

Step 4 - Customize InApp message Display (Optional - available in 6.52 SDK and later)

  • SDK supports hiding status bar for Interstitial and Banner-Header InApp views.

    Interstitial IAM image without status bar
    Banner-Header IAM image without status bar

    To hide status bar use the following API:

     [[PushIOManager sharedInstance] setStatusBarHiddenForIAMBannerInterstitial:YES]; //To hide status bar.
    PushIOManager.sharedInstance().setStatusBarHiddenForIAMBannerInterstitial(true) //To hide status bar.

     

  • SDK defined default height for banner view is 100px, minimum height is 100px and maximum height is 200px. User can customise the banner height to any value within this given range as per requirements.

    To customise the banner view height use the following API:

      [[PushIOManager sharedInstance] setInAppMessageBannerHeight:bannerHeight]; //To set custom height for banner view.
    PushIOManager.sharedInstance().setInAppMessageBannerHeight(bannerHeight) //To set custom height for banner view.

     

Step 5 - Delay Rich Push message Display (Optional - available in 6.47 SDK and later)

Rich-push messages are displayed at app`s launch. This can be an issue for apps that have a onboarding screen or an intermediate screen like a login screen or customised splash screen where the app may not be ready to show a rich-push message. With release 20D/6.47, the SDK now supports delaying the rich-push message display.

For this, enable the delaying rich push using the following API:

[[PushIOManager sharedInstance] setDelayRichPushDisplay:YES]; //To enable/disable delaying rich push
PushIOManager.sharedInstance().setDelayRichPushDisplay(true) //To enable/disable delaying rich push

 

Parameter : Flag for enabling or disabling the delayed rich push display. If YES, the rich push on press on the notification would be saved by the SDK and only be shown on the API call for showRichPushMessage (defined below) If set to NO, it will work as the original Rich Push Message feature.

After the setDelayRichPushDisplay enabled, you can use the showRichPushMessage API to trigger the rich push message display from any of your landing screens.

[[PushIOManager sharedInstance] showRichPushMessage];
PushIOManager.sharedInstance().showRichPushMessage()

 

Call isRichPushDelaySet API to check whether the flag for delayed rich push is set or not. The API returns YES if the delayed rich push display feature is enabled in the app, and returns NO if application wants to follow the legacy rich push display method.

[[PushIOManager sharedInstance] isRichPushDelaySet]; //returns YES if rich push delay is set
PushIOManager.sharedInstance().isRichPushDelaySet() //returns true if rich push delay is set

Troubleshooting your In-App Message Implementation using SDK Logs

If you are experiencing issues with In-App messages, check your SDK logs to determine the cause. Use the following sample SDK logs to determine what your issue might be.

SDK Event SDK Log Example
App launch happened, but the In-App fetch request cannot be made to Responsys because the 5 minute interval rule is not met.
Not making IAM fetch request. Nextfetch time is not reached
In-App fetch request made to Responsys.
Fetch IAM initiated: 1
In-App fetch response received from Responsys with no messages for user.
{
  "event_actions": [
  ],
  "next_req_time": "2019-10-04T10:57:57Z"
}
In-App fetch response received from Responsys with messages for user.
{
  "event_actions": [
    {
      "ei": "ABEpAGqW-UBXAc3QM_JJBBpyCqmYomZPk3P5JfFkXOH6wiReKY21uP3_COy88",
      "p_event_action": {
        "start_ts": "2019-02-11T10:49:15Z",
        "event_type": "$ExplicitAppOpen",
        "action_uri": "pio-ABEgGFd_CNo9NOL_87c6k2GzI://show_iam?style=fullscreen&url=",
        "expiry_ts": "2019-02-18T10:49:15Z"
      }
    }
  ],
  "next_req_time": "2019-02-12T05:53:05Z"
}