← Back to list

Firebase Dynamic Links was shut down. What to do next?

A working replacement for Flutter apps, without an SDK.

Poong Ka Vui · 2026-07-28 03:21 · 0 claps · 5.3 min read paywalled
#firebasedynamiclinks #dynamic-link #flutter-dynamic-link
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

Firebase Dynamic Links was shut down. What to do next?

A working replacement for Flutter apps, without an SDK.

If you had a Flutter app using Firebase Dynamic Links, you already know what happened. One day your page.link URLs just stopped resolving. Install links in your marketing, referral links, the QR code on your poster, all dead.

Google shut Firebase Dynamic Links down in August 2025. There was a deprecation notice, and like most of us I filed it under “deal with it later”. Later arrived.

This post is what I learned rebuilding it. There is no drop-in replacement, but the part most apps actually use is simpler than the SDK you were relying on. I will go through what broke, the four rules a replacement has to follow, the exact Android intent URL that trips people up, and the three options you have.

What Firebase Dynamic Links actually did

Two jobs:

  1. Device routing. One URL that sends an iPhone to the App Store, an Android phone to Google Play, and a laptop to your website.
  2. Deferred deep linking. Carrying parameters through an install, so a user who clicks a link to a specific product, installs the app, and opens it, lands on that product instead of the home screen.

Most apps only ever needed the first one. If that is you, you can replace it in an afternoon. If you genuinely need the second one, that is a heavier feature and I will be honest about it at the end.

What broke, specifically

Every dynamic link stopped resolving. Not degraded, gone. That means:

  • App Store and Play Store links in your website and emails
  • Referral and invite links inside your app
  • QR codes you already printed
  • Any campaign link you shared on WhatsApp or Facebook

The printed QR codes were the painful one for me. You cannot patch a poster.

The four rules a replacement must follow

Whatever you build or buy, the link has to do these four things. The first two are obvious. The last two are where I have seen most rebuilds break.

  1. iOS goes to the App Store. Read the User-Agent, look for iPhone, iPad or iPod, redirect to your App Store listing. A plain 302 is fine.

  2. Android opens the app if installed, Play Store if not. This is the part that needs a specific URL format. More on it below.

  3. Desktop goes to your website. Do not send a laptop to the App Store. It is a dead end. Your website is the useful destination for anyone on a computer.

  4. Crawlers must never be sent to a store or an intent URL. This is the one that bit me. WhatsApp, Facebook, Telegram and Slack all fetch your link to build a preview card. If you hand that crawler the same thing you hand a phone, it either shows a confusing App Store page or, with an intent:// URL, nothing at all. Detect crawler User-Agents and send them to your web destination so they can read its Open Graph tags, or serve the tags yourself.

Worth checking your destination site actually has those tags. I found out mine was missing an og:image while writing this, which is why my links previewed as plain text instead of a card.

The Android intent URL

Here is the format. This is the piece worth copying:

intent://yoursite.com/path#Intent;
  scheme=https;
  package=com.your.app;
  S.browser_fallback_url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dcom.your.app;
end

Three things to notice:

  • package= is your Android application ID. In Flutter this is the applicationId in android/app/build.gradle, not your Dart package name.
  • S.browser_fallback_url is what saves everyone who does not have the app installed. Without it, those users hit a dead page. With it, they land on the Play Store. It must be URL-encoded.
  • scheme=https matches the scheme of the URL your app is registered to handle.

If the app is installed and registered for that link, Android opens it. If not, the browser follows the fallback. One URL, both cases covered.

What about Universal Links and App Links?

Fair question, and worth knowing the difference.

Universal Links (iOS) and App Links (Android) let the operating system open your app directly, before a browser is even involved. They are a better experience when the app is installed. But they need two things:

  1. Files hosted on your domain: apple-app-site-association and assetlinks.json
  2. Configuration inside the app: entitlements on iOS, intent filters on Android

That means a code change and a new App Store release. And critically, they only handle the case where the app is already installed. If it is not, the OS just loads the URL in a browser, and you still need a server that decides where to send that person.

So they are complementary, not a replacement. Firebase Dynamic Links did both. If you want the full experience, do both. If you just need your install links working again this week, the User-Agent routing above is enough and needs no app release.

Your three options

Option 1: Build it yourself. It is roughly 30 lines in any serverless function. Cloudflare Workers, Vercel, Firebase Functions, whatever you already use. Free, and you control it. You own the hosting, the TLS certificate, the crawler edge cases, and if you want click analytics you build that too.

Option 2: Flinku. Open source, with SDKs for Flutter, iOS, Android, React Native and others. If you want to self-host and do not mind running it, this is a solid choice and it is free.

Option 3: A hosted link. Branch and AppsFlyer are the established players. They are excellent at attribution and they are priced for companies with a marketing budget, starting around $299 a month. For most indie apps that is not the right shape.

What I ended up building

I got quoted enterprise pricing for what is fundamentally a redirect, so I built the redirect. It is called Linkbah. Disclosure up front: this is my product, so weigh my opinion accordingly. The four rules above apply whatever you choose.

It is the four rules as a hosted link. You paste your website URL, your App Store URL, your Play Store URL and your Android package name, and you get a URL. No SDK, nothing changes in your Flutter project, no new release.

I use it on my own app, Reviewbah, which is the one whose QR codes I could not patch. This is the real link, answering three different devices:

$ $ curl -A 'iPhone' linkbah.app/reviewbah
302 -> apps.apple.com/my/app/reviewbah-your-local-guide/id1603402647

$ curl -A 'Android' linkbah.app/reviewbah
intent://reviewbah.com/#Intent;scheme=https;
  package=my.themaker.sabahreview;
  S.browser_fallback_url=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2F
  details%3Fid%3Dmy.themaker.sabahreview;end

$ curl -A 'Mac' linkbah.app/reviewbah
302 -> reviewbah.com

That link is live, so you can test it yourself right now on whatever device you are reading this on: linkbah.app/reviewbah

It runs on Cloudflare Workers so the redirect happens at the edge, and it counts clicks by device so you can see whether your audience is actually on iOS or Android.

The free plan is one link with one app store. Routing iOS and Android from the same link is the paid plan, so I am not going to pretend the whole thing is free.

What this does not do

Being straight about the limits, because I would want to know:

  • No install attribution. If you need to know which ad campaign drove an install, you want Branch or AppsFlyer. That is a different product category.
  • No deferred deep linking with parameters through install. If a user must land on a specific screen after installing, that needs an SDK.
  • No A/B testing or ad-network integrations.

If you need those, use the tools built for them. If you need one URL that gets people to the right store, you do not need any of that machinery.

The short version

Firebase Dynamic Links is not coming back. The replacement is a link that branches on User-Agent: App Store for iOS, an intent:// URL with a browser_fallback_url for Android, your website for desktop, and leave the crawlers alone so your link previews survive.

Build it yourself in 30 lines, run Flinku, or use something hosted. Any of the three beats leaving your install links dead.

I wrote a longer technical version of this with the full setup here: linkbah.app/firebase-dynamic-links-alternative

If you are dealing with this migration and get stuck on the intent URL or the crawler handling, leave a comment. Those two are where everyone loses time, including me.

[embed]


메타데이터
post_id
77b5268be46a
slug
firebase-dynamic-links-was-shut-down-what-to-do-next-77b5268be46a
url
https://medium.com/@vaytrex/firebase-dynamic-links-was-shut-down-what-to-do-next-77b5268be46a
canonical_url
https://medium.com/@vaytrex/firebase-dynamic-links-was-shut-down-what-to-do-next-77b5268be46a
author_url
https://medium.com/@vaytrex
status
ok
fetched_at
2026-08-04 07:10:45