Route Pulsate campaign links into your app, other apps, or phone numbers.
Deeplinks let you link from Pulsate to your app, other apps, or phone numbers. In the Pulsate CMS you can add buttons to your marketing campaigns that lead to deep links in your application.
Deeplinks must be unique
When creating deeplinks that target your app, pick a scheme / name that is unique. If several apps on the device share the same deeplink scheme, tapping the link makes the phone ask which app to open instead of opening yours directly.
Add / edit / delete deeplinks in the Pulsate CMS
The first step is adding deeplinks in the Pulsate CMS so you can use them in campaigns (https://control.pulsatehq.com).
- From the CMS dashboard, select your application and open Settings → App Settings.
- In App Settings you will find the Add Deeplink and Manage Deeplinks sections.
- To add a deeplink, enter its name and value and click Save.
The deeplink is now added to your account and available when building campaigns. Existing deeplinks can be changed or removed with the Edit and Delete buttons next to each entry.
Deeplink to call a phone number
To open the Phone app with a number pre-filled, create a deeplink with a URL formatted as
tel:+123456789. This opens the Phone app on both iOS and Android with+123456789as the number to call.
Register your URL scheme in Xcode
To support deep linking, declare your app's URL scheme in Xcode:
- Select your project in Xcode and open the Info tab.
- Expand URL Types and add a new entry.
- Enter your bundle identifier in the Identifier field and the URL scheme you want to use.
You can test the scheme by entering myapp:// in the device's web browser.
How Pulsate opens a deeplink
When a user taps a campaign's deeplink - in a push, an in-app message, or the feed - Pulsate:
- Calls your link listener, if you registered one. If it returns
true, Pulsate stops there. - Otherwise asks iOS to open the link (
UIApplication.shared.open). - If the link uses your app's own scheme, iOS delivers it back to your app:
- App without scenes:
application(_:open:options:)on your app delegate. - Scene-based app: your scene delegate - see Scene-based apps.
- App without scenes:
You can handle your own links in either place: in the link listener (simplest, and it only sees Pulsate's links), or in your normal URL handling (which also sees links from Safari, other apps and QR codes).
Handling Pulsate deeplinks
Register a link listener on the PULPulsateManager instance. Pulsate invokes your listener when a campaign or CTA link needs to be handled. Return true if your app consumed the link, or false to let Pulsate open it with iOS as described above.
import PULPulsate
guard let manager = PULPulsateFactory.getDefaultInstance() else { return }
manager.setPULPulsateLinkListener { link -> Bool in
if link == "myapp://clothes" {
self.openClothesViewController()
return true
}
return false
}
Register the listener at startup
The listener receives the link as a
String(PULPulsateLinkListener = (String) -> Bool). Register it once, right afterPULPulsateFactory.getInstance(...)inapplication(_:didFinishLaunchingWithOptions:). A push tap that launches the app is handled shortly after launch; a listener registered later - for example after sign-in - misses it, and the link falls through to iOS.
Scene-based apps
If your app uses the UIScene lifecycle and handles its own links outside the link listener, handle them in your scene delegate - UIKit does not call application(_:open:options:) on the app delegate in a scene-based app. Implement both:
scene(_:openURLContexts:)- links that arrive while the app is running.scene(_:willConnectTo:options:), readingconnectionOptions.urlContexts- links that launch the app. Without this, a deeplink tapped while the app is closed is dropped.
Pulsate does not need these callbacks - they are only for routing your own links.
import UIKit
final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private var pendingLinks: [URL] = []
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
// A link that launches the app arrives here, not in scene(_:openURLContexts:).
pendingLinks += connectionOptions.urlContexts.map(\.url)
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
pendingLinks += URLContexts.map(\.url)
if scene.activationState == .foregroundActive {
routePendingLinks()
}
}
func sceneDidBecomeActive(_ scene: UIScene) {
// On a cold launch the window is not on screen yet in willConnectTo, and anything
// presented then is discarded - so links wait until the scene is active.
routePendingLinks()
}
private func routePendingLinks() {
let links = pendingLinks
pendingLinks.removeAll()
for url in links where url.scheme == "myapp" {
// Route to the screen for this link, e.g. myapp://clothes
}
}
}
Testing checklist
Test each deeplink in all three app states:
- App in the foreground
- App in the background
- App closed (swipe it away first), then tap the push - the most timing-sensitive case

