Default actions for mobile app messages

Your app users can choose two predefined actions in response to a notification being opened or a specific action being chosen from a dynamic action category message you create.

The three standard, or predefined, actions are:

  • url – opens Safari for the website that is specified in the “value” key.
  • dial – opens a dialer to call the number that is specified in the “value” key. Tip: You must have iCloud set up on both devices to use “dial.” If you dial on an iPad, nothing happens unless you set up iCloud. If you test with an app without iCloud, the dialer does not show.
  • openApp – opens the app.
    The default standard actions, such as url, dial, and openApp, can be overridden by a custom plug-in. In fact, this is specifically what WebActionPlugin does. It takes over the default action of opening a URL in Safari and instead opens the page in a WebView in the app.

Dynamic action categories are created in real time by the SDK when a special payload is received and background processing is enabled for the app. They are defined in the “category-actions” section of the payload and include standard actions. You can use them with custom actions that you define by overriding those two predefined actions. The specific action is chosen by supplying a “type” key in either the “notification-action” or “category-actions” payload.

Remember: All actions, default and custom, send a Universal Behavior (UB) to the IBM Silverpop® servers.

Adding a deep link for a url action
You can add a deep link that is tied to a url action or through a custom action.

  1. Integrate the iOS SDK with a deep link sample app.
  2. Set up the deep linking schema.
  3. Send a mobile app message with a url type that activates your schema.
{"aps": {
  "alert":"Testing.. (3)",
  "badge":1,"sound":"default"},
  "notification-action":{
    "type":"url",
    "value":"mdldemo://"
  }
}

Register action types

You can plug in to action handling by registering your own actions, or custom actions. You can register for handling any action type, and you can override the default handling of any predefined type.

Custom actions methods are defined by the developer and run when an action is selected by the user with the registered type value. An example of this would be for the developer to create a method that handles viewProduct action types. The developer registers that method with the MCEActionRegistry system. Then, a push message comes in with the “notification-action” set to type=”viewProduct”, and the app user opens the mobile app message. Additionally, both custom actions and standard actions (url, dial, openApp) can be within the “category-actions” section of the payload, which would run in response to a user selecting the specific button that is attached to the action.

There are two types of dynamic action category plug-ins: the Action Menu plug-in and the Web Action plug-in. The Action Menu plug-in displays a list of available actions as the target of an action. It registers with the showactions dynamic action type. The Web Action plug-in overwrites the url dynamic action type with the ability to display the specified web page in the app instead of opening it in Safari.

The iOS SDK provides three custom actions that you can implement:

  • Custom action using a single argument type payload
  • Custom action using an action payload and a full iOS payload
  • Custom action for text entry fields

Example: custom action using a single argument type

You can customize your dynamic action category types by registering your object and selector with the MCEActionRegistry class. See the following code example

-(instancetype)init
{
if(self=[super init])
{
MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
[registry registerTarget: [self sharedInstance] withSelector:@selector(customAction:) forAction: @"customAction"];
}
return self;
]

 When a notification is opened with the customAction type, your custom method is run. 

-(void)customAction:(NSDictionary*)action
{
// Do something neat with the action payload here!
}

Example: custom action using an action payload and full iOS payload

This custom action is demonstrated in the Action Menu plug-in in the sample app. The following code sample shows how to register the custom action.

{code}
MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
[registry registerTarget: [self sharedInstance] withSelector:@selector(executeAction:withPayload:) forAction: @"custom"];
{code}

The following code shows how to implement the custom action.

{code}
-(void)executeAction:(NSDictionary*)action withPayload:(NSDictionary*)payload
{
// the action dictionary contains the action that is being executed, eg: {"type": "custom", "value":"foo"}
// the payload dictionary includes the full APNS payload, e.g. {"aps": {...}}
}
{code}

Requirements for custom action types

When a custom action type for a mobile app message is used, the marketer must also include the destructive, authentication, and foreground keys in the action definition.

The “aps” section is used for system displayed notifications.

The {{type}} of action can be anything. Predefined action types include “dial” and “url”. If the {{type}} is “rich”, “dial”, or “url”, then the destructive is false, authentication is false, and foreground is true; otherwise, those attributes need to be included.

The {{value}} depends on the type of action. If the type is “dial”, then the value is a phone number to be dialed. If the type is “url”, then the value is the url that is to be viewed. If the type is “rich”, then the value is the rich content ID to be displayed. When the type is anything else, it is handled by the plug-in that is defined for that type.

The {{name}} of the action is the title that shows on the button. If the {{type}} is not “rich”, “dial”, or “url”, the following keys need to be defined in the action:

  • {{destructive}} can be either true or false. This sets the style of the action button.
  • {{authentication}} can be either true or false. This allows actions to be performed with the device is locked when true.
  • {{foreground}} can be either true or false. If it is true, then the app is opened when a selection is made. If it is false, then the app is not opened.

Notification Service Dynamic Action Categories

In iOS 10, Apple introduced the notification service extension that allows applications to intercept and pre-process remote notifications before they are presented to the user.
For information about media attachments and dynamic action categories, see Enabling media attachment and multiple action support.

Dynamic action categories are sets of actions in mobile app messages that are dynamically generated by the SDK in real time when a special payload is received, if the device is running iOS 10 (or later). Dynamic action categories are not predefined in the application binary.

Note: Dynamic action categories are not supported in Xamarin for iOS.

Developers define actions for dynamic action categories in the “category-actions” section of the payload. The payload includes the category-actions key, as well as a mutable-content flag in the normal aps payload. It can also include a category-name key if the name of the dynamic category must match a specific identifier. The category-name key is sometimes used for dynamic notification presentation.

  • The mutable-content flag allows the application’s notification service to process the push message before it is delivered to the user.
  • The category-actions key includes a list of action buttons that are assigned to a temporary category at run time.
  • The aps key includes the text, sound, and badge of the notification.
  • After the temporary category is created, the SDK assigns the category name to the notification and passes the category name to the operating system so that it can be displayed to the user.
  • The category-name key overrides the random category name that is generated by the SDK with a category name that you specify. Add this key to your payload when you want to use iOS 10 (and later) features that require a predefined category name.

Tip: Always include a notification-action value so a default action can be executed when the notification is opened. Category actions only open if a user expands the push message and selects an alternative action button.

{
"category-actions": [ { "name": "IBM_CA", "type": "url", "value": "https://ibm.ca" },
{ "name": "IBM", "type": "url", "value": "https://ibm.com"} ],
"notification-action": { "type": "url", "value": "https://ibm.com" },
"aps": { "alert": "Message", "sound": "default", "mutable-content": 1 },
"category-name": "content-extension"
}

Static action categories

Because all application delegate methods are forwarded to your defined appDelegateClass, you can implement any standard application delegate methods, including handling static action categories, in any way you want. Static action categories are compiled into the app binary itself. They are sets of predefined buttons that have predefined actions behind them. Those are entirely implemented by the developer and do not interact with the SDK at all.

Note: Static action categories are not supported in Xamarin for iOS.

If you are using simple notifications and want to create static action categories with background actions, you must turn on Remote notifications in your XCode project. Go to the Background Modes section of the Capabilities tab for your target, and select Remote notifications.

  • Implement the standard method for handling the category callbacks in your AppDelegate class.
    #pragma mark Process Static Category
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier
    forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler
    {
    NSLog(@"%@ button clicked", identifier);
    completionHandler();
    }
  • Register the categories that you want to handle in the APNS registration call in your AppDelegate.
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
    {
    UIMutableUserNotificationAction* acceptAction = [[UIMutableUserNotificationAction alloc] init];
    acceptAction.identifier = @"Accept";
    acceptAction.title = @"Accept";
    acceptAction.activationMode = UIUserNotificationActivationModeForeground;
    acceptAction.destructive = false;
    acceptAction.authenticationRequire = false;

    UIMutableUserNotificationAction* rejectAction = [[UIMutableUserNotification alloc] init];
    rejectAction.identifier = @"Reject";
    rejectAction.title = @"Reject";
    rejectAction.activationMode = UIUserNotificationActivationModeForeground;
    rejectAction.destructive = false;
    rejectAction.authenticationRequired = false;

    UIMutableUserNotificationCategory* category = [UIMutableUserNotificationCategory alloc] init];
    category.identifier = @"example";
    [category setActions:@[acceptAction, rejectAction] forContext: UIUserNotificationActionContextDefault];
    [category setActions:@[acceptAction, rejectAction] forContext: UIUserNotificationActionContextMinimal];

    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationType Badge |
    UIUserNotificationTypeSound |
    UIUserNotificationTypeAlert categories: [NSSet setWithObject: category ] ];
    [application registerUserNotificationSettings:settings];
    [application registerForRemoteNotification];
    }
    }

Action plug-ins for enhanced notifications

There are four action plug-ins you can use to enhance your mobile app message:

  • Add to Calendar
  • Snooze
  • Add to Passbook
  • Web Action
  • iOS image Carousel (For details, see here.)

You can use any of the plug-ins by adding the set of files for the plug-in and registering it. Each plug-in requires certain parameters.

  • Add to Calendar plug-in 

    The Add to Calendar plug-in allows a user to add an event to the calendar. This action happens in the background without opening the calendar.

    {
    	"interactive": true/false,	// true = brings up interface to add event
    	"title": "<event title>", 	// text
    	"timeZone": "<timezone>", 	//  text (optional)
    	"startDate": "<the event start datetime>", 	// formatted like 2015-04-07T10:10:10Z
    	"endDate": "<the event and datetime>", 	// formatted like 2015-04-07T10:10:10Z
    	"description": "<event notes>", 	// text (saved to notes)
    	"type": "calendar"  	// constant
    }

    If the time or timezone fields are incorrect, the timezone of the device is used. You can show the calendar user interface for adding an item to the calendar by adding interactive = true or false in the payload. If false, it does it in the background. Calendar requires AddToCalendarPlugin.h and AddToCalendarPlugin.m.
    Note: For iOS 10 applications, add a description to NSCalendarsUsageDescription in the info.plist file that provides a reason to the user for allowing the app to add the calendar event.

  • Snooze plug-in 

    The Snooze plug-in allows a user to bring back the mobile app message after some time.

    {
    	"value": "<minutes to wait>",
    	"type": "snooze"        // Constant
    }
  • Add to Passbook plug-in 

    The Add to Passbook plug-in allows a user to add a pass to Passbook with a single click.

    {
        "value": "<url>"       // url of server that can vend the pass (https only)
        "type": "passbook"     // Constant
    }
  • Web Action plug-in 

    The Web Action plug-in allows a mobile app user to view a web page inside the app.

    {
    	"value": "<url>",	// Url of web page to show (https only)
    	"type": "displayWebView"	// Constant
    }
    

    Web Action requires the following files in the plugins/web-action folder: WebActionPlugin.h, WebActionPlugin.m, WebViewController.h, and WebViewController.m. Then, register it in the AppDelegate.

    The following example shows how to implement the plug-ins in your AppDelegate init method for iOS:

    -(instancetype)init
    {
        if(self = [super init])
        {
            [SnoozeActionPlugin registerPlugin];
        }
        return self;
    }
    

    You can also implement all four plug-ins:

    -(instancetype)init
    {
        if(self = [super init])
        {
            [SnoozeActionPlugin registerPlugin];
            [AddToCalendarPlugin registerPlugin];
            [AddToPassbookPlugin registerPlugin];
            [WebActionPlugin registerPlugin];
        }
        return self;
    }

Write your own plug-in

If you want to write your own plug-in, you can adapt the Example plug-in that ships with the SDK. For more information, see Creating custom actions for mobile app messages.

Action plug-in architecture overview

When an action is triggered, the system looks for handlers that match the types registered. You can use two types of action plug-in approaches: simple or advanced.

The simple method consists of modifying the main.m file to point to MCEAppDelegate and setting the AppDelegate class in the configuration file to your AppDelegate class name. When you use this method of integration, the MCEAppDelegate class runs all the required methods at their required integration points and passes over control to all calls back to your AppDelegate class. This works for any custom methods that you want to use because it proxys the callback to the AppDelegate class.

The plug-ins in the sample app are used by following this process. For the simple approach, drag all source files into the project. In the AppDelegate class, add the plug-in initialization code:

-(instancetype)init
{
    if(self = [super init])
    {
        [WebActionPlugin registerPlugin]; // if web action plugin is being used
        [ActionMenuPlugin registerPlugin]; // if action menu plugin is being used
    }
    return self;
}

You can register any action handlers that you want by implementing the following code.

  1. In the AppDelegate class, add the plug-in initialization code.
    -(instancetype)init
    {
        if(self = [super init])
        {
            MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
            [registry registerTarget: self withSelector:@selector(custom:) forAction: @"custom"];
        }
        return self;
    }
  2. Implement the custom action:
    -(void)showActionsMenu:(NSDictionary*)action
    {
        // Do something with action here
    }

You can use an alternative method that includes both the action payload and the rest of the APNs payload:

  1. In the AppDelegate class, add the plug-in initialization code.
    -(instancetype)init
    {
        if(self = [super init])
        {
            MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
            [registry registerTarget: self withSelector:@selector(custom:payload:) forAction: @"custom"];
        }
        return self;
    }
  2. Implement the custom action:
    -(void)showActionsMenu:(NSDictionary*)action payload:(NSDictionary*)payload
    {
        // Do something with action and payload here
    }

You can create a class that registers with the MCEActionRegistry system as shown in the following example for the WebActionPlugin.h file. The following example overrides the default handling of the url type with a web view inside the application instead of the default handling of opening Safari.

#import <Foundation/Foundation.h> 
#import <MobileEngagement/MobileEngagement.h>


@interface WebActionPlugin : NSObject
-(void)performAction:(NSDictionary*)action;
+(void)registerPlugin;
@end

The following example shows the WebActionPlugin.m file.

#import "WebActionPlugin.h"
#import "WebViewController.h"

@implementation WebActionPlugin

-(void)performAction:(NSDictionary*)action
{
    WebViewController * viewController = [[WebViewController alloc] initWithURL:[NSURL URLWithString:action[@"value"]]];
    UIWindow * window = [[UIApplication sharedApplication] keyWindow];
    [window.rootViewController presentViewController:viewController animated:TRUE completion:nil];
}

+(void)registerPlugin
{
    MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];

    [registry registerTarget: [self sharedInstance] withSelector:@selector(performAction:) forAction: @"url"];
}
+ (instancetype)sharedInstance
{
    static id sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
@end

Register the class in your AppDelegate at launch time, as shown in the following code:

-(instancetype)init
{
    if(self = [super init])
    {
        [WebActionPlugin registerPlugin];
    }
    return self;
}

The advanced method involves implementing certain methods on your AppDelegate class instead of using the previous instructions. You must implement the following methods:

-(void)applicationDidFinishLaunching:(UIApplication *)application
{
    [[MCESdk sharedInstance] handleApplicationLaunch];
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
    {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
        [application registerUserNotificationSettings:settings];
        [application registerForRemoteNotifications];
    }
}

-(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    [[MCESdk sharedInstance]registerDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler
{
    [[MCESdk sharedInstance] processCategoryNotification: userInfo identifier:identifier fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [[MCESdk sharedInstance] presentOrPerformNotification: userInfo];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    [[MCESdk sharedInstance] presentDynamicCategoryNotification: userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    [[MCESdk sharedInstance] presentOrPerformNotification: notification.userInfo];
}

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler
{
    [[MCESdk sharedInstance] processDynamicCategoryNotification: notification.userInfo identifier:identifier fetchCompletionHandler:completionHandler];
}

Payload formats

A payload is a property list that specifies how you want to alert your app user on their device and any custom data you provide. The property list is defined by a JSON dictionary object.
There are three types of payload formats you can include in the SDK:

  • Mobile app message with no action category – If you have a mobile app message with no action category, only one action is possible.
    {"aps" : {
    
                "alert" :  "Bob wants to play poker",
                "badge" : 5
            },
    
            "notification-action":{
               "type":{{type}},
    
               "value":{{value}}
           }
    
    }
  • Payloads for iOS 10 (and later) apps

    To use the iOS 10 (and later) features in push notifications you must configure several keys in iOS 10 payloads.

    For example, you might want to use Notification Content Extensions to add media attachments for images, sound, and video to push notifications. To add media attachments, add the mutable-content flag to the aps key in the iOS 10 payload and the media-attachment key to the root of the iOS 10 payload. The notification service extension downloads the media file from the URL that you specify in the media-attachment key of the payload and attaches the file to the message.

    Several keys that you can use in iOS payload include:

    • mutable-content – To enable iOS 10 apps to process media attachments that are displayed to the user, set this flag and specify a URL in the media-attachment key on the root of the payload. Example: “mutable-content”:1,
    • media-attachment – To enable the notification service extension to download a media attachment and attach the media file to a message, specify a URL for the attachment in the media-attachment field. Example: “media-attachment”: “https://url/to/BostonMap.png”
    • Titles and subtitles: You can add titles that are displayed at the top of notifications and subtitles that are displayed within notifications. The user pulls down the notification to view additional content, where the “below the fold” section of the alert is visible and available for user interaction. To add titles and subtitles to notifications, add the title field and subtitle field to the alert key in the iOS 10 payload.
      • title – To add a title to the notification, specify a notification title in the title field. Example: “title”: “Welcome to Boston”,
      • subtitle – To add a subtitle to the notification, specify a notification title in the subtitle field. Example: “subtitle”: “Thanks for using Rent-A-Car. Your rental is ready”,
    • category-name – To override random category names that are generated by the SDK, add the category-name key to your payload. This key enables you to use iOS 10 (and later) features, such as Notification Content Extensions, that require predefined compiled category names.
    • For information about best practices when specifying file sizes in media attachments, see Best practices for using images, videos, and audio.

    The following code example shows a basic iOS payload:

    {
      "aps": {
        "mutable-content":1,
        "alert":{
          "title": "Notification title",
          "subtitle": "Notification subtitle",
          "body": "Notification body"
        }
      },
      "media-attachment": "https://url/to/content.mpg"
      "notification-action": {"type":"url", "value": "http://ibm.com"}, 
      "category-actions": [{"name":"foo","type":"url", "value": "http://ibm.com"}], 
      "category-name": "content-extension" 
    }

    Go Back to the Mobile App Messaging home page.

    Join The Discussion

    Your email address will not be published. Required fields are marked *