Customization

All of Braze’s in-app message types are highly customizable across messages, images, Font Awesome icons, click actions, analytics, editable styling, custom display options, and custom delivery options. Multiple options can be configured on a per in-app message basis from within the dashboard. Braze additionally provides multiple levels of advanced customization to satisfy a variety of use cases and needs.

Key-value pair extras

ABKInAppMessage objects may carry key-value pairs as extras. These are specified on the dashboard when creating a campaign. Key-value pairs can be used to send data down along with an in-app message for further handling by your app.

Setting delegates

In-app message display and delivery customizations can be accomplished in code by setting our optional delegates.

In-app message delegate

The ABKInAppMessageUIDelegate delegate can be used to receive triggered in-app message payloads for further processing, receive display lifecycle events, and control display timing.

Set your ABKInAppMessageUIDelegate delegate object on the Braze instance by calling:

1
[[Appboy sharedInstance].inAppMessageController.inAppMessageUIController setInAppMessageUIDelegate:self];
1
Appboy.sharedInstance()?.inAppMessageController.inAppMessageUIController?.setInAppMessageUIDelegate?(self)

See our in-app message sample app for an example. Note that if you are not including Braze’s UI library in your project (uncommon), this delegate is unavailable.

Core in-app message delegate

If you are not including Braze’s UI library in your project and would like to receive triggered in-app message payloads for further processing or custom display in your app, implement the ABKInAppMessageControllerDelegate protocol.

Set your ABKInAppMessageControllerDelegate delegate object on the Braze instance by calling:

1
[Appboy sharedInstance].inAppMessageController.delegate = self;
1
Appboy.sharedInstance()?.inAppMessageController.delegate = self

You can alternatively set your core in-app message delegate at initialization time via appboyOptions using the key ABKInAppMessageControllerDelegateKey.

1
2
3
4
[Appboy startWithApiKey:@"YOUR-API_KEY"
          inApplication:application
      withLaunchOptions:options
      withAppboyOptions:@{ ABKInAppMessageControllerDelegateKey : self }];
1
2
3
4
Appboy.start(withApiKey: "YOUR-API-KEY",
                 in:application,
                 withLaunchOptions:launchOptions,
                 withAppboyOptions:[ ABKInAppMessageControllerDelegateKey : self ])

Customizing orientation

Setting orientation for all in-app messages

To set a fixed orientation for all in-app messages, you can set the supportedOrientationMask property on ABKInAppMessageUIController. Add the following code after your app’s call to startWithApiKey:inApplication:withLaunchOptions::

1
2
3
4
// Set fixed in-app message orientation to portrait.
// Use UIInterfaceOrientationMaskLandscape to display in-app messages in landscape
id<ABKInAppMessageUIControlling> inAppMessageUIController = [Appboy sharedInstance].inAppMessageController.inAppMessageUIController;
((ABKInAppMessageUIController *)inAppMessageUIController).supportedOrientationMask = UIInterfaceOrientationMaskPortrait;
1
2
3
4
5
// Set fixed in-app message orientation to portrait
// Use .landscape to display in-app messages in landscape
if let controller = Appboy.sharedInstance()?.inAppMessageController.inAppMessageUIController as? ABKInAppMessageUIController {
  controller.supportedOrientationMask = .portrait
}

Following this, all in-app messages will be displayed in the supported orientation, regardless of device orientation. Please note that the device orientation must also be supported by the in-app message’s orientation property in order for the message to display. For more information, see the section below.

Setting orientation per in-app message

You may alternatively set orientation on a per-message basis. To do this, set an in-app message delegate. Then, in your beforeInAppMessageDisplayed: delegate method, set the orientation property on the ABKInAppMessage. For example:

1
2
3
4
5
// Set inAppMessage orientation to portrait
inAppMessage.orientation = ABKInAppMessageOrientationPortrait;

// Set inAppMessage orientation to landscape
inAppMessage.orientation = ABKInAppMessageOrientationLandscape;
1
2
3
4
5
  // Set inAppMessage orientation to portrait
  inAppMessage.orientation = ABKInAppMessageOrientation.portrait

  // Set inAppMessage orientation to landscape
  inAppMessage.orientation = ABKInAppMessageOrientation.landscape

In-app messages will not display if the device orientation does not match the orientation property on the in-app message.

For iPads, in-app messages will appear in the style of the user’s preferred orientation regardless of actual screen orientation.

Custom handling in-app message display

When the ABKInAppMessageControllerDelegate is set, the following delegate method will be called before in-app messages are displayed:

1
- (ABKInAppMessageDisplayChoice) beforeInAppMessageDisplayed:(ABKInAppMessage *)inAppMessage;
1
func beforeInAppMessageDisplayed(inAppMessage: ABKInAppMessage!) -> ABKInAppMessageDisplayChoice

If you have only implemented ABKInAppMessageUIDelegate, the following UI delegate method will be called instead:

1
- (ABKInAppMessageDisplayChoice) beforeInAppMessageDisplayed:(ABKInAppMessage *)inAppMessage withKeyboardIsUp:(BOOL)keyboardIsUp;
1
func beforeInAppMessageDisplayed(inAppMessage: ABKInAppMessage!, withKeyboardIsUp keyboardIsUp: Bool) -> ABKInAppMessageDisplayChoice

You can customize in-app message handling by implementing this delegate method and returning one of the following values for ABKInAppMessageDisplayChoice:

ABKInAppMessageDisplayChoice Behavior
ABKDisplayInAppMessageNow The message will be displayed immediately
ABKDisplayInAppMessageLater The message will be not be displayed and will be placed back on the top of the stack
ABKDiscardInAppMessage The message will be discarded and will not be displayed

You can use the beforeInAppMessageDisplayed: delegate method to add in-app message display logic, customize in-app messages before Braze displays them, or opt-out of Braze’s in-app message display logic and UI entirely.

For an implementation example, see our In-App Message Sample Application.

Overriding in-app messages before display

If you would like to alter the display behavior of in-app messages, you should add any necessary display logic to your beforeInAppMessageDisplayed: delegate method. For example, you might want to display the in-app message from the top of the screen if the keyboard is currently being displayed, or take the in-app message data model and display the in-app message yourself.

If the IAM campaign is not displaying when the session has been started, make sure you have the necessary display logic added to your beforeInAppMessageDisplayed: delegate method. This allows the IAM campaign to display from the top of the screen even if the keyboard is being displayed.

Hiding the status bar during display

For Full and HTML in-app messages, the SDK will attempt to place the message over the status bar by default. However, in some cases the status bar may still appear on top of the in-app message. As of version 3.21.1 of the iOS SDK, you can force the status bar to hide when displaying Full and HTML in-app messages by setting ABKInAppMessageHideStatusBarKey to YES within the appboyOptions passed to startWithApiKey:.

Logging impressions and clicks

Logging in-app message impressions and clicks is not automatic when you implement completely custom handling (i.e. if you circumvent Braze’s in-app message display by returning ABKDiscardInAppMessage in your beforeInAppMessageDisplayed:). If you choose to implement your own UI using our in-app message models, you must log analytics with the following methods on the ABKInAppMessage class:

1
2
3
4
// Registers that a user has viewed an in-app message with the Braze server.
- (void) logInAppMessageImpression;
// Registers that a user has clicked on an in-app message with the Braze server.
- (void) logInAppMessageClicked;
1
2
3
4
// Registers that a user has viewed a in-app message with the Braze server.
func logInAppMessageImpression()
// Registers that a user has clicked on a in-app message with the Braze server.
func logInAppMessageClicked()

Furthermore, you should be logging button clicks on subclasses of ABKInAppMessageImmersive (i.e., Modal and Full in-app messages):

1
2
// Logs button click analytics
- (void)logInAppMessageClickedWithButtonID:(NSInteger)buttonID;
1
2
// Logs button click analytics
func logInAppMessageClickedWithButtonID(buttonId: NSInteger)

Customizing in-app message behavior on click

The inAppMessageClickActionType property on the ABKInAppMessage defines the action behavior after the in-app message is clicked. This property is read-only. If you want to change the in-app message’s click behavior, you can call the following method on ABKInAppMessage:

1
[inAppMessage setInAppMessageClickAction:clickActionType withURI:uri];
1
inAppMessage.setInAppMessageClickAction(clickActionType: clickActionType, withURI: uri)

The inAppMessageClickActionType can be set to one of the following values:

ABKInAppMessageClickActionType On-Click Behavior
ABKInAppMessageDisplayNewsFeed The News Feed will be displayed when the message is clicked, and the message will be dismissed. Note: The uri parameter will be ignored, and the uri property on the ABKInAppMessage will be set to nil.
ABKInAppMessageRedirectToURI The given URI will be displayed when the message is clicked, and the message will be dismissed. Note: The uri parameter cannot be nil.
ABKInAppMessageNoneClickAction The message will be dismissed when clicked. Note: The uri parameter will be ignored, and the uri property on the ABKInAppMessage will be set to nil.

Customizing in-app message body clicks

The following ABKInAppMessageUIDelegate delegate method is called when an in-app message is clicked:

1
- (BOOL) onInAppMessageClicked:(ABKInAppMessage *)inAppMessage;
1
func onInAppMessageClicked(inAppMessage: ABKInAppMessage!) -> Bool

Customizing in-app message button clicks

For clicks on in-app message buttons and HTML in-app message buttons (i.e., links), ABKInAppMessageUIDelegate includes the following delegate methods:

1
2
3
4
5
6
- (BOOL)onInAppMessageButtonClicked:(ABKInAppMessageImmersive *)inAppMessage
                             button:(ABKInAppMessageButton *)button;

- (BOOL)onInAppMessageHTMLButtonClicked:(ABKInAppMessageHTML *)inAppMessage
                             clickedURL:(nullable NSURL *)clickedURL
                               buttonID:(NSString *)buttonID;
1
2
3
4
5
func onInAppMessageButtonClicked(inAppMessage: ABKInAppMessageImmersive!,
                                 button: ABKInAppMessageButton) -> Bool

func onInAppMessageHTMLButtonClicked(inAppMessage: ABKInAppMessageHTML!,
                                     clickedURL: URL, buttonID: String) -> Bool

Each method returns a BOOL value to indicate if Braze should continue to execute the click action.

To access the click action type of a button in a delegate method, you can use the following code:

1
2
3
4
5
6
7
if ([inAppMessage isKindOfClass:[ABKInAppMessageImmersive class]]) {
      ABKInAppMessageImmersive *immersiveIAM = (ABKInAppMessageImmersive *)inAppMessage;
      NSArray<ABKInAppMessageButton *> *buttons = immersiveIAM.buttons;
      for (ABKInAppMessageButton *button in buttons) {
         // Button action type is accessible via button.buttonClickActionType
      }
   }
1
2
3
4
5
6
if inAppMessage is ABKInAppMessageImmersive {
      let immersiveIAM = inAppMessage as! ABKInAppMessageImmersive;
      for button in inAppMessage.buttons as! [ABKInAppMessageButton]{
        // Button action type is accessible via button.buttonClickActionType
      }
    }

When an in-app message has buttons, the only click actions that will be executed are the ones on the ABKInAppMessageButton model. The in-app message body will not be clickable even though the ABKInAppMessage model will have the default click action (“News Feed”) assigned.

Dismiss modal on outside tap

The default value is NO. This determines if the modal in-app message will be dismissed when the user taps outside of the in-app message.

To enable outside tap dismissals, add a dictionary named Braze to your Info.plist file. Inside the Braze Dictionary add the DismissModalOnOutsideTap boolean subentry and set the value to YES. Note that prior to Braze iOS SDK v4.0.2, the dictionary key Appboy must be used in place of Braze.

Example Info.plist contents:

1
2
3
4
5
<key>Braze</key>
<dict>
	<key>DismissModalOnOutsideTap</key>
	<boolean>YES</boolean>
</dict>

You can also enable the feature at runtime by setting ABKEnableDismissModalOnOutsideTapKey to YES in appboyOptions.

Description of dismiss modal on outside tap

DismissModalOnOutsideTap Description
YES Modal in-app messages will be dismissed on outside tap
NO Default, modal in-app messages will not be dismissed on outside tap

Display in-app messages in a custom view controller

In-app messages can also be displayed within a custom view controller which you pass to Braze. Braze will animate the customized in-app message in and out, as well as handle analytics of the in-app message. The view controller must meet the following requirements:

  • It must be a subclass or an instance of ABKInAppMessageViewController.
  • The view of the returned view controller should be an instance of ABKInAppMessageView or its subclass.

The following UI delegate method is called every time an in-app message is offered to ABKInAppMessageViewController to allow the app would like to pass a custom view controller to Braze for in-app message display:

1
- (ABKInAppMessageViewController *)inAppMessageViewControllerWithInAppMessage:(ABKInAppMessage *)inAppMessage;
1
func inAppMessageViewControllerWithInAppMessage(inAppMessage: ABKInAppMessage!) -> ABKInAppMessageViewController!

All of our in-app message view controllers are open-sourced. You can use subclasses or categories to customize the display or behavior of in-app messages.

See the in-app message view controllers for more details.

Custom in-app message triggering

By default, in-app messages are triggered by event types that are logged by the SDK. If you would like to trigger in-app messages by server-sent events you are also able to achieve this.

To enable this feature you would send a silent push to the device which allows the device to log an SDK based event. This SDK event would subsequently trigger the user-facing in-app message.

Step 1: Handle silent push and key-value pairs

Add the following code within the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method:

1
2
3
4
5
6
- (void)handleExtrasFromPush:(NSDictionary *)userInfo {
  NSLog(@"A push was received.");
  if (userInfo !=nil && userInfo[@"IS_SERVER_EVENT"] !=nil && userInfo[@"CAMPAIGN_NAME"]!=nil) {
    [[Appboy sharedInstance] logCustomEvent:@"IAM Trigger" withProperties:@{@"campaign_name": userInfo[@"CAMPAIGN_NAME"]}];
  }
 };
1
2
3
4
5
6
func handleExtras(userInfo: [AnyHashable : Any]) {
  NSLog("A push was received");
  if userInfo != nil && (userInfo["IS_SERVER_EVENT"] as? String) != nil && (userInfo["CAMPAIGN_NAME"] as? String) != nil {
    Appboy.sharedInstance()?.logCustomEvent("IAM Trigger", withProperties: ["campaign_name": userInfo["CAMPAIGN_NAME"]])
  }
}

When the silent push is received an SDK recorded event “In-App Message Trigger” will be logged against the user profile. Note that these In-App Messages will only trigger if the silent push is received while the application is in the foreground.

Step 2: Create a push campaign

Create a silent push campaign which is triggered via the server sent event. For details on how to create a silent push campaign, refer to our article on silent push notifications.

Server Event Trigger

The push campaign must include key-value pair extras which indicate that this push campaign is sent with the intention to log an SDK custom event. This event will be used to trigger the in-app message:

IAM Silent Push

The code within the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method checks for key IS_SERVER_EVENT and will log an SDK custom event if this is present.

You can alter either the event name or event properties by sending the desired value within the key-value pair extras of the push payload. These extras can be used as the parameter of either the event name or as an event property when logging the custom event.

Step 3: Create an in-app message campaign

Create your user visible in-app message campaign from within Braze’s dashboard. This campaign should have an Action Based delivery, and be triggered from the custom event logged from within the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method.

In the example below the specific in-app message to be trigger has been configured by sending the event property as part of the initial silent push.

IAM Push Trigger Example

Due to a push message being used to record an SDK logged custom event, Braze will need to store a push token for each user to enable this solution. For iOS users, Braze will only store a token from the point that a user has been served the OS’s push prompt. Before this, the user will not be reachable using push and the above solution will not be possible.

Method declarations

For additional information see the following header files:

Implementation samples

See AppDelegate.m, ViewController.m and CustomInAppMessageViewController.m in the in-app message sample app.

WAS THIS PAGE HELPFUL?
New Stuff!