WarpLink
Migration

Branch Migration

Migrate from Branch to WarpLink: link and parameter mapping, exporting data, SDK swap, and deep linking, install attribution, and analytics.

This guide is for teams currently using Branch for links, deep linking, install attribution, or analytics who are moving to WarpLink. It covers Branch-specific concept mapping, exporting your existing links and data, and swapping the Branch SDK for the WarpLink SDK on each platform. For the provider-agnostic playbook (inventory, domain planning, cutover, and decommissioning), see Migration Overview.

Concept Mapping

Branch ConceptWarpLink Concept
Quick Link / Ad LinkLink
AliasSlug
app.link / bnc.lt domainaplnk.to domain (or custom domain)
Custom domain (CNAME or NS delegation)Custom domain
$-prefixed link parametersLink fields (see parameter mapping below)
LinkHub (Dashboard → Manager)WarpLink dashboard Links page
Journeys (smart banners)Not replaced; see Attribution and Reporting

Branch's LinkHub (Dashboard → Manager) lets you search, filter, and bulk export both Quick Links and Ad Links, meaning dashboard-created and SDK/API-generated links are both reachable there. If you need to script an export instead, the Read endpoint returns one link's configuration at a time:

There is no single Branch endpoint that exports all historical links and all historical click analytics together. Link configuration and click/event data are separate export surfaces:

  • Dashboard Exports: an ad hoc CSV of whatever report you are currently viewing.
  • Daily Exports API (POST https://api2.branch.io/v3/export): gzipped CSV, up to 200,000 rows per file, capped at 7 days per request (1 day recommended), and only accessible via the API for 6 months after the data posts.
  • Custom Exports API: covers install, commerce, content, user-lifecycle, custom, and fraud events as CSV or JSON, up to 2,000,000 records per request with a 180-day lookback and a 60-day query window per request. Rate limited to 10 requests/minute and 25/hour, so a full-account export has to be paced across multiple calls.

Branch's device-matching attribution data is deleted after 30 days of user inactivity (90 days for some attribution products). Pull your historical exports before that window closes, not after.

Recreate your Branch links in WarpLink via the dashboard or the REST API.

Parameter Mapping

Branch ParameterWarpLink Field
Aliasslug
$fallback_urldestination_url
$ios_urlios_fallback_url
$android_urlandroid_fallback_url
$deeplink_path / $ios_deeplink_pathios_url
$android_deeplink_pathandroid_url
$og_titleog_title
$og_descriptionog_description
$og_image_urlog_image_url
$exp_dateexpires_at
$match_durationmatch_window_hours (capped at 24 hours, versus Branch's default 7200 seconds)
Repeated ~tags query parameterstags
password (Branch reserved query param)password
Other link data (custom key/value pairs)Encoded as query parameters on destination_url, echoed back as custom_params on resolve

Branch's deepview, social-card variants beyond title/description/image, custom meta tags, and attribution-window parameters other than $match_duration have no direct WarpLink field. Fold anything you still need into destination_url query parameters.

Create via API

3. Swap the SDK

Remove Branch:

  1. Remove the BranchSDK package (CocoaPods pod 'BranchSDK', SPM https://github.com/BranchMetrics/ios-branch-sdk-spm, or Carthage github "BranchMetrics/ios-branch-deep-linking")
  2. Remove the Branch.getInstance() / initSession(launchOptions:) call
  3. Remove the branch_key and branch_universal_link_domains keys from Info.plist
  4. Remove the applinks:subdomain.app.link Associated Domains entries (including the -alternate and .test variants)

Add WarpLink:

Remove Branch:

Also remove the io.branch.sdk.BranchKey, io.branch.sdk.BranchKey.test, and io.branch.sdk.TestMode manifest meta-data entries, and the custom URI scheme and HTTPS App Links intent filters pointed at your app.link domains.

Add WarpLink:

Remove Branch:

Add WarpLink:

The iOS SDK is distributed through Swift Package Manager and needs dynamic linkage, so add this to ios/Podfile inside your app target before installing pods:

4. Update SDK Initialization

Use an SDK key here, not an API key. Mobile apps authenticate with an SDK key, created in the dashboard under API Keys > SDK key. An API key looks identical but cannot record installs, so deep links keep resolving while every attribution call is rejected and no installs appear in your dashboard.

Before (Branch):

After (WarpLink):

Before (Branch):

After (WarpLink):

Before (Branch):

After (WarpLink):

5. Update Domain Configuration

In Signing & Capabilities > Associated Domains:

Remove every applinks: entry for your app.link (and legacy bnc.lt) subdomain, including the -alternate and .test variants Branch adds automatically.

In AndroidManifest.xml, update the intent filter host and remove Branch's custom URI scheme filter:

Remove the android:autoVerify="true" intent filters for both your live and test app.link domains.

Moving your links to a custom domain instead? Use that host here, and declare it to the SDK as well: linkDomains at configure(), or the WarpLinkDomains plist key / app.warplink.DOMAINS manifest entry. That is what makes a custom-domain link resolve on the first launch. See Use it in your app.

Branch's default app.link and bnc.lt domains cannot move with you; only your own custom domain can be repointed. If your custom domain was set up as a Branch CNAME subdomain, your registrar was never handed off, so the CNAME can be repointed to WarpLink once your links exist there. If it was set up as a root-domain NS delegation, Branch's nameservers are authoritative for that domain, so regaining control means moving the NS records back to your registrar (or another DNS provider) before pointing it at WarpLink, a normal DNS change but one Branch does not document as an offboarding step. Branch hosts the AASA file and TLS certificate for both setups; once you repoint to WarpLink, WarpLink issues and renews the certificate for your verified custom domain automatically.

Delete the Branch calls inside application(_:open:options:) and application(_:continue:restorationHandler:) (and the SceneDelegate equivalents, scene(_:continue:) and scene(_:openURLContexts:), if your app uses scenes). Forward the same URL or activity to WarpLink instead:

Resolved links arrive in your onLink callback. Or set your delegate class to the drop-in WarpLinkAppDelegate / WarpLinkSceneDelegate and skip writing these methods yourself.

Delete the Branch.sessionBuilder(this).withCallback { ... }.withData(intent.data).init() call from your Activity's onStart(). Cold start is automatic once onLink is set at configure(). For warm start, forward new intents and keep android:launchMode="singleTask" on the Activity:

Resolved links arrive in your onLink callback.

Delete the branch.subscribe(...) callback. WarpLink.configure()'s onLink callback covers cold start, warm start, and deferred installs in one callback, the same way subscribe did.

On iOS you are removing the Branch line from a delegate method that already exists and already forwards to your linking library. Swap it for the WarpLink call and leave the rest of the method alone. Do not let handleIncomingURL decide the return value: it returns nothing, and replacing the forwarded result breaks React Navigation, Expo Linking, and OAuth callbacks.

Android needs no host code, given android:launchMode="singleTask". See the React Native SDK guide for the Objective-C form and Expo prebuild, and the iOS SceneDelegate hook if your app has a SceneDelegate.

Branch's deferred deep linking on iOS 15+ with Private Relay enabled relies on NativeLink (the $ios_nativelink link parameter), delivered through the same session-init callback as a direct tap. WarpLink runs its deferred check automatically from configure() and delivers the match to the same onLink callback, flagged with isDeferred:

Branch delivers a deferred match through the same sessionBuilder().init() callback used for a direct link open. WarpLink runs its deferred check automatically from configure() and delivers the match to the same onLink callback, flagged with isDeferred:

Branch's subscribe callback also surfaces deferred params on cold start: the result is cached natively and delivered if subscribe is called within a TTL (default 5000ms, configurable via branch.initSessionTtl). WarpLink runs its deferred check automatically from configure() and delivers the match to the same onLink callback, flagged with isDeferred, with no TTL to configure:

To run the check manually instead, set the deferred opt-out flag and call checkDeferredDeepLink() yourself (see the deferred deep link guides for iOS, Android, and React Native).

8. Attribution and Reporting

WarpLink attributes an install to the link that drove it with a multi-tier match cascade (referrer, device ID, and fingerprint matching), returning a match type and confidence score you can use to decide how to route the user. See Install Attribution for the full match cascade and confidence scoring, and the platform attribution guides for iOS, Android, and React Native.

Branch offers several products WarpLink does not replace: SKAdNetwork postback handling, Journeys (deep-link-aware web-to-app smart banners), branded QR codes, one-tap email/SMS link tools, and fraud protection against suspicious clicks and devices. As with any migration, WarpLink does not replace a mobile measurement partner for paid ad network postbacks, SKAdNetwork reporting, or ad spend and cost data; keep that integration in place if Branch currently serves that role for you.

Branch does not publish guidance for running its SDK alongside another provider during a migration off Branch (its published migration guides only cover switching onto Branch from another vendor). A few gotchas to test for during a dual-SDK window:

  • iOS AASA caching. iOS caches the apple-app-site-association file, and a fresh fetch is typically triggered by an app reinstall, so a device that already resolved a Branch link may not immediately pick up your new WarpLink Associated Domains entry.
  • Android App Links verification. Every manifest-referenced domain must host its own .well-known/assetlinks.json, and the sha256_cert_fingerprints value must exactly match your release signing key (uppercase), including Play App Signing's value if you use it. An http/https or www mismatch also breaks verification. Force a re-check with adb shell pm verify-app-links --re-verify.

Testing Checklist

After migration, verify on each platform:

  • SDK initializes: enable debug logging and check console output
  • Deep links open the app: tap a WarpLink URL on a physical device
  • Deep link data resolves: destination and custom parameters are correct
  • Deferred deep links work: click link, install, verify match. An uninstall is enough to retest on either platform, because the completion marker goes with the app. That second install is reported as a reinstall and still counts as an install
  • AASA/assetlinks verified: curl https://aplnk.to/.well-known/apple-app-site-association
  • Error handling: test invalid URLs, expired links, no connectivity
  • All Branch code removed: no remaining imports or dependencies
  • Clean build: no compilation errors

Next Steps

On this page