AppboyKit (also known as the Objective-C SDK) is no longer supported and has been replaced by the Swift SDK. It will no longer receive new features, bug fixes, security updates, or technical support—however, messaging and analytics will continue to function as normal. To learn more, see Introducing the New Braze Swift SDK.
Looking for the basic in-app message developer integration guide? Find it here.
In-app messaging implementation guide
This optional and advanced implementation guide covers in-app message code considerations, three custom use cases built by our team, and accompanying code snippets. Visit our Braze Demo repository here! This implementation guide is centered around a Swift implementation, but Objective-C snippets are provided for those interested. Looking for HTML implementations? Take a look at our HTML template repository!
Code considerations
The following guide offers an optional custom developer integration to use in addition to default in-app messages. Custom view controllers are included with each use case, offering examples to extend functionality and natively customize the look and feel of your in-app messages.
ABKInAppMessage subclasses
The following code snippet is a UI delegate method from the Braze SDK that determines what subclass view you want to populate your in-app message with. We cover a basic implementation in this guide and show how the full, slide up, and modal subclasses can be implemented in captivating ways. Note that if you want to set up your custom view controller, you must set up all other in-app message subclasses. After you have a solid understanding of the concepts behind subclassing, check out our use cases to start implementing in-app messaging subclasses.
ABKInAppMessage subclasses
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
extension AppboyManager: ABKInAppMessageUIDelegate {
func inAppMessageViewControllerWith(_ inAppMessage: ABKInAppMessage) -> ABKInAppMessageViewController {
switch inAppMessage {
case is ABKInAppMessageSlideup:
return slideupViewController(inAppMessage: inAppMessage) //Custom Method
case is ABKInAppMessageModal:
return modalViewController(inAppMessage: inAppMessage) //Custom Method
case is ABKInAppMessageFull:
return fullViewController(inAppMessage: inAppMessage) //Custom Method
case is ABKInAppMessageHTML:
return ABKInAppMessageHTMLViewController(inAppMessage: inAppMessage)
default:
return ABKInAppMessageViewController(inAppMessage: inAppMessage)
}
}
}
ABKInAppMessage subclasses
1
2
3
4
5
6
7
8
9
10
11
12
13
- (ABKInAppMessageViewController *)inAppMessageViewControllerWithInAppMessage:(ABKInAppMessage *)inAppMessage {
if ([inAppMessage isKindOfClass:[ABKInAppMessageSlideup class]]) {
return [self slideupViewControllerWithInAppMessage:inAppMessage]; //Custom Method
} else if ([inAppMessage isKindOfClass:[ABKInAppMessageModal class]]) {
return [self modalViewControllerWithInAppMessage:inAppMessage]; //Custom Method
} else if ([inAppMessage isKindOfClass:[ABKInAppMessageFull class]]) {
return [self fullViewControllerWithInAppMessage:inAppMessage]; //Custom Method
} else if ([inAppMessage isKindOfClass:[ABKInAppMessageHTML class]]) {
return [[ABKInAppMessageHTMLViewController alloc] initWithInAppMessage:inAppMessage];
} else {
return [[ABKInAppMessageViewController alloc] initWithInAppMessage:inAppMessage];
}
}
Use cases
We’ve provided three use cases below. Each use case offers a detailed explanation, relevant code snippets, and a look into how in-app messages may look and be used in the Braze dashboard:
Custom slide-up in-app message
While building out your slide-up in-app message, you may notice you aren’t able to modify the placement of the message using default methods. Modification like this is made possible by subclassing the ABKInAppMessageSlideupViewController
and overriding the offset
variable with your own custom variable. The image to the right shows an example of how this can be used to adjust your slide-up in-app messages.
Visit the SlideFromBottomViewController
to get started.
Adding additional behavior to our default UI
Update offset
variable
Update the offset
variable and set your own offset to suit your needs.
1
2
3
func setSlideConstraint() {
offset = 0
}
1
2
3
4
5
6
7
8
override var offset: CGFloat {
get {
return super.offset
}
set {
super.offset = newValue + adjustedOffset
}
}
Version 3.34.0 or earlier
Update slideConstraint
variable
The slideConstraint
public variable comes from the superclass ABKInAppMessageSlideupViewController
.
1
2
3
func setSlideConstraint() {
slideConstraint?.constant = bottomSpacing
}
1
2
3
private var bottomSpacing: CGFloat {
return AppboyManager.shared.activeApplicationViewController.topMostViewController().view.safeAreaInsets.bottom
}
Visit the Braze Demo repository for the topMostViewController()
function.
Update offset
variable
Update the offset
variable and set your own offset to suit your needs.
1
2
3
- (void)setOffset {
self.offset = 0;
}
1
2
3
4
5
6
7
- (CGFloat)offset {
return [super offset];
}
- (void)setOffset:(CGFloat)offset {
[super setOffset:offset + [self adjustedOffset]];
}
Version 3.34.0 or earlier
Update slideConstraint
variable
The slideConstraint
public variable comes from the superclass ABKInAppMessageSlideupViewController
.
1
2
3
- (void)self.setSlideConstraint:(NSLayoutConstraint *)slideConstraint {
slideConstraint.constant = bottomSpacing;
}
1
2
3
- (CGFloat)bottomSpacing {
return [AppboyManager shared].activeApplicationViewController.topMostViewController.view.safeAreaInsets.bottom;
}
Override and set custom constraint
Override beforeMoveInAppMessageViewOnScreen()
and set your own custom constraint value to suit your needs. The original value is set in the superclass.
1
2
3
4
override func beforeMoveInAppMessageViewOnScreen() {
super.beforeMoveInAppMessageViewOnScreen()
setOffset()
}
Version 3.34.0 or earlier
1
2
3
override func beforeMoveInAppMessageViewOnScreen() {
setSlideConstraint()
}
Override and set custom constraint
Override beforeMoveInAppMessageViewOnScreen()
and set your own custom constraint value to suit your needs. The original value is set in the superclass.
1
2
3
4
- (void)beforeMoveInAppMessageViewOnScreen {
[super beforeMoveInAppMessageViewOnScreen];
[self setOffset];
}
Version 3.34.0 or earlier
1
2
3
- (void)beforeMoveInAppMessageViewOnScreen {
[self setSlideConstraint:self.slideConstraint];
}
Adjust constraint for device orientation
Adjust the respective value in viewWillTransition()
because the subclass assumes responsibility for keeping the constraint synced during layout changes.
Custom modal in-app message
An ABKInAppMessageModalViewController
can be subclassed to leverage a UIPickerView
offering engaging ways to collect valuable user attributes. The custom modal in-app message allows you to use Connected Content or any available list to display and capture attributes from a dynamic list of items.
You can interject your own views into subclassed in-app messages. This example showcases how a UIPickerView
can be utilized to extend the functionality of an ABKModalInAppMessageViewController
.
Visit the ModalPickerViewController to get started.
Dashboard configuration
To set up a modal in-app message in the dashboard, you must provide a list of items formatted as a comma-separated string. In our example, we use Connected Content to pull a JSON list of team names and format them accordingly.
In the key-value pairs, provide an attribute_key
; this key, along with the user’s selected value, will be saved to their user profile as a custom attribute. Your custom view logic must handle user attributes sent to Braze.
The extras
dictionary in the ABKInAppMessage
object allows you to query for a view_type
key (if any) that signals the correct view to display. It’s important to note that in-app messages are configured on a per-message basis, so custom and default modal views can work harmoniously.
Using view_type
for UI display behavior
Query the extras
dictionary for your view_type
to load the desired subclassed view controller.
1
2
3
4
5
6
7
8
func modalViewController(inAppMessage: ABKInAppMessage) -> ABKInAppMessageModalViewController {
switch inAppMessage.extras?[InAppMessageKey.viewType.rawValue] as? String {
case InAppMessageViewType.picker.rawValue:
return ModalPickerViewController(inAppMessage: inAppMessage)
default:
return ABKInAppMessageModalViewController(inAppMessage: inAppMessage)
}
}
Using view_type
for UI display behavior
Query the extras
dictionary for your view_type
to load the desired subclassed view controller.
1
2
3
4
5
6
7
8
9
10
11
- (ABKInAppMessageModalViewController *)modalViewControllerWithInAppMessage:(ABKInAppMessage *)inAppMessage {
InAppMessageData *inAppMessageData = [[InAppMessageData alloc] init];
NSString *key = [inAppMessageData rawValueForInAppMessageKey:InAppMessageKeyViewType];
NSString *viewType = [inAppMessageData rawValueForInAppMessageViewType:InAppMessageViewTypePicker];
if ([inAppMessage.extras objectForKey:key] && [inAppMessage.extras[key] isEqualToString:viewType]) {
return [[ModalViewController alloc] initWithInAppMessage:inAppMessage];
} else {
return [[ABKInAppMessageModalViewController alloc] initWithInAppMessage:inAppMessage];
}
}
Override and provide custom view
Override loadView()
and set your own custom view to suit your needs.
1
2
3
4
5
6
7
override var nibname: String{
return "ModalPickerViewController"
}
override func loadView() {
Bundle.main.loadNibNamed(nibName, owner: self, options: nil)
}
Override and provide custom view
Override loadView()
and set your own custom view to suit your needs.
1
2
3
4
- (void)loadView {
NSString *nibName = @"ModalPickerViewController";
[[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
}
Format variables for a dynamic list
Before reloading the UIPickerView
components, the inAppMessage
message variable is output as a String. This message must be formatted as an array of items to be displayed correctly. As an example, this can be achieved using components(separatedBy: ", ")
.
1
2
3
4
5
6
override func viewDidLoad() {
super.viewDidLoad()
items = inAppMessage.message.separatedByCommaSpaceValue
pickerView.reloadAllComponents()
}
Format variables for PickerView
Before reloading the UIPickerView
components, the inAppMessage
message variable is output as a String. This message must be formatted as an array of items to be displayed correctly. For example, this can be achieved using componentsSeparatedByString
.
1
2
3
4
5
6
- (void)viewDidLoad {
[super viewDidLoad];
self.items = [[NSArray alloc] initWithArray:[self.inAppMessage.message componentsSeparatedByString:@", "]];
[self.pickerView reloadAllComponents];
}
Assign custom attribute
Using the subclass, after a user presses submit, pass the attribute with its corresponding selected value to Braze.
1
2
3
4
5
@IBAction func primaryButtonTapped(_ sender: Any) {
guard let item = selectedItem, !item.isEmpty, let attributeKey = inAppMessage.extras?[InAppMessageKey.attributeKey.rawValue] as? String else { return }
AppboyManager.shared.setCustomAttributeWithKey(attributeKey, andStringValue: item)
}
Assign custom attribute
Using the subclass, after a user presses submit, pass the attribute with its corresponding selected value to Braze.
1
2
3
4
5
6
7
8
- (IBAction)primaryButtonTapped:(id)sender {
InAppMessageData *inAppMessageData = [[InAppMessageData alloc] init];
NSString *key = [inAppMessageData rawValueForInAppMessageKey:InAppMessageKeyAttributeKey];
if (self.selectedItem.length > 0 && [self.inAppMessage.extras objectForKey:key]) {
[[AppboyManager shared] setCustomAttributeWithKey:self.inAppMessage.extras[key] andStringValue:self.selectedItem];
}
}
Interesting in leveraging our custom modal in-app messages to share videos across FaceTime? Check out our SharePlay in-app message implementation guide.
Custom full in-app message
Use custom full in-app messages to create interactive, user-friendly prompts to collect valuable customer data. The example to the right shows an implementation of the custom full in-app message reimagined as an interactive push primer with notification preferences.
Visit the FullListViewController
to get started.
Dashboard configuration
To set up a custom full in-app message in the dashboard, you must provide a list of your tags formatted as a comma-separated string.
In the key-value pairs, provide an attribute_key
; this key, along with the user’s selected values, will be saved to their user profile as a custom attribute. Your custom view logic must handle user attributes sent to Braze.
Intercepting in-app message touches
Intercepting in-app message touches is crucial in making the custom full in-app message buttons function correctly. By default, the ABKInAppMessageImmersive
adds a tap gesture recognizer onto the message, so users can dismiss messages without buttons. By adding a UISwitch
or button to the UITableViewCell
view hierarchy, the touches now get handled by our custom view. As of iOS 6, buttons and other controls have precedence when working with gesture recognizers, making our custom full in-app message work as it should.