Using Deep Links to Drive Mobile Engagement in Braze

Using Deep Links to Drive Mobile Engagement in Braze

Deep links send someone from a Braze message straight to a screen inside your app. Which link type you need is decided by the channel you are sending on, not by the destination. Custom schemes suit push, in-app messages and Content Cards. Universal links suit email and SMS, where click tracking rewrites the address before anyone taps it.

Key Takeaways

  • The channel decides the link type, not the destination. Custom schemes suit push, in-app messages and Content Cards. Universal links suit email and SMS.
  • Email service providers rewrite links through a click-tracking domain, and a custom scheme cannot survive that rewrite.
  • The Apple App Site Association file has to be hosted on the click-tracking domain as well as your primary domain.
  • The Braze SDK does not read your association file. It separates universal links from ordinary web URLs by domain name alone.
  • Test outside the app first. If the link fails there, the fault is in your app and no campaign change will move it.
  • Universal links need a physical device, because a simulator does not expose the required entitlements directly.

Which link type should you use?

Braze documents three ways to handle a link from a message. The choice is not a matter of taste. Each one carries different setup work and fails in a different way.

Link typeExampleSuitsOpens without the app installed
Custom schememyapp://products/123Push, in-app messages, Content CardsNo, the link fails
Universal linkhttps://myapp.com/products/123Email, SMS, channels with click trackingYes, falls back to web
Open Web URL Inside AppAny https:// URLWeb content in a modal WebViewNot applicable, displays in a WebView

The rule we apply on delivery work is that the channel picks the link type, and it picks it before anyone writes app code. Push, in-app messages and Content Cards deliver the address you typed. Email and SMS do not, because the sending infrastructure rewrites it on the way out.

That sequencing is our own position from implementation work, not a Braze recommendation. Teams that choose the destination first and the link type afterwards tend to discover the mismatch in staging, when the app code is already written against the wrong delegate method.

Why do email deep links need extra setup?

Braze is explicit that an email service provider wraps links in a click-tracking domain. The three it names are:

  • SendGrid
  • SparkPost
  • Amazon SES

A custom scheme cannot survive that rewrite. Email needs a universal link for this reason alone.

The part that catches people out sits one level deeper. The Apple App Site Association file has to be hosted on the click-tracking domain too, not only on your primary domain. Host it in one place and every email link lands in the browser.

The opposite failure is documented as well. If the association file on the click-tracking domain uses a path pattern that matches everything on that domain, every link in the email opens the app, including the unsubscribe footer. Braze's fix is to limit the paths. For SendGrid the guidance is to match /uni/ and mark only those links as universal.

What does each link type actually require?

Custom schemes are the cheaper build. You register the scheme under CFBundleURLTypes in Info.plist, add it to the query allowlist, and implement application(_:open:options:). No association file. No Braze SDK configuration, because the SDK opens custom scheme URLs by default.

Universal links cost more in three places at once:

  1. Host the association file at https://yourdomain.com/.well-known/apple-app-site-association.
  2. Add applinks:yourdomain.com under Signing and Capabilities in Xcode.
  3. Implement application(_:continue:restorationHandler:) and set configuration.forwardUniversalLinks to true.

One behaviour worth knowing before you design around path exclusions. The Braze SDK does not read your association file. It separates universal links from ordinary web URLs by looking at the domain name alone, so an exclusion rule written into that file has no effect on how the SDK routes the link.

How do you isolate a broken deep link?

Debugging a deep link inside a campaign tells you almost nothing, because a campaign stacks four independent things on top of each other. We work outward from the device instead, and we stop at the first rung that fails.

Rung one, outside the app

For a custom scheme, run xcrun simctl openurl booted "myapp://products/123". For a universal link, paste it into the Notes app on a physical device and tap it. Braze advises against testing from the Safari address bar, because iOS treats a typed URL differently from a tapped one. If the link fails here, the fault is in your app, and no campaign change will move it.

Rung two, one channel

Send the link through a single Braze channel with verbose logging turned on. The SDK prints an Opening entry carrying the channel, the useWebView flag and the isUniversalLink flag.

Rung three, compare channels

If the link works from push but not from an in-app message, put the two log entries side by side. A difference in isUniversalLink means the SDK classified the same address two different ways.

The three-rung ordering is ours. Braze publishes the individual steps in its investigation path and we have arranged them as an escalation, so a failing rung tells you which team owns the fix.

What breaks that looks like a Braze problem?

Several documented behaviours produce symptoms that read as campaign faults and are not.

SymptomDocumented cause
Universal link opens the browser after working yesterdayLong-pressing a link and selecting Open can break the domain association. Reset by long-pressing and choosing Open in the app
Universal links never fire in the simulatorForwarding needs the application entitlements, which a simulator does not expose directly
Web URL opens to a blank viewThe target page sets a framing or content security header that blocks rendering inside a WebView
Android push opens the app but not the screencom_braze_handle_push_deep_links_automatically is not set to true in braze.xml

Two more are worth carrying into a build checklist. Apps built with Xcode 27 and later adopt the UIScene life cycle, which means custom scheme URLs arrive at your SceneDelegate rather than your AppDelegate. And on Android, one delegate implementing IBrazeDeeplinkHandler handles links across Content Cards, in-app messages and push together.

Where do deep links change campaign design?

A deep link shortens the distance between a message and the action it asks for. That matters where the action is specific, which is where journey design and message design meet.

Onboarding is the clearest case. An activation step that names a feature should land on that feature, and a Canvas-driven onboarding journey gives you the branch structure to send different users to different screens. The activation campaigns we have written about before each imply a destination, and each one is a separate path in the association file.

The same holds for personalisation. If you are already building personalised message content, the destination deserves the same treatment, and dynamic content techniques apply to a link path as readily as to a message body. Win-back work has the sharpest version of this problem, since a retention campaign often points at a cart or a saved item that only exists for one person.

Frequently Asked Questions

1. Do custom scheme deep links work in email?

No. Braze documents that email service providers wrap links in a click-tracking domain, and that rewrite breaks a custom scheme. Use a universal link for email and host the Apple App Site Association file on the click-tracking domain as well as your primary domain.

2. Do I need an Apple App Site Association file for push deep links?

Not for custom scheme links. Braze lists the association file as not required for custom schemes, which only need a registered scheme in Info.plist and a handler. You need one if you send universal links from push with forwardUniversalLinks enabled.

3. How large can the Apple App Site Association file be?

Braze's validation checklist gives a ceiling of 128 KB, alongside a valid certificate, a Content-Type of application/json, and an appID matching your Team ID and Bundle ID.

4. Why does a deep link work from push but not from an in-app message?

Turn on verbose logging and compare the Opening entry for each channel. Braze points to differences in the useWebView and isUniversalLink values as the signal that the SDK is interpreting the same link differently.

5. Can I test universal links in the iOS simulator?

Braze advises a physical device, because universal link forwarding needs application entitlements that a simulator does not expose directly. Adding the .entitlements file to the Copy Bundle Resources build phase adds simulator support.

Sources

CustomerIK is a Braze implementation partner working across onboarding, technical integration, marketing operations and customer data management.

If your deep links work in testing and break inside a campaign, let's talk.

Preferences

Privacy is important to us, so you have the option of disabling certain types of storage that may not be necessary for the basic functioning of the website. Blocking categories may impact your experience on the website.

Accept all cookies
Accept all cookies

These items are required to enable basic website functionality.

Always active

These items are used to deliver advertising that is more relevant to you and your interests.

These items allow the website to remember choices you make (such as your user name, language, or the region you are in) and provide enhanced, more personal features.

These items help the website operator understand how its website performs, how visitors interact with the site, and whether there may be technical issues.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.