This migration guide focuses on using
[App Links](https://developer.android.com/training/app-links) and
[Universal Links](https://developer.apple.com/ios/universal-links/),
optionally using Firebase Hosting to host your app-site association files.

This migration replaces the following Firebase Dynamic Links features:

| Feature | Firebase Dynamic Links | App Links / Universal Links |
|---|---|---|
| Route users to the correct store for their device from a single link click | Yes | No^★^ |
| Provide users with a continuation of journey after downloading and installing your app using a deferred deep link | Yes | No^★^ |
| Provide users with a contextual experience using deep-linked content in your app (when already installed) | Yes | Yes |
| Provide analytics data related to dynamic link click events | Yes | No |
| Provide the ability to create short link URLs | Yes | No |

**Note** : [Smart App Banners on iOS](https://developer.apple.com/documentation/webkit/promoting_apps_with_smart_app_banners) provide an alternative means
to display a clickable banner that routes users to the App Store if your app
isn't installed, or into your app if it is installed already.

Smart App Banners also provide the ability to pass in parameters after a
user clicks on your Smart App Banner link, potentially providing a way to
give users a continuation of their user journey when navigating to your app
from clicking on the Smart App Banner.

If you continue to need other Firebase Dynamic Link features for your migration
that aren't supported in this guide, see other migration scenarios in the
[Dynamic Links Deprecation FAQ](https://firebase.google.com/support/dynamic-links-faq.md.txt#how_should_i_migrate_from_the_service)
documentation.

Suppose you have a Firebase Dynamic Link that looks like this:

| Dynamic Link Example ||
|---|---|
| Link name | Welcome to Example.com |
| Deep link | `https://example.web.app/welcome` |
| Android app | `com.example.android` |
| Apple app | `com.example.ios` |
| Long Dynamic Link | `https://example.page.link/?link=https://example.web.app/welcome&apn=com.example.android&isi=123456789&ibi=com.example.iuos` |
| Short Dynamic Link | `https://example.page.link/m9Mm` |

The goal of this migration guide is to replace Firebase Dynamic Links like this:

`https://example.page.link/m9Mm`

With App Link / Universal Link deep links that look like this:

`https://your-project-domain.web.app/welcome`

Note that the App Link / Universal Link deep link will provide the
following to your users:

- A deep link they can click that will open your app when already installed
- A continuation of their user journey navigating them to a specific part of your app when it is opened

However, the App Link / Universal Link deep link will not provide the following
behaviors for your users (which Firebase Dynamic Links previously did):

- Navigating users to the correct store for their device to download and install your app
- Providing a continuation of their user journey after downloading, installing and opening the app for the first time

Note the differences in behavior and functionality of these App
Links / Universal Links compared to Firebase Dynamic Links called out
in the table above.

## Before you begin

Firebase Dynamic Links utilizes App Links (on Android) and Universal Links (on
iOS) in its own underlying implementation in order to provide deep-linking
functionality after your app is already installed.

This guide walks through how to create your own App Links and Universal Links
using Firebase Hosting to replace that part of the functionality provided by
Firebase Dynamic Links while migrating your Firebase Dynamic Links to the new
App Links / Universal Links migration solution.

You'll need the following pieces of information in order to complete your
migration:

- The Firebase Dynamic Links you intend to migrate
- The deep-link URL parameters included in your dynamic links
- The domain you plan to use to replace your previous Firebase Dynamic Links domain (if applicable)

You can use the [Export Dynamic Links Metadata guide](https://firebase.google.com/support/guides/export-dynamic-links.md.txt)
to export your existing link metadata and
obtain the information listed above.

## Migration steps overview

1. Provision a new domain (if you don't already have one you want to use)
   to host your App Link / Universal Link configuration files using Firebase
   Hosting.

2. Create and host your App Link / Universal Link configuration files on
   your hosting domain.

3. Create new App Links / Universal Links matching the deep-link schema
   used in your Firebase Dynamic Links.

4. Update your Android / iOS apps and application code to receive deep-links.

5. Testing your App Links / Universal Links integrations.

6. Replace your published or shared Firebase Dynamic Links with App Links
   and Universal Links.

The first step
will be common to both the App Links or Universal Link migration flows. The
remainder will vary depending on the platform, so navigate to the section of the
guide below depending on which platform you would like to migrate first.

- [Migration Steps for Android App Links](https://firebase.google.com/support/guides/app-links-universal-links.md.txt#app-links)
- [Migration Steps for Universal Links on iOS](https://firebase.google.com/support/guides/app-links-universal-links.md.txt#universal-links)

## Provision a new domain to host your App Link / Universal Link configuration files using Firebase Hosting

### Choose a domain

The first step is to choose a domain you would like to use for your App Links /
Universal Links. This will be the domain that will be used for the new links
that you will share out to your users.

If you use
[Firebase Hosting](https://firebase.google.com/docs/hosting.md.txt),
project subdomains with the format `your-project-domain.web.app` or
`your-project-domain.firebaseapp.com` are automatically provisioned at no cost. You
can optionally use a custom domain with or without Firebase Hosting to host your
App Link / Universal Link configuration files as well.

### Set up Firebase Hosting

Next, you'll need to
[set up and configure your Firebase Hosting instance](https://firebase.google.com/docs/hosting/quickstart.md.txt).

By the time you're done setting up your Firebase Hosting instance, you'll have
a domain similar to `your-project-domain.web.app`\`, or a
[custom domain](https://firebase.google.com/docs/hosting/custom-domain.md.txt)
if you prefer.

## Migration steps for Android App Links

### Create and host your App Link configuration files on your new hosting domain

In order to use App Links, you must host a configuration file that helps
establish a secure association between the domain used in your links and your
app. For App Links, this is the `assetlinks.json` file.

#### Steps to create and host the assetlinks.json file

The `assetlinks.json` file allows us to provide a list of authorized apps that
can handle the contents of the web domain we'll be using for our App Links. The
assetlinks.json file itself needs to be hosted in the root of the web domain
under the path: `/.well-known`.

Follow the steps below to complete this configuration:

1. Create the `.well-known` folder under the public folder in your
   Firebase Hosting root directory.

2. Create a file named `assetlinks.json` under the `.well-known` folder.

3. Copy the following content to your assetlinks.json file, taking note of
   the meaning of each field below:

   ```json
   [{
     "relation": ["delegate_permission/common.handle_all_urls"],
     "target": {
       "namespace": "android_app",
       "package_name": "com.example.android",
       "sha256_cert_fingerprints":
         ["01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF:01:23:45:67:89:AB:CD:EF"]
     }
   }]
   ```
   - `namespace` - refers to the name of the application you want to provide
   - `package_name` - refers to the applicationId declared in the app's `build.gradle` file
   - `sha256_cert_fingerprints` - refers to the SHA256 fingerprint of the keystore file that you use for signing the application.

   You can use the debug.keystore file used by Android Studio to generate a
   sha256_cert_fingerprints record for debugging purposes. You can find the
   file at `/Users/<username>/.android/debug.keystore` on Mac and Linux and
   `C:\Users\<username>\.android\debug.keystore` on Windows.

   From this keystore, you can fetch the SHA256 value using the keytool.

   Refer to
   [this section of the App Links documentation](https://developer.android.com/training/app-links/verify-android-applinks#web-assoc)
   for more instructions on completing this step.

   Alternatively you can also use the
   [App Links Assistant](https://developer.android.com/studio/write/app-link-indexing)
   in Android Studio to generate the assetlinks.json file contents and
   configure your application to handle App Links.
4. Update your firebase.json file to index the file for hosting.

   ```json
   "headers": [
     {
       "source": "/.well-known/assetlinks.json",
       "headers": [
         {
           "key": "Content-Type",
           "value": "application/json"
         }
       ]
     }
   ]
   ```
5. Now that we have the assetlinks.json file in place, run `firebase deploy` to
   host the changes.

   Note you will need to have the [Firebase CLI](https://firebase.google.com/docs/cli.md.txt)
   installed in order to run the above deploy command.

       firebase deploy --only hosting

6. Verify the assetlinks.json file by going to
   `https://your-project-domain.web.app/.well-known/assetlinks.json`

### Create new App Links matching the deep-link schema used in your Firebase Dynamic Links

In this step, you will recreate the deep-links from your Firebase Dynamic Links
using regular deep-link URLs matching the new domain you've created for your App
Links.

So for example, let's say you have the following Firebase Dynamic Link:

| Dynamic Link Example ||
|---|---|
| Link name | Welcome to Example.com |
| Deep link | `https://example.web.app/welcome` |
| Android app | `com.example.android` |
| Apple app | `com.example.ios` |
| Long Dynamic Link | `https://example.page.link/?link=https://example.web.app/welcome&apn=com.example.android&isi=123456789&ibi=com.example.iuos` |
| Short Dynamic Link | `https://example.page.link/m9Mm` |

In this case, you would extract the deep link parameter - i.e.
https://example.web.app/welcome and will now use this as the App Link
parameter for your app.

> [!NOTE]
> **Note:** When you first created your Firebase Dynamic Link, you may have created a deep-link parameter that used a domain that you do not own (e.g. [example.com/welcome](http://example.com/welcome)). Firebase Dynamic Links supported this, however in this migration any deep links you plan to use must be changed to use the domain that you own and that was previously configured with Firebase Hosting. If you already used a domain you own for the deep link URL parameters used in your Firebase Dynamic Links, this may save you a lot of time, and your app may already be configured to handle the incoming App Links that you'll need to create.

You'll want to repeat this process for each Firebase Dynamic Link you wish to
migrate to using App Links / Universal Links, and replicate the deep-linking
schema you used.

For example, please see the following set of Firebase Dynamic Links
short-links, deep link parameters and migrated deep link values:

| **Short link** | **Deep link parameter** | **Migrated deep link** |
|---|---|---|
| yourapp.page.link/welcome | https://example.com/welcome | yourapp.web.app/welcome |
| yourapp.page.link/c7sn | https://example.com/main/?p=23\&t=1 | yourapp.web.app/main/?p=23\&t=1 |
| yourapp.page.link/social | https://example.com/friendinvite/?add=1 | yourapp.web.app/friendinvite/?add=1 |

Next, you'll need to replace any instances of Firebase Dynamic Links that have
been published or shared with the new migrated deep links so users will click on
those App Links instead of the previous Firebase Dynamic Links.

> [!NOTE]
> **Note:** These new links will only work after completing the rest of the instructions in this guide, and after your user has already downloaded and installed your app on their Android device.

### Update your Android app and application code to receive deep links

The next step after selecting a domain, choosing a deep-linking schema and
migrating your Firebase Dynamic Links to App Links is to update your Android app
and application code to receive the new deep links.

We recommend following the full
[App Links documentation here](https://developer.android.com/training/app-links/deep-linking)
or alternatively the
[Android Studio guide](https://developer.android.com/studio/write/app-link-indexing)
on configuring your app to handle deep links, but the main steps include:

1. Identifying which activities should handle the respective deep links
2. Adding an Intent Filter for those activities in your AndroidManifest.xml file
3. Receiving the deep link in your activities' application code

Let's say that you wanted to use your MainActivity to handle some of your deep
links. To do this, you will need to add the following Intent Filter to the
MainActivity in your AndroidManifest.xml file:

```xml
<activity android:name=".MainActivity"
   android:exported="true">
   <intent-filter>
       <action android:name="android.intent.action.MAIN" />
       <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
   <intent-filter android:autoVerify="true">
       <action android:name="android.intent.action.VIEW" />
       <category android:name="android.intent.category.DEFAULT" />
       <category android:name="android.intent.category.BROWSABLE" />
       <data android:host="example.web.app" android:scheme="http"
           android:pathPrefix="/welcome" />
       <data android:host="example.web.app" android:scheme="https"
           android:pathPrefix="/welcome" />
   </intent-filter>
</activity>
```

In this step, you are specifying that the MainActivity is the destination for
handling deep links from the wxample.web.app domain and that includes the
/welcome path prefix. Note that you will also need to specify the
android:autoVerify="true" attribute, which allows you to designate your app as
the default handler for this given type of link.

Finally, you'll need to add the code in your MainActivity to retrieve the
deep-link data and use that to drive the deep link experience in your app. This
is similar to logic you may have already coded in your app when you integrated
with Firebase Dynamic Links.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.main)

  val  data: Uri? = intent?.data

  val toast = Toast.makeText(this, data, duration)
  toast.show()
}
```

### Testing App Links

You can test the App Links you've just created by either running your app on a
physical device or in the
[Android Emulator](https://developer.android.com/studio/run/emulator).

You'll need to create a clickable link using the domain configured for your App
Links and then click on that link to ensure that it opens up into your app and
navigates you to the intended activity.

Alternatively you can also test your App Links integration using the
[App Links Assistant](https://developer.android.com/studio/write/app-link-indexing#testindent)
in Android Studio, or use the following command for an App Link URL you've
configured to ensure it launches the matching activity correctly:

```bash
adb shell am start -a android.intent.action.VIEW -d <your_deep_link_url>
```

### Replace your published or shared Firebase Dynamic Links with App Links

The final step for your migration will be to replace your published or shared
Firebase Dynamic Links with App Links wherever possible, and to continue using
App Links going forward.

Completing this step will vary depending on where and how you have your
Firebase Dynamic Links published, but to help you track which ones exist, you
can export your existing Firebase Dynamic Link metadata. See
the [Export Dynamic Links Metadata guide](https://firebase.google.com/support/guides/export-dynamic-links.md.txt).

## Migration Steps for Universal Links on iOS

> [!NOTE]
> **Note:** If you've already completed migrating to App Links using the previous Migration Steps for App Links on Android section, the instructions here will be very similar except now for Universal Links on iOS.

### Create and host your Universal Links configuration files on your new hosting domain

In order to use Universal Links, you must host a configuration file that helps
establish a secure association between the domain used in your links and your
app. For Universal Links, this is the `apple-app-site-association` file (also
known as AASA file).

#### Steps to create and host the apple-app-site-association file

The AASA file allows us to provide a list of authorized apps that can handle
the contents of the web domain we'll be using for our Universal Links. The AASA
file itself needs to be hosted in the root of the web domain under the path:
/.well-known.

Follow the steps below to complete this configuration:

1. Create the "*.well-known*" folder under the public folder in your
   Firebase Hosting root directory.

2. Create a file named "*apple-app-site-association*" under the
   ".well-known" folder.

3. Copy the following content to your apple-app-site-association file,
   taking note of the meaning of each field below:

   ```json
   {
     "applinks": {
       "apps": [],
       "details": [
         {
           "appID": "$TEAM_ID.com.firebase.UniversalLinks",
           "paths": [
             "NOT /_/*",
             "/*"
           ]
         }
       ]
     }
   }
   ```
   - $TEAM_ID.BundleId - the fully qualified application name authorized to handle the links
4. Update your firebase.json file to index the file for hosting.

   ```json
   "headers": [
     {
       "source": "/.well-known/apple-app-site-association",
       "headers": [
         {
           "key": "Content-Type",
           "value": "application/json"
         }
       ]
     }
   ]
   ```
5. Now that we have the AASA file in place, do firebase deploy to host the
   changes.

6. Verify the AASA file by going to
   https://<var translate="no">your-project-domain</var>.web.app/.well-known/app-app-site-association

### Create new Universal Links matching the deep-link schema used in your Firebase Dynamic Links

In this step, you will recreate the deep-links from your Firebase Dynamic Links
using regular deep-link URLs matching the new domain you've created for your
Universal Links.

So for example, let's say you have the following Firebase Dynamic Link:

| Dynamic Link Example ||
|---|---|
| Link name | Welcome to Example.com |
| Deep link | `https://example.web.app/welcome` |
| Android app | `com.example.android` |
| Apple app | `com.example.ios` |
| Long Dynamic Link | `https://example.page.link/?link=https://example.web.app/welcome&apn=com.example.android&isi=123456789&ibi=com.example.iuos` |
| Short Dynamic Link | `https://example.page.link/m9Mm` |

In this case, you would extract the deep link parameter -
i.e.https://example.web.app/welcome and will now use this as the Universal
Link parameter for your app.

> [!NOTE]
> **Note:** When you first created your Firebase Dynamic Link, you may have created a deep-link parameter that used a domain that you do not own (e.g. [example.com/welcome](http://example.com/welcome)). Firebase Dynamic Links supported this, however in this migration any deep links you plan to use must be changed to use the domain that you own and that was previously configured with Firebase Hosting. If you already used a domain you own for the deep link URL parameters used in your Firebase Dynamic Links, this may save you a lot of time, and your app may already be configured to handle the incoming Universal Links that you'll need to create.

You'll want to repeat this process for each Firebase Dynamic Link you wish to
migrate to using App Links / Universal Links, and replicate the deep-linking
schema you used.

For example, please see the following set of Firebase Dynamic Links
short-links, deep link parameters and migrated deep link values:

| **Short link** | **Deep link parameter** | **Migrated deep link** |
|---|---|---|
| yourapp.page.link/welcome | https://example.com/welcome | yourapp.web.app/welcome |
| yourapp.page.link/c7sn | https://example.com/main/?p=23\&t=1 | yourapp.web.app/main/?p=23\&t=1 |
| yourapp.page.link/social | https://example.com/friendinvite/?add=1 | yourapp.web.app/friendinvite/?add=1 |

Next, you'll need to replace any instances of Firebase Dynamic Links that have
been published or shared with the new migrated deep links so users will click on
those Universal Links instead of the previous Firebase Dynamic Links.

> [!NOTE]
> **Note:** These new links will only work after completing the rest of the instructions in this guide, and after your user has already downloaded and installed your app on their iOS device.

### Update your iOS app and application code to receive deep links

The next step after selecting a domain, choosing a deep-linking schema and
migrating your Firebase Dynamic Links to Universal Links is to update your iOS
app and application code to receive the new deep links.

We recommend following the full
[Universal Links documentation here](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content)
on configuring your app to handle deep links, but the main steps include:

1. Update your project configuration to enable your app to handle deep
   links from your newly created domain

2. Receive the deep link in your application code

In order to update your project configuration to enable your app to handle deep
links, you'll need to add an additional Associated Domain to your project in
xCode for the domain you're now planning to use to host your
apple-app-site-associate file.

This can be done by:

1. Opening Xcode
2. Selecting your project in the file navigator
3. Navigating to the Signing \& Capabilities tab of your project settings
4. Navigate down to the Associated Domains section
5. Clicking on the + button to add the additional domain to your project in the format "applinks:".

Finally, you need to update your application code to be able to receive the
incoming deep links.

To accomplish this, first update the AppDelegate.swift file to respond to a
Universal Link by adding the following code:

```swift
func application(_ application: UIApplication, continue userActivity: NSUserActivity,
                 restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  AppDelegate.showReceivedUrl(userActivity: userActivity);
  return true
}

static func showReceivedUrl(userActivity: NSUserActivity) {
  if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
    let url = userActivity.webpageURL!
    print(url.absoluteString)
}
```

The above code overrides the Universal Link callback method and logs the deep
link URL if present.

Now we will call the same `showReceivedUrl` method from the SceneDelegate class
as well since if the app is already open by the time the user clicked on the
universal link, the universal link callback inside `SceneDelegate` will be the one
which gets invoked.

```swift
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
  AppDelegate.showReceivedUrl(userActivity: userActivity)
}
```

### Testing Universal Links

You can test the Universal Links you've just created by either running your app
on a
[physical device or simulator](https://developer.apple.com/documentation/xcode/running-your-app-in-simulator-or-on-a-device).

You'll need to create a clickable link using the domain configured for your
Universal Links and then click on that link to ensure that it opens up into your
app and navigates you to the intended screen in your app.

### Supporting Smart App Banners

We strongly recommend using
[Smart App Banners](https://developer.apple.com/documentation/webkit/promoting_apps_with_smart_app_banners)
as a way to provide your users with a similar experience to Firebase Dynamic
Links.

Using Smart App Banners, your users will be taken to the App Store for your app
listing if your app isn't already installed on their device. You can also
optionally configure a parameter to pass into your app after it gets downloaded
and installed to provide your users with a continuation of their journey. If
your app is already installed, it will open up passing in the parameter to your
app to help navigate your user to the appropriate content based on the Smart App
Banner that they clicked.

### Replace your published or shared Firebase Dynamic Links with App Links

The final step for your migration will be to replace your published or shared
Firebase Dynamic Links with Universal Links wherever possible, and to continue
using Universal Links going forward.

Completing this step will vary depending on where and how you have your
Firebase Dynamic Links published.

To help you track existing Firebase Dynamic Links to be migrated, we will be
publishing a guide on how to export your short-link meta data from Firebase
Dynamic Links. Please check back on our
[Dynamic Links Deprecation FAQ doc](https://firebase.google.com/support/dynamic-links-faq.md.txt)
for more updates.