Skip to main content
Documentation
Migration

Firebase Dynamic Links Migration

Recover from the Firebase Dynamic Links shutdown: recreate links, swap the SDK, and restore deep linking, install attribution, and analytics.

This guide is for teams whose links broke when Firebase Dynamic Links shut down: recreating those links on WarpLink, swapping the SDK, and restoring deep linking, install attribution, and analytics. It assumes a WarpLink account and app are already set up.

For the provider-agnostic playbook (planning, domains, cutover, decommissioning), see the general migration guide. This page covers only what is specific to recovering from Firebase Dynamic Links.

Firebase Dynamic Links shut down on August 25, 2025. Google says all Firebase Dynamic Links, on page.link domains and on custom domains, now return an error. There is nothing to reconfigure on the Firebase side, only links to recreate elsewhere.

Some Firebase Dynamic Links still redirect, for now

Google says all Firebase Dynamic Links now return 404. On October 8, 2026 we requested 32 real page.link short links from 25 domains found in the September 2026 Common Crawl, the way an iPhone does. 25 still redirected, 15 to the app's own website or store and 10 to a Firebase preview page. The other 7 returned an error or no redirect. A redirect only sends the tap to a web destination. Google can end these redirects at any time, and we do not know when. Migrate before they stop. To see whether a given link still redirects, use the Firebase Dynamic Links checker.

Concept Mapping

Firebase Dynamic LinksWarpLink
Dynamic LinkLink
Firebase console (Dynamic Links section)WarpLink dashboard
page.link domainyourapp.aplnk.to (your app's subdomain) or a custom domain
Firebase Hosting custom domainCustom domain
Link parameters (link, apn, ibi, social metadata)Link fields + OG tags
Google Analytics link-open loggingBuilt-in click analytics, viewed in the WarpLink dashboard

Firebase Dynamic Links has no working export path today. The Short Links and Link Stats REST APIs return errors, and the Dynamic Links section of the Firebase console is gone with the rest of the shut-down product. Google deleted the page.link prefix domains, so a link on one that still redirects today can stop at any time. Google says links on a Firebase Hosting custom domain also 404, because the firebase.json rewrite that routed them to the Dynamic Links backend has nothing left to route to.

Rebuild your link list from whatever sources you still control:

  • App code. Deep link URLs are often hardcoded or referenced in app source, App Store or Play Store listings, or push notification payloads.
  • Marketing materials. Emails, ads, social bios, and printed QR codes that carried a Dynamic Link. Each one is a link you need to recreate before the material stops working.
  • Analytics referrers. Any analytics tool that recorded traffic from your page.link or Dynamic Links custom domain can reconstruct which destinations and campaigns mattered, even without the original link configuration.
  • A prior Google Takeout export. If your team exported Dynamic Link metadata via Google Takeout before the shutdown, that CSV is your best source. Firebase's own export documentation describes roughly 29 fields per link, including the short link, the destination URL, platform identifiers, fallback links, social preview text, and UTM parameters. That export cannot be run now that the product is shut down. If nobody on the team ran it, treat those links as gone and rebuild from the sources above.

Recreate each Dynamic Link in WarpLink via the dashboard or the REST API.

Parameter Mapping

Firebase ParameterWarpLink Field
link (deep link)destination_url. The SDK hands it to your app as deepLink.destination.
apn (Android package name) / ibi (iOS bundle ID)Configured once per app (android_package_name / ios_bundle_id), not per link
isi (App Store ID)Configured once per app as ios_app_store_url, https://apps.apple.com/app/id<ID>, the default iOS fallback for every link
afl / ifl (fallback links)android_fallback_url / ios_fallback_url
ofl (desktop fallback link)Desktop browsers open destination_url.
ius (iOS custom URL scheme)WarpLink opens the app through Universal Links and passes the link to onLink.
efr=1 (skip the iOS app-preview interstitial)Not needed. WarpLink redirects real users with a 302 and serves preview tags only to bots.
st / sd / si (social metadata)og_title / og_description / og_image_url
utm_source / utm_medium / utm_campaignSame fields on the link
utm_term / utm_contentAdd them as injected parameters on the link, which appends them to the destination.

Create via API

Firebase's own Short Links API (POST https://firebasedynamiclinks.googleapis.com/v1/shortLinks) now returns errors, so this is not a live migration path, only the shape you are replacing. Custom slugs on WarpLink are 2 to 100 characters, lowercase alphanumeric with hyphens. Decide on a slug mapping before scripting if you want to preserve your old link paths.

3. Swap the SDK

Remove Firebase:

  1. Remove the FirebaseDynamicLinks package (SPM from firebase-ios-sdk.git, or CocoaPods Firebase/DynamicLinks)
  2. Remove DynamicLinks.dynamicLinks().handleUniversalLink(...) and DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL:)
  3. Remove the -ObjC linker flag if it was added solely for this SDK, the Associated Domains entitlement for your old Dynamic Links domain, and (if set) the FirebaseDeepLinkPasteboardRetrievalEnabled Info.plist key
  4. Remove FirebaseApp.configure() unless you use other Firebase services

Add WarpLink:

Remove Firebase:

Also remove the <intent-filter> tied to your old Dynamic Links domain, and any Firebase.dynamicLinks.getDynamicLink(intent) handling.

Add WarpLink:

Remove Firebase:

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:

Remove Firebase:

Also remove FirebaseDynamicLinks.instance.getInitialLink() and FirebaseDynamicLinks.instance.onLink from your Dart code, and Firebase.initializeApp() unless you use other Firebase services.

Add WarpLink:

The iOS SDK is distributed through Swift Package Manager, so there is no Podfile change. If your Flutter version does not use Swift Package Manager by default, run flutter config --enable-swift-package-manager once.

4. Update SDK Initialization

Mobile apps authenticate with an SDK key, created in the dashboard under Keys > SDK keys. An API key looks identical but cannot record installs, so pasting one here leaves deep links working while attribution silently fails.

Before (Firebase):

After (WarpLink):

Before (Firebase):

After (WarpLink):

Before (Firebase):

After (WarpLink):

Before (Firebase):

After (WarpLink):

5. Update Domain Configuration

In Signing & Capabilities > Associated Domains:

Find your app's subdomain in the dashboard: open the app, then Settings. Or see Your app's own link address.

In AndroidManifest.xml, update the intent filter host:

page.link domains are Google-owned. Google says Dynamic Links has shut down and offers no forwarding, so any link built on a page.link domain must be reissued on a new domain. If your links instead used a custom domain you added to Firebase Hosting, the domain itself is yours: after you recreate your links on WarpLink, remove the old firebase.json Dynamic Links rewrite and point that domain at WarpLink. Existing shares, QR codes, and bookmarks on that domain keep working once the repoint is live.

Moving to a custom domain? Declare it to the SDK too: 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.

The onLink callback set in step 4 already receives resolved links for cold start, warm start, and deferred installs.

Delete the DynamicLinks.dynamicLinks().handleUniversalLink(...) and DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL:) calls. Forward the incoming activity to WarpLink (or set your scene delegate class to WarpLinkSceneDelegate):

Resolved links arrive in your onLink callback.

Delete the Firebase.dynamicLinks.getDynamicLink(intent).addOnSuccessListener { ... }.addOnFailureListener { ... } block. Cold start is automatic. For warm start, forward new intents and set android:launchMode="singleTask" on the Activity:

Resolved links arrive in your onLink callback.

Delete the dynamicLinks().getInitialLink() and dynamicLinks().onLink(...) calls. Cold and warm start flow into onLink automatically.

On iOS you are removing the Firebase call from a delegate method that already exists and already forwards to your linking library. Swap the Firebase line 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 (Info.plist declares UIApplicationSceneManifest): iOS stops calling the AppDelegate method above once a scene exists.

Delete the FirebaseDynamicLinks.instance.getInitialLink() call and the FirebaseDynamicLinks.instance.onLink.listen(...) subscription. Cold and warm start flow into onLink automatically.

There is no delegate or Activity code to port. The plugin registers with Flutter's iOS and Android lifecycles, so the Firebase forwarding you may have added to AppDelegate or MainActivity can go. Set minSdk = 26 in android/app/build.gradle.kts, and see the Flutter SDK guide for the Associated Domains capability, the intent filter, and Flutter's own link handling.

WarpLink runs the deferred deep link check automatically from configure(). The match arrives in the same onLink callback, flagged with isDeferred. There is no separate deferred call to port from Firebase.

This matters more for a Firebase migration than it might elsewhere. Google's own migration guidance for Dynamic Links is explicit that switching to native App Links and Universal Links does not include deferred deep linking: there is no "continue the user's journey after they install the app" behavior without a third-party SDK, only the app opening to its default screen. An app that relied on Dynamic Links resuming a user's journey after an install needs a real replacement for that, not just updated Associated Domains entries.

Handle the deferred case inside your onLink callback:

Handle the deferred case inside your onLink callback:

Handle the deferred case inside your onLink callback:

Handle the deferred case inside your onLink callback:

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

8. Attribution and Reporting

WarpLink attributes installs to the link that drove them through a match cascade: an exact referrer signal (Play Install Referrer) on Android, an enriched probabilistic match on both platforms, and a device ID (IDFV) check on iOS that recognizes an install asking again, with a confidence score on every result. See the iOS attribution guide (or the Android, React Native, and Flutter equivalents) for match types, confidence bands, and privacy details.

Firebase Dynamic Links did not provide install attribution beyond link-open tracking. Click analytics for every link appear in the WarpLink dashboard. View your link reporting there, or send the event to Google Analytics from inside the app.

There is no live Firebase SDK to run alongside WarpLink during a transition: Dynamic Links is shut down, not merely deprecated, so there is no dual-SDK overlap period to manage. A physical device test, click a link and confirm the install, is the only way to verify the new setup, since the old provider can no longer serve a side-by-side comparison.

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 and curl https://yourapp.aplnk.to/.well-known/assetlinks.json
  • Error handling: test invalid URLs, expired links, no connectivity
  • All Firebase code removed: no remaining imports or dependencies
  • Clean build: no compilation errors

Next Steps