{"id":848,"date":"2026-04-19T09:00:00","date_gmt":"2026-04-19T14:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=848"},"modified":"2026-03-07T03:48:27","modified_gmt":"2026-03-07T08:48:27","slug":"migrate-from-firebase-dynamic-links","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/migrate-from-firebase-dynamic-links\/","title":{"rendered":"Firebase Dynamic Links Migration Guide"},"content":{"rendered":"\n<p>Google deprecated Firebase Dynamic Links in August 2023 and shut down the service in August 2025. If you&#39;re still relying on Firebase Dynamic Links (FDL) or its compatibility shims, your links are either already broken or operating on borrowed time.<\/p>\n\n\n\n<p>This guide walks you through migrating from Firebase Dynamic Links to Tolinku, covering link mapping, SDK replacement, and handling existing links that are still circulating.<\/p>\n\n\n\n<p>For the general migration guide covering multiple providers, see <a href=\"https:\/\/tolinku.com\/blog\/migrating-to-tolinku\/\">Migrating to Tolinku from Branch, Firebase, and AppsFlyer<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding What You&#39;re Migrating<\/h2>\n\n\n\n<p>Firebase Dynamic Links had a relatively simple feature set:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Short links<\/strong>: <code>yourapp.page.link\/xyz<\/code> or a custom domain<\/li>\n<li><strong>Deep link routing<\/strong>: Open a specific screen in the app based on the link URL<\/li>\n<li><strong>Deferred deep linking<\/strong>: Preserve link data through the app store install process<\/li>\n<li><strong>Social meta tags<\/strong>: OG tags for link previews<\/li>\n<li><strong>Analytics<\/strong>: Basic click and conversion tracking in the Firebase console<\/li>\n<\/ul>\n\n\n\n<p>All of these have direct equivalents in Tolinku. The migration is mostly about remapping your link patterns and replacing the SDK.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Audit Your Firebase Dynamic Links<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Export Your Links<\/h3>\n\n\n\n<p>Firebase Dynamic Links had two types:<\/p>\n\n\n\n<p><strong>Manually created links<\/strong> (in the Firebase console): These have short URLs like <code>yourapp.page.link\/promo<\/code>. List all of them and their deep link parameters.<\/p>\n\n\n\n<p><strong>Programmatically created links<\/strong> (via the API or SDK): These are created in your app or server code using the Firebase Dynamic Links API. Search your codebase for:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>DynamicLinks<\/code> (iOS)<\/li>\n<li><code>FirebaseDynamicLinks<\/code> (Android)<\/li>\n<li><code>https:\/\/firebasedynamiclinks.googleapis.com\/v1\/shortLinks<\/code> (REST API)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Document Link Parameters<\/h3>\n\n\n\n<p>For each link, record:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>Parameter<\/th>\n<th>FDL Field<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td>Deep link URL<\/td>\n<td><code>link<\/code><\/td>\n<td><code>https:\/\/yourapp.com\/product\/123<\/code><\/td>\n<\/tr>\n<tr>\n<td>iOS bundle ID<\/td>\n<td><code>isi<\/code> \/ <code>ibi<\/code><\/td>\n<td><code>com.yourcompany.yourapp<\/code><\/td>\n<\/tr>\n<tr>\n<td>Android package<\/td>\n<td><code>apn<\/code><\/td>\n<td><code>com.yourcompany.yourapp<\/code><\/td>\n<\/tr>\n<tr>\n<td>iOS fallback<\/td>\n<td><code>ifl<\/code><\/td>\n<td><code>https:\/\/yourapp.com\/product\/123<\/code><\/td>\n<\/tr>\n<tr>\n<td>Android fallback<\/td>\n<td><code>afl<\/code><\/td>\n<td><code>https:\/\/yourapp.com\/product\/123<\/code><\/td>\n<\/tr>\n<tr>\n<td>OG title<\/td>\n<td><code>st<\/code><\/td>\n<td><code>Check out this product<\/code><\/td>\n<\/tr>\n<tr>\n<td>OG description<\/td>\n<td><code>sd<\/code><\/td>\n<td><code>Amazing product at 50% off<\/code><\/td>\n<\/tr>\n<tr>\n<td>OG image<\/td>\n<td><code>si<\/code><\/td>\n<td><code>https:\/\/yourapp.com\/img\/product.jpg<\/code><\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Identify Where Links Are Used<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Email campaigns (ESPs, transactional emails)<\/li>\n<li>Push notifications<\/li>\n<li>Social media posts<\/li>\n<li>QR codes (printed materials)<\/li>\n<li>Referral\/invite systems<\/li>\n<li>In-app sharing features<\/li>\n<li>Partner integrations<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Set Up Tolinku<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Create Your Appspace<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Sign up at <a href=\"https:\/\/tolinku.com\">tolinku.com<\/a><\/li>\n<li>Create an Appspace for your app<\/li>\n<li>Enter your iOS Bundle ID and Team ID<\/li>\n<li>Enter your Android Package Name and SHA-256 fingerprint<\/li>\n<li>Set your default web fallback URL<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Set Up Your Domain<\/h3>\n\n\n\n<p><strong>If you used <code>yourapp.page.link<\/code><\/strong> (Firebase&#39;s default domain): You can&#39;t migrate this domain because Google owns it. You&#39;ll need a new domain. Set up a branded subdomain like <code>go.yourapp.com<\/code>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add the domain in Tolinku&#39;s <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/domains\/\">Domains<\/a> settings<\/li>\n<li>Create a CNAME record pointing <code>go<\/code> to Tolinku&#39;s link server<\/li>\n<li>Wait for DNS propagation and SSL provisioning<\/li>\n<\/ol>\n\n\n\n<p><strong>If you used a custom domain with FDL<\/strong>: You can reuse that domain. Update the DNS to point to Tolinku instead of Firebase.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create Routes<\/h3>\n\n\n\n<p>Map your Firebase Dynamic Link patterns to Tolinku <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/routes\/\">routes<\/a>:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table>\n<thead>\n<tr>\n<th>FDL Pattern<\/th>\n<th>Tolinku Route<\/th>\n<\/tr>\n<\/thead>\n<tbody><tr>\n<td><code>link=https:\/\/yourapp.com\/product\/123<\/code><\/td>\n<td>Route path: <code>\/product\/:id<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>link=https:\/\/yourapp.com\/invite?code=ABC<\/code><\/td>\n<td>Route path: <code>\/invite\/:code<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>link=https:\/\/yourapp.com\/promo\/summer<\/code><\/td>\n<td>Route path: <code>\/promo\/summer<\/code><\/td>\n<\/tr>\n<\/tbody><\/table><\/figure>\n\n\n\n<p>In Tolinku, the route path IS the deep link path. There&#39;s no separate &quot;link&quot; parameter; the URL structure itself defines the routing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Replace the SDK<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Remove Firebase Dynamic Links SDK<\/h3>\n\n\n\n<p><strong>iOS<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Remove <code>FirebaseDynamicLinks<\/code> from your Podfile, Package.swift, or SPM dependencies<\/li>\n<li>Remove the <code>FirebaseDynamicLinksCustomDomains<\/code> entry from Info.plist<\/li>\n<li>Remove the Associated Domains entitlement for <code>yourapp.page.link<\/code><\/li>\n<li>Remove <code>DynamicLinks.dynamicLinks().handleUniversalLink()<\/code> from your link handling code<\/li>\n<li>Remove any <code>DynamicLinkComponents<\/code> link creation code<\/li>\n<\/ol>\n\n\n\n<p><strong>Android<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Remove <code>com.google.firebase:firebase-dynamic-links<\/code> from build.gradle<\/li>\n<li>Remove <code>FirebaseDynamicLinks.getInstance()<\/code> calls<\/li>\n<li>Remove intent filters for Firebase Dynamic Links domains<\/li>\n<li>Remove any <code>DynamicLink.Builder<\/code> link creation code<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Add Tolinku SDK<\/h3>\n\n\n\n<p><strong>iOS<\/strong>: Add TolinkuSDK and configure Universal Links:<\/p>\n\n\n\n<p>Add to your Associated Domains entitlement:<\/p>\n\n\n\n<pre><code>applinks:go.yourapp.com\n<\/code><\/pre>\n\n\n\n<p>Handle incoming links:<\/p>\n\n\n\n<pre><code class=\"language-swift\">func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {\n    guard let url = userActivity.webpageURL else { return }\n    \/\/ Route based on URL path\n    let path = url.path\n    if path.hasPrefix(&quot;\/product\/&quot;) {\n        let productId = String(path.dropFirst(&quot;\/product\/&quot;.count))\n        navigateToProduct(id: productId)\n    } else if path.hasPrefix(&quot;\/invite\/&quot;) {\n        let code = String(path.dropFirst(&quot;\/invite\/&quot;.count))\n        handleInvite(code: code)\n    }\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Android<\/strong>: Add the Tolinku SDK and configure App Links:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n    &lt;data\n        android:scheme=&quot;https&quot;\n        android:host=&quot;go.yourapp.com&quot; \/&gt;\n&lt;\/intent-filter&gt;\n<\/code><\/pre>\n\n\n\n<p>Handle incoming intents:<\/p>\n\n\n\n<pre><code class=\"language-kotlin\">private fun handleDeepLink(intent: Intent) {\n    val uri = intent.data ?: return\n    when {\n        uri.path?.startsWith(&quot;\/product\/&quot;) == true -&gt; {\n            val productId = uri.lastPathSegment\n            navigateToProduct(productId)\n        }\n        uri.path?.startsWith(&quot;\/invite\/&quot;) == true -&gt; {\n            val code = uri.lastPathSegment\n            handleInvite(code)\n        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Key Difference: Data Handling<\/h3>\n\n\n\n<p>Firebase Dynamic Links passed data through a special <code>link<\/code> parameter and additional metadata accessible via the SDK&#39;s <code>DynamicLink<\/code> object. Tolinku uses standard URL paths and query parameters.<\/p>\n\n\n\n<p><strong>Firebase approach<\/strong>:<\/p>\n\n\n\n<pre><code class=\"language-swift\">\/\/ Firebase: data comes from SDK callback\nDynamicLinks.dynamicLinks().handleUniversalLink(url) { dynamicLink, error in\n    guard let link = dynamicLink?.url else { return }\n    \/\/ link = &quot;https:\/\/yourapp.com\/product\/123?ref=abc&quot;\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Tolinku approach<\/strong>:<\/p>\n\n\n\n<pre><code class=\"language-swift\">\/\/ Tolinku: data comes from the URL directly\nfunc handleDeepLink(url: URL) {\n    \/\/ url = &quot;https:\/\/go.yourapp.com\/product\/123?ref=abc&quot;\n    let path = url.path  \/\/ &quot;\/product\/123&quot;\n    let ref = URLComponents(url: url, resolvingAgainstBaseURL: false)?\n        .queryItems?.first(where: { $0.name == &quot;ref&quot; })?.value  \/\/ &quot;abc&quot;\n}\n<\/code><\/pre>\n\n\n\n<p>The Tolinku approach is simpler because it uses standard URL parsing rather than a proprietary SDK data format.<\/p>\n\n\n\n<p>For more on the differences between App Links and Firebase Dynamic Links, see <a href=\"https:\/\/tolinku.com\/blog\/android-app-links-vs-firebase-dynamic-links\/\">Android App Links vs Firebase Dynamic Links<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Handle Existing Firebase Links<\/h2>\n\n\n\n<p>This is the trickiest part. Firebase Dynamic Links that are already in the wild (in sent emails, printed QR codes, social media posts) will stop working after Firebase shuts them down.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Links on Firebase&#39;s Domain<\/h3>\n\n\n\n<p>Links on <code>yourapp.page.link<\/code> will stop resolving once Firebase fully decommissions the service. You can&#39;t redirect them because you don&#39;t control the domain.<\/p>\n\n\n\n<p><strong>Mitigation<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Send updated links in email campaigns to your active users<\/li>\n<li>Update social media profiles and bios<\/li>\n<li>For QR codes on print materials, you&#39;ll need to reprint (this is why custom domains are important)<\/li>\n<li>Accept that some old links will break; focus on high-traffic links first<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Links on Your Custom Domain<\/h3>\n\n\n\n<p>If you used a custom domain with Firebase Dynamic Links, you CAN redirect by updating DNS:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Lower DNS TTL to 60 seconds<\/li>\n<li>Create matching routes in Tolinku for all existing link paths<\/li>\n<li>Update the DNS CNAME to point to Tolinku<\/li>\n<li>Verify all routes work<\/li>\n<li>Raise TTL back to normal<\/li>\n<\/ol>\n\n\n\n<p>This is seamless if you&#39;ve recreated all the active link paths.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Programmatically Created Links<\/h3>\n\n\n\n<p>Links created via the Firebase Dynamic Links API or SDK had a specific URL format. If your app creates sharing links, update the link creation code to use Tolinku&#39;s API instead.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Verify and Monitor<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Testing Checklist<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Universal Links open the app on iOS (from Messages, Notes, Safari long-press)<\/li>\n<li>App Links open the app on Android (from Chrome, messaging apps)<\/li>\n<li>Deferred deep linking works for new installs<\/li>\n<li>Web fallback works for users without the app<\/li>\n<li>OG previews render correctly on social media<\/li>\n<li>Analytics show clicks and conversions in Tolinku dashboard<\/li>\n<li>All existing link paths resolve to the correct screens<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Post-Migration Monitoring<\/h3>\n\n\n\n<p>For the first 2 weeks after migration:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Monitor <a href=\"https:\/\/tolinku.com\/features\/analytics\">analytics<\/a> for any drop in deep link clicks or conversions<\/li>\n<li>Check for user reports of broken links<\/li>\n<li>Watch app reviews for deep-link-related complaints<\/li>\n<li>Compare pre and post-migration conversion rates<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Timeline<\/h2>\n\n\n\n<p>Firebase Dynamic Links migrations are typically faster than Branch migrations because FDL&#39;s feature set is smaller:<\/p>\n\n\n\n<p><strong>Day 1<\/strong>: Audit links, set up Tolinku Appspace, create routes\n<strong>Day 2-3<\/strong>: Replace SDK, update deep link handling code\n<strong>Day 4<\/strong>: Testing across devices and scenarios\n<strong>Day 5<\/strong>: DNS cutover (if using custom domain), begin using Tolinku links for new campaigns\n<strong>Day 5-14<\/strong>: Monitor and fix any issues<\/p>\n\n\n\n<p>For the general migration guide, see <a href=\"https:\/\/tolinku.com\/blog\/migrating-to-tolinku\/\">Migrating to Tolinku from Branch, Firebase, and AppsFlyer<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Migrate from Firebase Dynamic Links before full shutdown. Step-by-step guide to moving deep links, updating SDKs, and preserving existing links.<\/p>\n","protected":false},"author":2,"featured_media":847,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Firebase Dynamic Links Migration Guide","rank_math_description":"Migrate from Firebase Dynamic Links before full shutdown. Step-by-step guide to moving deep links, updating SDKs, and preserving existing links.","rank_math_focus_keyword":"Firebase Dynamic Links migration","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-migrate-from-firebase-dynamic-links.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-migrate-from-firebase-dynamic-links.png","footnotes":""},"categories":[17],"tags":[25,20,54,124,24,52,30],"class_list":["post-848","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-comparisons","tag-android","tag-deep-linking","tag-firebase","tag-google","tag-ios","tag-migration","tag-sdks"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=848"}],"version-history":[{"count":3,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/848\/revisions"}],"predecessor-version":[{"id":2509,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/848\/revisions\/2509"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/847"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}