Skip to content
Tolinku
Tolinku
Sign In Start Free
Comparisons · · 5 min read

SDK Swap Guide: Replacing Your Deep Linking SDK

By Tolinku Staff
|
Tolinku platform comparisons dashboard screenshot for comparisons blog posts

Swapping a deep linking SDK is the most engineering-intensive part of a platform migration. The SDK handles deep link reception, deferred deep linking, and often event tracking. Replacing it means changing how your app receives and processes links.

This guide covers the technical steps for swapping deep linking SDKs in iOS and Android apps, with patterns that minimize risk.

For the full migration guide, see Migrating to Tolinku from Branch, Firebase, and AppsFlyer. For the migration checklist, see Deep Linking Migration Checklist: 30 Steps.

The Abstraction Layer Approach

Before ripping out the old SDK, build an abstraction layer. This gives you a clean interface that your app code calls, with the implementation swappable behind it.

Define the Interface

iOS (Swift):

protocol DeepLinkHandler {
    func handleURL(_ url: URL) -> DeepLinkResult?
    func handleDeferredLink(completion: @escaping (DeepLinkResult?) -> Void)
}

struct DeepLinkResult {
    let path: String
    let parameters: [String: String]
    let isDeferred: Bool
}

Android (Kotlin):

interface DeepLinkHandler {
    fun handleUri(uri: Uri): DeepLinkResult?
    fun handleDeferredLink(callback: (DeepLinkResult?) -> Unit)
}

data class DeepLinkResult(
    val path: String,
    val parameters: Map<String, String>,
    val isDeferred: Boolean
)

Wrap the Old SDK

Create an implementation using your current SDK:

// iOS: Branch implementation (temporary)
class BranchDeepLinkHandler: DeepLinkHandler {
    func handleURL(_ url: URL) -> DeepLinkResult? {
        // Bridge Branch's data format to your DeepLinkResult
        // This wraps existing Branch logic
    }

    func handleDeferredLink(completion: @escaping (DeepLinkResult?) -> Void) {
        // Bridge Branch's deferred link callback
    }
}

Update App Code

Change all deep link handling in your app to use the protocol:

class AppRouter {
    let deepLinkHandler: DeepLinkHandler

    init(handler: DeepLinkHandler) {
        self.deepLinkHandler = handler
    }

    func handleIncomingURL(_ url: URL) {
        guard let result = deepLinkHandler.handleURL(url) else { return }
        navigate(to: result)
    }
}

Now your app code is decoupled from any specific SDK. Swapping SDKs means creating a new DeepLinkHandler implementation.

Step 1: Remove the Old SDK

iOS Removal

CocoaPods:

# Remove from Podfile
# pod 'Branch'  # or pod 'AppsFlyerFramework', pod 'FirebaseDynamicLinks'

Run pod install.

Swift Package Manager: Remove the package dependency in Xcode (File → Swift Packages → Remove).

Manual removal:

  • Delete the framework files
  • Remove from Build Phases → Link Binary With Libraries
  • Remove any related build flags

After removing the dependency, clean the build folder (Cmd+Shift+K in Xcode) and search for any remaining imports:

grep -r "import Branch" .
grep -r "import AppsFlyerLib" .
grep -r "import FirebaseDynamicLinks" .

Remove all found references.

Android Removal

Remove from build.gradle:

// Remove these lines
// implementation 'io.branch.sdk.android:library:5.+'
// implementation 'com.appsflyer:af-android-sdk:6.+'
// implementation 'com.google.firebase:firebase-dynamic-links:21.+'

Sync the project and search for remaining imports:

grep -r "import io.branch" .
grep -r "import com.appsflyer" .
grep -r "import com.google.firebase.dynamiclinks" .

Cleanup Checklist

After removing the SDK:

  • Remove initialization code from AppDelegate/Application class
  • Remove delegate/listener implementations
  • Remove event tracking calls
  • Remove link creation calls
  • Remove SDK-specific configuration from Info.plist / AndroidManifest.xml
  • Remove SDK-specific build scripts or plugins
  • Remove proguard rules for the old SDK (Android)

Step 2: Add the New SDK

Tolinku SDK Integration

iOS (Swift Package Manager): Add the TolinkuSDK package.

Associated Domains: Add your Tolinku domain to the Associated Domains entitlement:

applinks:go.yourapp.com

SceneDelegate (or AppDelegate for older apps):

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else { return }

    let handler = TolinkuDeepLinkHandler()
    if let result = handler.handleURL(url) {
        AppRouter.shared.navigate(to: result)
    }
}

Android: Add the dependency to build.gradle.

AndroidManifest.xml:

<activity android:name=".MainActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="https"
            android:host="go.yourapp.com" />
    </intent-filter>
</activity>

MainActivity:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handleIntent(intent)
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    handleIntent(intent)
}

private fun handleIntent(intent: Intent) {
    val uri = intent.data ?: return
    val handler = TolinkuDeepLinkHandler()
    handler.handleUri(uri)?.let { result ->
        AppRouter.navigate(result)
    }
}

Step 3: Implement the New Handler

Create the Tolinku implementation of your abstraction:

class TolinkuDeepLinkHandler: DeepLinkHandler {
    func handleURL(_ url: URL) -> DeepLinkResult? {
        let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
        let path = url.path
        let params = components?.queryItems?.reduce(into: [String: String]()) { dict, item in
            dict[item.name] = item.value
        } ?? [:]

        return DeepLinkResult(
            path: path,
            parameters: params,
            isDeferred: false
        )
    }

    func handleDeferredLink(completion: @escaping (DeepLinkResult?) -> Void) {
        // Use Tolinku SDK to check for deferred deep link data
        Tolinku.shared.checkForDeferredLink { url in
            guard let url = url else {
                completion(nil)
                return
            }
            completion(self.handleURL(url))
        }
    }
}

The key difference from most old SDKs: Tolinku passes deep link data through standard URLs, so parsing is just URL component extraction. No proprietary data dictionaries to decode.

Step 4: Handle Edge Cases

Multiple URL Schemes

If your app registered custom URL schemes (e.g., yourapp://product/123) in addition to Universal Links/App Links, decide whether to keep them. Custom URL schemes are less secure and less reliable than Universal Links/App Links, but some older integrations may depend on them.

Map your old routing patterns to the new URL structure:

Old SDK Route New URL Route
Branch.data["product_id"] = "123" /product/123 or ?product_id=123
AppsFlyer.deepLinkValue = "promo" /promo
Firebase.link = "https://yourapp.com/sale" /sale

Event Tracking

If you tracked events through the old deep linking SDK, move event tracking to your analytics SDK or Tolinku's analytics. Don't mix deep link routing with event tracking responsibilities.

Testing the Swap

Test these scenarios on both iOS and Android:

  1. Cold start with link: App is not running; user taps a link → app launches and navigates to the correct screen
  2. Warm start with link: App is backgrounded; user taps a link → app comes to foreground and navigates
  3. Deferred deep link: App not installed; user taps link → installs → opens → sees correct content
  4. No-op link: User taps a link that doesn't match any route → app handles gracefully (home screen, not crash)
  5. Malformed link: Link with missing or invalid parameters → app handles gracefully

For a comprehensive comparison of deep linking SDKs, see Deferred Deep Linking SDK Comparison.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.