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 Concept | WarpLink Concept |
|---|---|
| Quick Link / Ad Link | Link |
| Alias | Slug |
app.link / bnc.lt domain | yourapp.aplnk.to (your app's subdomain) or a custom domain |
| Custom domain (CNAME or NS delegation) | Custom domain |
$-prefixed link parameters | Link fields (see parameter mapping below) |
| LinkHub (Dashboard → Manager) | WarpLink dashboard Links page |
1. Export Your Links
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:
GET /v1/url?url=<url>&branch_key=<branch key>
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.
2. Recreate Your Links
Recreate your Branch links in WarpLink via the dashboard or the REST API.
Parameter Mapping
| Branch Parameter | WarpLink Field |
|---|---|
| Alias | slug |
$fallback_url | destination_url |
$ios_url | ios_fallback_url |
$android_url | android_fallback_url |
$deeplink_path / $ios_deeplink_path | ios_url |
$android_deeplink_path | android_url |
$og_title | og_title |
$og_description | og_description |
$og_image_url | og_image_url |
$exp_date | expires_at |
$match_duration | match_window_hours |
Repeated ~tags query parameters | tags |
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 |
Carry any other Branch link data over as destination_url query parameters.
Create via API
curl -X POST https://api.warplink.app/v1/links \
-H "Authorization: Bearer wl_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination_url": "https://yourapp.com/product/123",
"ios_url": "myapp://product/123",
"ios_fallback_url": "https://apps.apple.com/app/id123456789",
"android_url": "myapp://product/123",
"android_fallback_url": "https://play.google.com/store/apps/details?id=com.example.myapp",
"og_title": "Check out this product",
"expires_at": "2027-12-31T00:00:00Z"
}'
3. Swap the SDK
Remove Branch:
- Remove the
BranchSDKpackage (CocoaPodspod 'BranchSDK', SPMhttps://github.com/BranchMetrics/ios-branch-sdk-spm, or Carthagegithub "BranchMetrics/ios-branch-deep-linking") - Remove the
Branch.getInstance()/initSession(launchOptions:)call - Remove the
branch_keyandbranch_universal_link_domainskeys fromInfo.plist - Remove the
applinks:subdomain.app.linkAssociated Domains entries (including the-alternateand.testvariants)
Add WarpLink:
// Package.swift
dependencies: [
.package(url: "https://github.com/WarpLinkApp/warplink-ios-sdk", from: "1.2.0")
]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 Keys > SDK keys. Only an SDK key records installs.
Before (Branch):
Branch.getInstance().initSession(launchOptions: launchOptions)After (WarpLink):
import WarpLink
WarpLink.configure(
apiKey: "wl_live_yoursdkkeyhere000000000000000000",
options: WarpLinkOptions(onLink: { result in
if case .success(let link) = result, let link {
navigate(to: link) // taps AND deferred installs (check link.isDeferred)
}
})
)5. Update Domain Configuration
In Signing & Capabilities > Associated Domains:
- applinks:yourapp.app.link
+ applinks:yourapp.aplnk.toRemove every applinks: entry for your app.link (and legacy bnc.lt) subdomain, including the -alternate and .test variants Branch adds automatically.
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.
6. Migrate Deep Link Handling
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:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
WarpLink.open(url) // was Branch's handler
return true
}
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
WarpLink.continue(userActivity) // was Branch's handler
return true
}Resolved links arrive in your onLink callback. Or set your delegate class to the drop-in WarpLinkAppDelegate / WarpLinkSceneDelegate and skip writing these methods yourself.
7. Migrate Deferred Deep Links
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:
options: WarpLinkOptions(onLink: { result in
guard case .success(let deepLink) = result, let deepLink else { return }
if deepLink.isDeferred {
print("Match confidence: \(deepLink.matchConfidence ?? 0)")
}
navigate(to: deepLink)
})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, React Native, and Flutter).
8. Attribution and Reporting
WarpLink attributes an install to the link that drove it with a multi-tier match cascade (referrer, device ID, and probabilistic 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, React Native, and Flutter.
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-associationfile, 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 thesha256_cert_fingerprintsvalue must exactly match your release signing key (uppercase), including Play App Signing's value if you use it. An http/https orwwwmismatch also breaks verification. Force a re-check withadb 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://yourapp.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
- Migration Overview: the provider-agnostic playbook for domains, cutover, and decommissioning.
- Quickstart: create your first link and get an SDK key.
- iOS SDK, Android SDK, React Native SDK, and Flutter SDK: full setup and API reference.
- Branch.io alternative for indie developers and Branch pricing compared: how WarpLink compares to Branch.
Your App's Own Link Address
Set up your app's own {handle}.aplnk.to link address, test it on a phone, and make it the default for new links. Existing links keep their addresses.
AppsFlyer Migration
Migrate from AppsFlyer OneLink to WarpLink: link and parameter mapping, SDK swap, and deep linking, install attribution, and analytics.