Firebase Dynamic Links in iOS iOS 01.07.2020

Dynamic Link is a deep-linking platform of firebase for the developers to share any content or your application with others by creating a short link.

Dynamic link follow the basic pattern when someone tapped on a link:

  1. If the application installed in the mobile it will redirect to the Application.
  2. If the application is not installed in the mobile then it will redirect to the description web page from where you can open the application on the App Store/Play store.
  3. If you open the application on desktop or laptop then it will redirect to the respective website that we will mention while creating the dynamic link.

Open the Firebase console of the firebase and make a project if you don’t have any and do not forget to add App Store ID and Team ID in the project settings. This is essential to let your dynamic link know which App Store page will be opened when it is interacted on an iPhone where your app is not installed.. then open the project and redirect to the Dynamic Link section where you can see the get started view.

Press the get started button and then a popup appears where you can write the domain name of the prefix make sure that your prefix should be unique and relevant to the application.

Now its time to create a dynamic link under the prefix we just created.

Create dynamic link manually

If you have a static dynamic link that you don’t want to edit before sharing the link so its good practice to make it manually e.g you want to share your application. We can create the dynamic link manually from console but when we create a dynamic link from console it can’t be editable but only properties of it.

Create dynamic link programatically

You can use this approach to share some dynamic content of your application.

First we will install pod to access the dynamic link features. Open Podfile and add following.

pod 'Firebase/DynamicLinks'

Open AppDelegate in your project and in method didFinishLaunchingWithOptions write

FirebaseApp.configure()

The dynamic link is an embedded link with a URL and query parameters that are used for redirection. First, we will create URLComponents, dynamic link use this link for redirection when it opens in a browser.

guard let sharelink = URL(string: "https://en.proft.me/?itemId=id10") else { return }

Next, we create a DynamicLinkComponents this is a long shareable link. It took two params:

  1. URL (an embedded link)
  2. Dynamic link prefix (created in the Firebase Console).
guard let dynLink = DynamicLinkComponents.init(link: newSharelink, domainURIPrefix: "https://sdelka.page.link") else { return }

Now we will add iOS and Android parameters to the created dynamic link.

let options = DynamicLinkComponentsOptions()
options.pathLength = .short
dynLink.options = options

if let bundleID = Bundle.main.bundleIdentifier {
    dynLink.iOSParameters = DynamicLinkIOSParameters(bundleID: bundleID)
    dynLink.iOSParameters!.appStoreID = "1234567890"
    dynLink.androidParameters = DynamicLinkAndroidParameters(packageName: bundleID)
}

You can also add social tags to the dynamic link like if you want to add any promotion.

dynLink.socialMetaTagParameters = DynamicLinkSocialMetaTagParameters()
dynLink.socialMetaTagParameters?.title = "Title Of Promotion"
dynLink.socialMetaTagParameters?.descriptionText = "Description Of Promotion"
dynLink.socialMetaTagParameters?.imageURL = URL(string: "ImageURL")

Now we will shorten that URL to share it.

//guard let longDynLink = dynLink.url else { return }
dynLink.shorten() { [weak self] url, warnings, error in
    if let error = error {
        Logger.e(error.localizedDescription)
        return
    }
    let shortUrl = url?.absoluteString ?? ""
    Logger.d("The short URL is: \(shortUrl)")
}

Receive dynamic link

First, we will enable Associated Domain capability in identifiers. For that follow these steps:

  1. Login in Apple Developer Account.
  2. Goto Certificates, Identifiers & Profiles.
  3. Select Identifiers.
  4. Open the identifier of your application.
  5. Mark the Associated Domains.
  6. Then save it.

Before you can handle custom URL schemes in your app, you must register the URL schemes you want to support in your Info.plist file. Registering your URL scheme helps iOS determine what app it should ask to open a deeplink.

  1. Open Project and select target then go to Signing & Capabilities.
  2. Add capability Associated Domains.
  3. Now add Domain like this applinks:myapp.page.link

When your app is asked to handle this deeplink, the scene(_:openURLContexts:) method is called on your scene delegate. If you're using the older app delegate rather than a scene delegate, the application(_:open:options:) method would be called on your app delegate object.

func navigateToItem(_ id: Int) {
    guard let tabBarController = window?.rootViewController as? UITabBarController else {
        return
    }

    guard let viewControllers = tabBarController.viewControllers,
    let listIndex = viewControllers.firstIndex(where: { $0 is ListNavigationController }),
    let listViewController = viewControllers[listIndex] as? ListNavigationController else { return }

    listViewController.popToRootViewController(animated: false)
    tabBarController.selectedIndex = listIndex

    let detailViewController = ListDetailViewController(item: id)
    listViewController.pushViewController(detailViewController, animated: true)
}

func handleURL(_ url: URL) {
    let strLink = url["link"] ?? ""
    guard let urlLink = URL(string: strLink) else { return }
    let itemId = urlLink["itemId"] ?? ""
    //navigateToItem(itemId)
    print("handleURL \(url) - \(itemId)")
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let urlToOpen = URLContexts.first?.url else { return }

    handleURL(urlToOpen)
}

When the system decides that your app should open a link, it calls scene(_:continue:) on your scene delegate, or application(_:continue:restorationHandler:) on the app delegate. This method receives an instance of NSUserActivity with NSUserActivityTypeBrowsingWeb set as its activityType, and the URL that needs to be opened as the webpageURL of the user activity. The following shows how you could extract the target URL from a user activity:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
        let urlToOpen = userActivity.webpageURL else {
            return
    }

    handleURL(urlToOpen)
}

Following is a useful extension for URL.

extension URL {
    subscript(queryParam:String) -> String? {
        guard let url = URLComponents(string: self.absoluteString) else { return nil }
        return url.queryItems?.first(where: { $0.name == queryParam })?.value
    }
}