Advanced : App Customization on iOS

This article will explain how to customize and override the behavior of the iOS SDK. This will allow you to achieve a better user experience and integration into your app.

The SDK allows you to execute yourself the actions and also to prevent the execution of an action if you consider that the current environment or context is not adapted at the moment the rule is triggered.

Default Behavior

If you are not clear about how the SDK behaves by default then you should read the Contextual Interaction Rules section of this Knowledge Base again.

Implement the UbuduSDKDelegate

In order to customize the behavior of the SDK you need to implement the SDK delegate and provide a reference on it to the SDK.

Declare that your class (like your AppDelegate) implements the UbuduSDKDelegate protocol
@interface AppDelegate : UIResponder <UIApplicationDelegate, UbuduSDKDelegate>

Set the delegate reference of the SDK
[UbuduSDK sharedInstance].delegate = self;

Preventing Action Execution

The following methods are called before the corresponding action is executed. If you haven't implemented the method then the SDK will execute the action, otherwise the choice will depend on the value your method returns.

- (BOOL)ubudu:(UbuduSDK *)ubuduSDK shouldExecuteLocalNotificationRequest:(UILocalNotification *)notification triggeredBy:(UbuduTriggerSource)triggeredBy;

- (BOOL)ubudu:(UbuduSDK *)ubuduSDK shouldExecuteOpenWebPageRequest:(NSURL *)url triggeredBy:(UbuduTriggerSource)triggeredBy;

- (BOOL)ubudu:(UbuduSDK *)ubuduSDK shouldExecuteOpenPassbookRequest:(NSURL *)passbookUrl triggeredBy:(UbuduTriggerSource)triggeredBy;

To prevent a type of action of being executed simply implement the corresponding method and return NO if you consider it's not a good time to interact with the user.

Note that it is strongly not recommended to execute the action in these method. Read the next section if you want to know how to customize the execution of the actions.

Custom Action Execution

If the default way of executing a specific type of actions doesn't match your needs you can override the execution of this type of actions. To do so you need to implement the following methods in your delegate.

Local Notification

- (void)ubudu:(UbuduSDK *)ubuduSDK executeLocalNotificationRequest:(UILocalNotification *)notification triggeredBy:(UbuduTriggerSource)triggeredBy;

For your information the SDK uses by default [[UIApplication sharedApplication] presentLocalNotificationNow:] to execute a local notification action. It also proceeds to the replacement of the placeholders in the notification message.

In order to take decision on what should be done, you can retrieve your payload object which is located in the userInfo dictionary of the local notification.

Example of implementation:

AppDelegate.m
- (void)ubudu:(UbuduSDK *)ubuduSDK executeLocalNotificationRequest:(UILocalNotification *)notification triggeredBy:(UbuduTriggerSource)triggeredBy
{
    NSDictionary *payload = [notification.userInfo objectForKey:@"payload"];
    NSString *notifType = [payload objectForKey:@"type"];
    if (notifType != nil && [notifType isEqualToString:@"prepareOrder"]) {
        // If the notification contains a custom payload that we want to handle differently
        [self sendOrderToPreparation];
    } else {
        // Present the notification to the user as usual. Will call application:didReceiveLocalNotification: if app is currently in foreground.
        [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
    }
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
    // Send back to the SDK the notification (that may have been received in background)
    // So it can trigger the right action (passbook or web view for example)
    [[UbuduSDK sharedInstance] executeLocalNotificationActions:notification];
    // Clear the received notification
    [application cancelLocalNotification:notification];
    application.applicationIconBadgeNumber--;
}

Open Web Page

- (void)ubudu:(UbuduSDK *)ubuduSDK executeOpenWebPageRequest:(NSURL *)url triggeredBy:(UbuduTriggerSource)triggeredBy;

Open Passbook

For your information by default the user is presented a modal PKAddPassesViewController configured with your pass. The user can then add the pass to its passbook or dismiss the view controller.

- (void)ubudu:(UbuduSDK *)ubuduSDK executeOpenPassbookRequest:(NSURL *)passbookUrl triggeredBy:(UbuduTriggerSource)triggeredBy;

Note that if you only want to specify with which view controller the web view or passbook controller should be presented you can set the presentationViewController property of the SDK.

By default the SDK uses [UIApplication sharedApplication].keyWindow.rootViewController to present the web view or passbook controller but will not be able to present it if a modal view controller is already being presented.

For example :

[UbuduSDK sharedInstance].presentationViewController = self;

The Ubudu SDK also allows you to use information that is present in your application to customize the content presented to your users (using the user properties) and to target only part of them (using the tags).

User Properties

You can use the user properties to customize the message of your notifications. The SDK will replace the placeholders defined in ubudu Manager. See the Create Contextual Interaction Rules article for placeholder insertion syntax.

Set the user properties

You can specify the properties of the user currently using your application when initializing the SDK by creating an instance of the UbuduUser class and pass it to the SDK.

You may use the following initializer:

- (id)initWithID:(NSString *)userID withProperties:(NSDictionary *)properties;

Here is a full example :

NSString *userID = @"your_user_id";
NSString *userName = @"John Doe";
[UbuduSDK sharedInstance].appNamespace = @"your_app_namespace";
[UbuduSDK sharedInstance].user = [[UbuduUser alloc] initWithID:userID withProperties:@{@"userName":userName}];
NSError *error = nil;
BOOL started = [[UbuduSDK sharedInstance] start:&error];

If you want to change the properties when the SDK is already started then you can just re-assign the properties property of your UbuduUser instance.

NSString *userName = @"John Doe";
[UbuduSDK sharedInstance].user.properties = @{@"userName":userName};

The SDK will take care of updating everything seamlessly.

Tags

Tags are very similar to user properties but fulfill a different role. The goal is to be able to target an interaction rule to only a subset of your users based on arbitrary criteria.

This feature works as following :
- You set some relevant information that you want to use to define a user segment to target in the SDK in the form of tags (think of them as keywords). - In the Ubudu manager you add a boolean expression that uses the tags previously set in the Conditions of the rule you want to restrict to the user segment.

Set the tags

Tags can be either set when initializing the SDK

NSString *userID = @"your_user_id";
NSString *gender = @"female";
NSString *ageBracket = @"under_25";
[UbuduSDK sharedInstance].appNamespace = @"your_app_namespace";
[UbuduSDK sharedInstance].user = [[UbuduUser alloc] initWithID:userID withProperties:nil tags:@[gender, ageBracket]];
NSError *error = nil;
BOOL started = [[UbuduSDK sharedInstance] start:&error];

Or if the SDK is already started and you want to update the tags

NSString *gender = @"female";
NSString *ageBracket = @"under_30";
[UbuduSDK sharedInstance].user.tags = @[gender, ageBracket];

As for the user properties, the SDK will take care of updating everything and will load or unload new rules by following the new criteria defined by the updated tags.

Target a user segment in a rule

Go to the edition page of your rule in the manager and set the Conditions field to a boolean expression that uses the tags set in the application.

target_user_segment.png

For example a valid expression is: "female" and "under_25".
A little more complex one could be: ("female" and "under_25") or "under_20"