Replace Firebase Dynamic Links with a modern, lightweight solution. SDDL gives you universal/app links, deferred deep linking, webhooks, and custom domains — all without heavy SDKs.
Why Switch from Firebase Dynamic Links
- Own your link logic. Keep routing on your backend, not inside a closed SDK.
- Universal/App Links done right. First‑install routing, fallback pages, and per‑platform control.
- Webhooks for analytics. Receive click events (IP, UA, UTM, optional geo) to your systems.
- Custom domains. Use branded links users trust and platforms don’t throttle.
What You Get with SDDL
Deferred Deep Linking: route first‑time installers to the exact in‑app screen after App Store / Play redirect.
Server‑First Design: define destinations and parameters centrally; mobile SDK is optional.
Webhooks: receive structured click data to your webhook URL for attribution on your side.
Custom Domains: map your domain for better trust and deliverability (e.g., go.example.com
).
Safety & Validation: guided setup for apple-app-site-association
and assetlinks.json
plus link validators.
How SDDL Works Under the Hood
SDDL resolves each smart link on the server and serves a minimal fallback page optimized for store hops and first‑install flows.
- Short‑lived context key: your app can redeem it on first open.
- Platform aware: sends users to the correct store or web fallback.
- Per‑link settings: platform store URLs, safe web fallback, etc.
Quick Start
1) Create a link
Create and configure links in the SDDL Dashboard or API. Set platform store URLs, web fallback, and any parameters you’ll need after install.
2) Configure Universal/App Links
3) Handle deferred deep linking
On first app open, follow this order: (1) use identifier from Universal/App Link if present → (2) else check clipboard → (3) else call the SDDL try details endpoint.
Client Integration Snippets (Using SDDL SDKs)
iOS (Swift, using SDDLSDK
)
import SwiftUI
import SDDLSDK
struct ContentView: View {
@State private var result: String = "Waiting for Universal Link..."
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
.font(.largeTitle)
Text(result)
.padding()
.foregroundColor(.blue)
}
.onOpenURL { url in
handleDeepLink(url)
}
.onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
if let incomingURL = userActivity.webpageURL {
handleDeepLink(incomingURL)
}
}
.onAppear {
handleDeepLink(nil)
}
.padding()
}
private func handleDeepLink(_ url: URL?) {
SDDLSDKManager.fetchDetails(from: url) { data in
if let json = data as? [String: Any] {
result = "Data: \(json)"
} else {
result = "Failed to fetch data"
}
}
}
}
#Preview {
ContentView()
}
Android (Kotlin, using SDDLSDK
)
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// handle a fresh deep link while app is already running
handleIncomingIntent(intent)
}
private fun handleIncomingIntent(intent: Intent) {
val data: Uri? = intent.data
if (data != null) {
Log.d("AppLinkTest", "Received URL: $data")
resultTextView.text = "Loading details..."
// fetch deferred link details from our service
SDDLSDK.fetchDetails(
context = this,
data = data,
callback = object : SDDLSDK.SDDLCallback {
override fun onSuccess(data: JsonObject) {
Log.d("SDDLSDK", "Fetched Data: $data")
// update UI on main thread
runOnUiThread {
resultTextView.text = data.toString()
}
}
override fun onError(error: String) {
Log.e("SDDLSDK", "Error: $error")
runOnUiThread {
resultTextView.text = "Error: $error"
}
}
}
)
} else {
Log.d("AppLinkTest", "No URL received")
resultTextView.text = "No URL received"
}
}
Webhook (Server)
// Example webhook payload (click)
// SDDL posts JSON to your configured webhook URL.
{
"link": "invite/abc123",
"details": {
"ip": "203.0.113.42",
"userAgent": "Mozilla/5.0 ...",
"createdAt": "2025-08-10 12:00:00",
"referer": "https://example.com/page",
"utmSource": "newsletter",
"utmMedium": "email",
"utmCampaign": "summer-sale",
"utmContent": "cta-button",
"country": "US",
"city": "New York",
"latitude": 40.7128,
"longitude": -74.0060
}
}
This payload contains the link key and the full details
object (IP/UA/timestamp/referrer, UTM fields, optional geo). Parse and attribute on your side as needed.
Firebase Dynamic Links vs SDDL (Quick Look)
Capability | Firebase Dynamic Links | SDDL |
---|---|---|
Deferred Deep Linking | Requires SDK logic | Server‑first (SDK optional) |
Universal/App Links | Supported | Guided setup + validators |
Webhooks | Limited | Click webhooks with full details |
Custom Domains | Restricted | First‑class with HTTPS |
SDK Requirement | Typically required | Optional (API‑first design) |
FAQ
Do I need to integrate an SDK? ⌄
No. You can implement the flow yourself. But our SDKs make it easy to check the URL or clipboard and call the correct SDDL endpoints in order.
How should I handle first‑install routing? ⌄
Follow this order: (1) identifier from Universal/App Link → (2) clipboard fallback → (3) SDDL try details endpoint. Then route the user in‑app.
Can I bring my own domain? ⌄
Yes. Map go.example.com
or any subdomain. We validate DNS and host AASA / Asset Links files for you.
What about analytics? ⌄
Use webhooks to ingest click events into your own systems. SDDL sends the link
and a full details
object.