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.
Deep linking for iOS
For introductory information on deep links, refer to our User Guide article. If you’re looking to implement deep links for the first time in your Braze app, the steps below will get you started.
This article includes information on News Feed, which is being deprecated. Braze recommends that customers who use our News Feed tool move over to our Content Cards messaging channel—it’s more flexible, customizable, and reliable. Check out the migration guide for more.
Step 1: Register a scheme
You must state a custom scheme in the Info.plist
file. The navigation structure is defined by an array of dictionaries. Each of those dictionaries contains an array of strings.
Use Xcode to edit your Info.plist
file:
- Add a new key,
URL types
. Xcode will automatically make this an array containing a dictionary calledItem 0
. - Within
Item 0
, add a keyURL identifier
. Set the value to your custom scheme. - Within
Item 0
, add a keyURL Schemes
. This will automatically be an array containing aItem 0
string. - Set
URL Schemes
»Item 0
to your custom scheme.
Alternatively, if you wish to edit your Info.plist
file directly, you can follow this spec:
1
2
3
4
5
6
7
8
9
10
11
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>{YOUR.SCHEME}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>{YOUR.SCHEME}</string>
</array>
</dict>
</array>
Step 2: Allowlist the custom scheme (iOS 9+)
Starting with iOS 9, apps must have an allowlist of custom schemes that the app is allowed to open. Attempting to call schemes outside this list will cause the system to record an error in the device’s logs, and the deep link will not open. An example of this error looks like this:
1
<Warning>: -canOpenURL: failed for URL: "yourapp://deeplink" – error: "This app is not allowed to query for scheme yourapp"
For example, if an in-app message should open the Facebook app when tapped, the app has to have the Facebook custom scheme (fb
) in the allowlist. Otherwise, the system will reject the deep link. Deep links that direct to a page or view inside your own app still require that your app’s custom scheme be listed in your app’s Info.plist
.
You should add all the schemes that the app needs to deep link to in an allowlist in your app’s Info.plist
with the key LSApplicationQueriesSchemes
. For example:
1
2
3
4
5
6
<key>LSApplicationQueriesSchemes</key>
<array>
<string>myapp</string>
<string>facebook</string>
<string>twitter</string>
</array>
For more information, refer to Apple’s documentation on the LSApplicationQueriesSchemes
key.
Step 3: Implement a handler
After activating your app, iOS will call the method application:openURL:options:
. The important argument is the NSURL object.
1
2
3
4
5
6
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
NSString *path = [url path];
NSString *query = [url query];
// Here you should insert code to take some action based upon the path and query.
return YES;
}
1
2
3
4
5
6
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let path = url.path
let query = url.query
// Here you should insert code to take some action based upon the path and query.
return true
}
Universal links
To use universal links, make sure you have added a registered domain to your app’s capabilities and have uploaded an apple-app-site-association
file. Then implement the method application:continueUserActivity:restorationHandler:
in your AppDelegate
. For example:
1
2
3
4
5
6
7
8
9
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
NSURL *url = userActivity.webpageURL;
// Handle url
}
return YES;
}
1
2
3
4
5
6
7
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
if (userActivity.activityType == NSUserActivityTypeBrowsingWeb) {
let url = userActivity.webpageURL
// Handle url
}
return true
}
Refer to Apple for more information.
The default universal link integration is not compatible with Braze push notifications, in-app messages, or News Feed. See linking customization to handle universal links within your application. Alternatively, we recommend using scheme-based deep links with push notifications, in-app messages, and the News Feed.
App transport security (ATS)
iOS 9 introduced a breaking change affecting web URLs embedded in in-app messages, News Feed cards, and push notifications.
ATS requirements
From Apple’s documentation: “App Transport Security is a feature that improves the security of connections between an app and web services. The feature consists of default connection requirements that conform to best practices for secure connections. Apps can override this default behavior and turn off transport security.”
ATS is applied by default on iOS 9+. It requires that all connections use HTTPS and are encrypted using TLS 1.2 with forward secrecy. Refer to Requirements for Connecting Using ATS for more information. All images served by Braze to end devices are handled by a content delivery network (“CDN”) that supports TLS 1.2 and is compatible with ATS.
Unless they are specified as exceptions in your application’s Info.plist
, connections that do not follow these requirements will fail with errors that look something like this:
1
2
CFNetwork SSLHandshake failed (-9801)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred, and a secure connection to the server cannot be made."
1
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
ATS compliance is enforced for links opened within the mobile app (our default handling of clicked links) and does not apply to sites opened externally via a web browser.
Handling ATS requirements
You can handle ATS in one of the following three ways:
Confirm all links are ATS compliant (recommended)
Your Braze integration can satisfy ATS requirements by ensuring that any existing links you drive users to (through in-app message and push campaigns or News Feed cards) satisfy ATS requirements. While there are ways to bypass ATS restrictions, we recommended checking that all linked URLs are ATS compliant. Given Apple’s increasing emphasis on application security, the following approaches to allowing ATS exceptions are not guaranteed to be supported by Apple.
An SSL tool can help you pinpoint web server security issues. This SSL server test from Qualys, Inc. provides a line item specifically for Apple ATS 9 and iOS 9 compliance.
Partially disable ATS
You can allow a subset of links with certain domains or schemes to be treated as exceptions to the ATS rules. Your Braze integration will satisfy ATS requirements if every link you use in a Braze messaging channel is either ATS compliant or handled by an exception.
To add a domain as an exception of the ATS, add the following to your app’s Info.plist
file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
Refer to Apple’s article on app transport security keys for more information.
Disable ATS entirely
You can turn off ATS entirely. Note that this is not recommended practice, due to both lost security protections and future iOS compatibility. To disable ATS, insert the following in your app’s Info.plist
file:
1
2
3
4
5
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Refer to Shipping an App With App Transport Security for more information on how to debug ATS failures.
URL encoding
As of Braze iOS SDK v2.21.0, the SDK percent-encodes links to create valid NSURL
s. All link characters that are not allowed in a properly formed URL, such as Unicode characters, will be percent escaped.
To decode an encoded link, use the NSString
method stringByRemovingPercentEncoding
. Note that you must also return YES
in the ABKURLDelegate
and that a call to action is required to trigger the handling of the URL by the app. For example:
1
2
3
4
5
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<NSString *, id> *)options {
NSString *urlString = url.absoluteString.stringByRemovingPercentEncoding;
// Handle urlString
return YES;
}
1
2
3
4
5
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let urlString = url.absoluteString.removingPercentEncoding
// Handle urlString
return true
}
Customization
Default WebView customization
The customizable ABKModalWebViewController
class displays web URLs opened by the SDK, typically when “Open Web URL Inside App” is selected for a web deep link.
You can declare a category for, or directly modify, the ABKModalWebViewController
class to apply customization to the web view. Check the class’ .h file and .m file for more detail.
Linking handling customization
The ABKURLDelegate
protocol can be used to customize the handling of URLs such as deep links, web URLs, and universal links. To set the delegate during Braze initialization, pass a delegate object to the ABKURLDelegateKey
in the appboyOptions
of startWithApiKey:inApplication:withAppboyOptions:
. Braze will then call your delegate’s implementation of handleAppboyURL:fromChannel:withExtras:
before handling any URIs.
Integration example: ABKURLDelegate
1
2
3
4
5
6
7
8
- (BOOL)handleAppboyURL:(NSURL *)url fromChannel:(ABKChannel)channel withExtras:(NSDictionary *)extras {
if ([[url.host lowercaseString] isEqualToString:@"MY-DOMAIN.com"]) {
// Custom handle link here
return YES;
}
// Let Braze handle links otherwise
return NO;
}
1
2
3
4
5
6
7
8
func handleAppboyURL(_ url: URL?, from channel: ABKChannel, withExtras extras: [AnyHashable : Any]?) -> Bool {
if (url.host == "MY-DOMAIN.com") {
// Custom handle link here
return true;
}
// Let Braze handle links otherwise
return false;
}
For more information, see ABKURLDelegate.h
.
Frequent use cases
Deep linking to app settings
iOS can take users from your app into its page in the iOS settings application. You can take advantage of UIApplicationOpenSettingsURLString
to deep link users to settings from push notifications, in-app messages, and the News Feed.
- First, make sure your application is set up for either scheme-based deep links or universal links.
- Decide on a URI for deep linking to the Settings page (for example,
myapp://settings
orhttps://www.braze.com/settings
). - If you are using custom scheme-based deep links, add the following code to your
application:openURL:options:
method:
1
2
3
4
5
6
7
8
9
10
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
NSString *path = [url path];
if ([path isEqualToString:@"settings"]) {
NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:settingsURL];
}
return YES;
}
1
2
3
4
5
6
7
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let path = url.path
if (path == "settings") {
UIApplication.shared.openURL(URL(string:UIApplicationOpenSettingsURLString)!)
}
return true
}