Deep Linking & Push Navigation
When a user taps a push notification, the DashX SDK resolves a NavigationAction from the payload and either handles it automatically or hands it to your app. This page covers how navigation is resolved, the available hooks, and how to wire up deep links and universal / app links.
Navigation actions
Every notification tap (including action-button taps) resolves to one of four navigation types:
| Action | When | Behaviour |
|---|---|---|
| Screen | screen_name is present | In-app navigation to a named screen with optional screen_data |
| Rich Landing | url is present and rich_landing is true | Opens the URL in an in-app browser (SFSafariViewController / Custom Tabs) |
| Deep Link | url is present | Opens the URL externally (system browser, another app, or your app via universal / app links) |
| Click Action | click_action is present | Launches an Activity class or intent action (Android) or maps to a UNNotificationCategory (iOS) |
Resolution priority: Screen > Rich Landing > Deep Link > Click Action. The first match wins; remaining fields are ignored.
Payload fields
These fields can be set at the top level of a push notification or per action button when creating a broadcast (see Send Messages):
| Field | Type | Description |
|---|---|---|
url | String | Deep link or rich-landing URL |
screen_name | String | Named in-app screen |
screen_data | Map<String, String> | Key-value parameters passed to the screen |
rich_landing | Boolean | When true, opens url in an in-app browser instead of externally |
click_action | String | Activity class / intent action (Android) or notification category (iOS) |
action_buttons | Array | Each button carries its own identifier, label, plus the fields above |
Handling notification taps
- iOS
- Android
Subclass DashXAppDelegate
DashXAppDelegate wires push permission, delivery / click / dismiss tracking, and sets DashXClient.instance.linkHandler to your handleLink(url:) override.
Override onNotificationClicked and return true to handle navigation yourself. Return false (the default) to let the SDK apply its built-in behaviour.
import DashXFirebase
@main
class AppDelegate: DashXAppDelegate {
override func onNotificationClicked(
message: [AnyHashable: Any],
action: NavigationAction?,
actionIdentifier: String
) -> Bool {
switch action {
case .screen(let name, let data):
navigate(to: name, params: data)
return true // handled — SDK will not open a URL or call legacy hooks
default:
return false // let the SDK handle deep links, rich landing, etc.
}
}
override func handleLink(url: URL) {
// Called by the SDK for deep links (NavigationAction.deepLink)
// Route the URL to the appropriate screen
}
}
The deprecated notificationClicked(message:actionIdentifier:) hook is still called as a fallback for .screen and .clickAction when onNotificationClicked returns false.
Subclass DashXSceneDelegate
DashXSceneDelegate forwards custom URL schemes and universal links into the SDK automatically:
import DashX
class SceneDelegate: DashXSceneDelegate {
// scene(_:openURLContexts:) — custom URL schemes → processURL
// scene(_:continue:) — universal links → handleUserActivity
// Add your own scene logic and call super for the methods above.
}
If you are not using DashXSceneDelegate, call these yourself:
DashXClient.instance.processURL(url, source: "scene_url")
DashXClient.instance.handleUserActivity(userActivity: userActivity)
Rich landing customisation
Set DashXBrowser.safariConfiguration to customise the SFSafariViewController before it is presented:
DashXBrowser.safariConfiguration = { safari in
safari.preferredBarTintColor = .systemBackground
safari.dismissButtonStyle = .close
}
Host-app configuration
- Universal Links — add the Associated Domains capability (
applinks:yourdomain.com) and host anapple-app-site-associationfile on your domain.DashXSceneDelegatehandles continuation automatically. - Custom URL Schemes — register the scheme in Info > URL Types. Ensure
scene(_:openURLContexts:)calls through toDashXSceneDelegate(or callprocessURLyourself).
Register a DashXNotificationListener
Register optional hooks with DashX.registerNotificationListener / unregisterNotificationListener:
DashX.registerNotificationListener(object : DashXNotificationListener {
override fun onNotificationClicked(
payload: DashXPayload,
action: NavigationAction?
): Boolean {
when (action) {
is NavigationAction.Screen -> {
navigate(action.name, action.data)
return true // handled — SDK will not open a URL
}
else -> return false // let the SDK handle deep links, rich landing, etc.
}
}
override fun onNotificationReceived(payload: DashXPayload) {
// Incoming FCM message (foreground delivery path)
}
override fun onNotificationDismissed(payload: DashXPayload) {
// Notification cleared from the shade
}
})
Return true from onNotificationClicked to handle navigation yourself and skip the SDK default behaviour (opening URLs, Custom Tabs for rich landing, click_action intents).
DashX.processDeepLink(uri, source)
Call this when you open a deep link outside the SDK (for example from your own App Link activity) to record the same dx_deep_link_opened analytics event the SDK fires for notification taps:
DashX.processDeepLink(intent.data!!, source = "app_link")
Notification clicks that use the default URL flow already call this with source = "notification".
DashX.openRichLanding(context, url)
Opens a URL in an in-app Custom Tabs browser. Use this when you want to present a URL inside the app outside the notification flow (for example from an in-app message or your own UI). Falls back to ACTION_VIEW when no Custom Tabs provider is installed.
Host-app configuration
For https deep links, configure Android App Links (intent filters and Digital Asset Links) so taps open your app. Use onNotificationClicked to map NavigationAction.Screen or custom URLs to your activities or Jetpack NavController.
Analytics events
The SDK automatically tracks two events for deep linking:
| Event | Fired when |
|---|---|
dx_deep_link_opened | A URL is opened (notification tap, universal link, custom URL scheme, or manual processDeepLink / processURL call) |
dx_notification_navigated | Any notification tap — includes the resolved navigation type (deep_link, screen, rich_landing, click_action, or default) and destination data |