Elido
12 мин чтенияСравнения

How to migrate from Firebase Dynamic Links to Elido (before your app goes dark)

Firebase Dynamic Links shut down on 2025-08-25. Every FDL link now returns 404. Here's the 30-minute migration path to Elido — EU-hosted, no SDK required.

Marius Voß
DevRel · edge infra
Three-stage timeline showing Firebase Dynamic Links returning 404, then a DNS migration arrow, then Elido deep-link restoration on a dark gradient background

Firebase Dynamic Links shut down on 2025-08-25. Every FDL link now returns 404. If your app was using them for install attribution, deferred deep linking, or post-install routing to a specific screen, those flows are broken in production right now. Branch.io starts at $199/month for the tier that replaces what FDL did for free. Elido's deep-link routing covers the same patterns at a fraction of the cost, with EU data residency built-in.

This is the shortest path from broken FDL links to working Universal Links and Android App Links.

TL;DR#

  • Firebase Dynamic Links shut down on August 25, 2025; all *.page.link URLs return HTTP 404 as of that date, per the Firebase Dynamic Links deprecation FAQ
  • Your app's install attribution, post-install routing, and deferred deep links are broken if you haven't already migrated
  • The migration is a DNS change, two JSON files (one Apple, one Google), and a link rewrite — not a code rewrite
  • Branch.io's entry-level tier for this use case is $199/month; Elido Pro covers the same routing at a substantially lower cost with no per-link metering
  • You don't need to touch your existing deep-link handling code in Swift or Kotlin — the OS-level Universal Link / App Link handoff works the same regardless of which service hosts the routing

FDL was Google's answer to three problems that plain HTTPS links can't solve on their own.

Deferred deep linking. A user on a device without your app clicks a link. The OS opens the App Store or Play Store. The user installs the app. The app opens to a generic home screen and has no idea the user was trying to reach a specific piece of content. FDL stored the intended destination and passed it through the install gap — the app could query FDL's SDK on first launch and route the user to the right screen.

Install attribution. FDL links carried campaign parameters (utm_source, utm_medium, custom parameters via ?st= and ?si=) that survived the install. This is the mechanism that let you attribute an install to a specific email campaign, paid social creative, or influencer link without a third-party MMP.

Platform-aware routing. One link, three destinations: iOS users went to the App Store (or deep into the app if installed), Android users went to Play Store (or the app), and desktop browsers got a configurable fallback URL. The routing happened server-side at Google's edge, not in your app code.

When FDL went down, all three of these capabilities went to 404 simultaneously. If you were using the FDL SDK in your app, it's calling an endpoint that no longer exists.

The Elido equivalent#

Elido replicates the same three behaviors through platform detection at the redirect edge and standard OS deep-link mechanisms.

Platform detection at the edge. An Elido short link inspects the User-Agent header at redirect time and routes to different destinations based on platform: iOS → App Store URL (or app universal link), Android → Play Store URL (or app link intent), desktop → your web fallback. This happens in under 5ms at the redirect plane. No SDK call, no round-trip to a separate attribution service.

iOS Universal Links. When your app is installed on the device, iOS intercepts the HTTPS link before the browser opens. This requires serving an Apple App Site Association (apple-app-site-association) file from the well-known path of your custom domain. Elido hosts this file on your behalf when you configure a custom domain with deep-link routing enabled. The result is identical to what FDL delivered: the app opens directly to the linked screen.

Android App Links. Same mechanism on Android, different file format. Google's assetlinks.json file lives at /.well-known/assetlinks.json on your domain. Elido generates and serves this file when you provide your app's package name and SHA-256 certificate fingerprint. Android App Links open your app directly without a browser interstitial.

Deferred deep link pass-through. For the install-gap case (user doesn't have the app yet), Elido stores the intended deep-link target against the short URL and exposes it via a lightweight query endpoint. Your app calls this endpoint on first launch with the short URL it was installed from — recoverable from the install referrer on Android (INSTALL_REFERRER) and the App Store attribution API on iOS — and gets back the original deep-link path. No FDL SDK, no proprietary handshake. The deep links guide covers the query endpoint contract.

The full feature page is at /features/deep-links.

Step-by-step migration#

This assumes you have an Elido account on Pro or higher and a custom domain you control. Allow 30 minutes for a straightforward migration; add a buffer if your FDL link volume is large enough to require a bulk rewrite script.

Step 1: Add your custom domain to Elido#

In the Elido dashboard, go to Workspace → Custom domains → Add domain. Enter your intended branded domain (e.g. links.yourapp.com). Elido will show you a CNAME record to create.

At your DNS registrar, add the CNAME:

links.yourapp.com.  CNAME  cname.elido.me.

TTL recommendation: lower it to 300 seconds a few hours before you do this if it's currently at 3600+. TLS provisioning is automatic via Caddy on-demand TLS and completes within a few minutes of DNS propagation.

In the domain settings, enable Deep link routing and provide:

  • Your iOS bundle identifier (e.g. com.yourcompany.yourapp)
  • The URL path patterns that should open the app (e.g. /l/* for all short links, or specific paths)

Elido generates and serves the AASA file at https://links.yourapp.com/.well-known/apple-app-site-association. Verify it resolves correctly before moving on:

curl -s https://links.yourapp.com/.well-known/apple-app-site-association | python3 -m json.tool

The response should include your bundle ID in the applinks.details array. iOS CDN caches the AASA file and refreshes it on a schedule; force a refresh in testing by resetting the device's AASA cache via Developer → Reset in iOS Settings, or by installing the app fresh.

Your app's Info.plist must declare the associated domain. If it already does for your FDL domain, add the new domain alongside it during the overlap period:

<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:links.yourapp.com</string>
  <!-- keep FDL domain during overlap if needed -->
</array>

In the same deep-link settings panel, provide:

  • Your app's package name (e.g. com.yourcompany.yourapp)
  • The SHA-256 fingerprint of your release signing certificate

Retrieve the fingerprint if you don't have it cached:

keytool -list -v -keystore release.keystore -alias your-alias | grep SHA256

Elido generates and serves the file at https://links.yourapp.com/.well-known/assetlinks.json. Verify:

curl -s https://links.yourapp.com/.well-known/assetlinks.json | python3 -m json.tool

Your AndroidManifest.xml intent filter should already be configured for App Links if you were using FDL with the Android SDK's auto-verify feature. If not, add the android:autoVerify="true" attribute to your deep-link intent filter and point it at the new domain.

FDL links have the shape https://yourapp.page.link/SLUG or https://yourapp.page.link/?link=https%3A%2F%2F...&.... Neither pattern will keep working — the page.link domain is dead.

If you minted a small number of FDL links (under a few hundred), rewrite them manually in the Elido dashboard. If you minted thousands — common for email campaigns or QR code print runs — use the Elido bulk import API:

curl -X POST https://api.elido.app/v1/links/bulk \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "links": [
      {
        "slug": "welcome",
        "destination": "https://yourapp.com/welcome",
        "routing": {
          "ios": "https://apps.apple.com/app/id12345678",
          "android": "https://play.google.com/store/apps/details?id=com.yourcompany.yourapp",
          "fallback": "https://yourapp.com/welcome"
        }
      }
    ]
  }'

For links already printed on physical materials (packaging, posters, business cards), you can't update the URL itself — but if the printed URL was a custom-domain FDL link pointing at a domain you control, you can repoint that domain's CNAME at Elido and the printed link will start working again with your new routing configuration.

FDL apps call FirebaseDynamicLinks.dynamicLinks().handleUniversalLink(url) or the equivalent SDK method on first launch. Remove that. Replace it with a call to the Elido deferred deep link endpoint:

// iOS — on first launch after install
let installURL = "https://links.yourapp.com/welcome" // recovered from StoreKit attribution
let endpoint = URL(string: "https://api.elido.app/v1/deferred?url=\(installURL.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)")!
URLSession.shared.dataTask(with: endpoint) { data, _, _ in
    guard let data, let result = try? JSONDecoder().decode(DeferredLink.self, from: data) else { return }
    DispatchQueue.main.async { self.navigate(to: result.deepLink) }
}.resume()

The Android equivalent uses the Play Install Referrer API to recover the short URL, then calls the same endpoint. The deep links guide has full code samples for both platforms.

Step 6: Test end-to-end#

Before cutting over, test the three cases:

  1. App installed, link clicked on-device — tap the short link in Safari/Chrome, confirm the app opens directly to the right screen without a browser interstitial.
  2. App not installed, link clicked — tap the link, confirm it routes to the correct App Store / Play Store page.
  3. App installed from store after clicking link — install the app fresh, confirm it opens to the intended screen on first launch (deferred deep link path).

Test on a physical device for Universal Links. iOS simulators don't reliably execute the AASA handoff.

Edge cases#

FDL parameters you were reading in-app. If your app called DynamicLink.dynamicLink().url to read parameters from an FDL link after opening, those parameters are now gone. You need to encode the same information into your Elido short link's destination URL as query parameters and read them from the deep link URL that iOS or Android delivers to your app. The parameter encoding is the same — ?screen=onboarding&ref=email_april — just moved from FDL's proprietary link= wrapper into the destination URL itself.

Attribution loss. FDL's attribution was self-contained: Google stored the campaign parameters and returned them to the SDK. Elido stores click-event data (timestamp, platform, country, referrer) in ClickHouse and exposes it via the analytics API, but it is not an MMP (mobile measurement partner). If you need probabilistic or deterministic install attribution at scale — cohort analysis, LTV by acquisition source, SKAdNetwork stitching — you need either an MMP (Adjust, AppsFlyer) or to instrument the Elido click webhook into your own analytics pipeline. For most indie apps and early-stage teams that were using FDL purely for "route the user to the right screen", Elido's analytics are sufficient. For paid-acquisition teams running multi-channel attribution, see the next section.

Existing page.link short URLs already embedded in your app binary. If you hardcoded FDL short URLs in your app code (push notification payloads generated client-side, referral links minted from the app), those strings reference a dead domain. You need a forced app update or a server-side endpoint that generates the new short URL on demand. There's no way to redirect page.link — Google shut the domain down completely.

Long FDL URLs with encoded parameters. FDL supported long-form URLs like https://yourapp.page.link/?link=https%3A%2F%2F...&ibi=com.yourapp&ifl=...&afl=.... These parameters (ibi, ifl, afl, isi) are FDL-specific. Map them to Elido routing fields: ifl (iOS fallback) → routing.ios, afl (Android fallback) → routing.android, ibi (iOS bundle ID) is already configured at the domain level in Elido. The link parameter becomes your destination URL.

EU data residency. If your app operates in the EU and you process EU user data, redirect events — including IP addresses and User-Agent strings — are personal data under GDPR. FDL was hosted on Google's global infrastructure with US processing. Elido is hosted in Frankfurt by default; EU click events stay in the EU. The trust page and compliance overview cover the contractual specifics.

When you actually need Branch.io instead#

Elido is the right choice for most apps that used FDL for screen routing and basic install attribution. It is not the right choice if you depend on:

Probabilistic attribution for paid UA. Branch integrates with ad networks (Meta, Google, TikTok, Snap) via postbacks and can attribute installs probabilistically when the deterministic fingerprint isn't available — e.g., on iOS 14.5+ with ATT not consented. Elido does not do probabilistic attribution. If your growth team is running paid UA and needs to reconcile installs against ad spend at the cohort level, Branch or an MMP (Adjust, AppsFlyer) is the right tool for that specific problem.

SDK-level fingerprinting and device matching. Branch's SDK collects device signals (screen resolution, IP, language, timezone) to fingerprint a device across the install gap without relying on an install referrer. Referrer-only matching degrades in environments where the referrer is stripped — if your deferred deep link hit rate needs to exceed ~80%, the SDK-level approach performs better.

Deep integration with specific ad networks. Branch has dedicated integrations with Meta's CAPI, Google's conversion tracking, and TikTok's events API that go beyond what Elido's server-side conversion forwarding covers. If your attribution stack is tightly coupled to one of those networks, evaluate Branch's specific integration documentation before switching.

The practical test: if you were using FDL primarily to route users to the right screen after install, and your attribution needs are covered by UTM parameters in your analytics tool, Elido replaces FDL at lower cost. If you're running performance marketing at scale and attribution accuracy drives budget decisions, that's Branch's actual value proposition and $199/month buys real infrastructure for it.

FAQ#

My app has FDL short links in push notification payloads — what happens when users tap them?

The links point at page.link, which returns 404. The OS's link handling passes the 404 back to the browser or your app's universal link handler, which will fail. You need to update your push notification service to generate Elido short links instead. If you're generating push payloads server-side (the correct approach), this is a one-line change to call the Elido API instead of the FDL API. If payloads are generated client-side from hardcoded templates, you need an app update.

Do I need to ship an app update to complete the migration?

For the deferred deep link query (install-gap routing), yes — you need to replace the FDL SDK call with the Elido endpoint call, which requires an app update. For Universal Links and Android App Links to the already-installed app, no app update is needed once DNS and the AASA/assetlinks.json files are in place — the OS queries these files from the server, not from the app binary. The one exception: if your Info.plist / AndroidManifest.xml doesn't yet declare your new domain as an associated domain, that requires an app update.

What happens to clicks on old FDL links after I complete the migration?

If the old link was at a page.link domain: nothing — that domain is dead and those links are unrecoverable. If you were using a custom domain for FDL (less common but supported), repoint the domain's CNAME at Elido and configure equivalent routing rules; the old URLs will start resolving again.

Does Elido have an SDK?

Elido doesn't require an SDK for Universal Links or App Links — those are OS-native mechanisms. For the deferred deep link query endpoint, you make a standard HTTPS call; no SDK dependency is needed. If you want a typed client, the Elido Go SDK, TypeScript SDK, and Python SDK all wrap the deep link API, but there's no iOS/Android SDK and you don't need one. This is by design — the fewer third-party SDKs in a production app, the better.

How long does AASA / assetlinks.json propagation take?

Once your DNS propagates (a few minutes to an hour depending on TTL), the AASA and assetlinks.json files are immediately available from Elido's edge. iOS refreshes its cached copy of the AASA file on app install and periodically thereafter; the delay you'll notice in testing is iOS's cache staleness, not Elido's serving latency. For a clean test, install the app fresh after the DNS change has propagated.


If you're looking at the broader deep linking feature set, the /features/deep-links page covers platform support matrix and routing rule depth. For EU data residency specifics relevant to mobile apps collecting EU user data, the compliance overview has the DPA and sub-processor list your privacy team will ask for.

Попробуйте Elido

URL-сокращатель с хостингом в ЕС: собственные домены, глубокая аналитика, открытый API. Бесплатный тариф — без банковской карты.

Теги
firebase dynamic links
firebase dynamic links replacement
deep linking
ios universal links
android app links
elido deep links

Читать дальше