How To Automatically Open Your App From Instagram Stories Using Universal Link and URL Scheme

Cem Nisan
6 min readFeb 3, 2024

--

Hello everyone,

In Today’s article, I will explain how to automatically open your app with “Universal Link” and “URL Scheme” using Swift and JavaScript if users have installed your app, and how to redirect them to your Website or App Store if they haven’t installed yet.

Problem

In my current project, we were facing an issue that users couldn’t open our app automatically when they clicked our link on Instagram stories, even though we had successfully integrated “Universal Link” and meta tags provided by Meta for “App Links”. We’ve already knew that we had successfully configured “Universal Link” because we could redirect users to our app from “another App to our App, for example, from Notes app to our App” or “When users clicked our link on a website, we could automatically redirect them to our app.” In the scenario “From Instagram Stories to our app”, we realized that we couldn’t automatically redirect them to our app using “Universal Link” or we missed something, so we fixed it with “URL Scheme”, which I’ll explain it below. 😅

Solution

Some companies had already fixed this problem and when we analyzed their “Deep Linking” flow, we noticed that they are using “URL Scheme”. But how? Because when you try to share your “URL Scheme” in an Instagram story, Instagram shows an error saying “It’s not a valid url, please enter a valid url”. Then we realized once again that they’re using both “Universal Link” and “URL Scheme” simultaneously. In this case, we’ve thought, “why our users don’t share an Instagram story with our link, where we have successfully integrated “Universal Link”, and why don’t we replace that link with our “URL Scheme” when user is coming from Instagram, allowing our app to open automatically?” and it worked.

Scenario

When users want to share something from our app, we’ll provide them a valid url containing the “apple-app-site-assosication” file hosted on our Website. Users will then be able to share this valid URL in their Instagram stories. When another users click this link, such as “https://myapp.com/profile/cameron”, users will be redirected to the relevant page, and then we’ll check as follows: “Are users’ device Mobile? and are they coming from Instagram referral?” If these conditions are true, along with the JavaScript code we’ll write, we’ll replace our “https://myapp.com/profile/cameron” URL with “myapp://profile/cameron” and If the users have installed our application, it will automatically open. If not, we’ll redirect them to our Website or Apple Store.

Not: Topics such as what is “Universal Link” and “URL Scheme” and what are the differences between them will not be covered in this article. You can get information from this excellent article:
https://medium.com/wolox/ios-deep-linking-url-scheme-vs-universal-links-50abd3802f97

iOS

We can list the things what we need to do on the Application side:

1.Determine the “URL Scheme”

In this section, we have to create a URL Type from “Targets” and its “Info” section. This URL type must have a unique name.

URL Type Creation

2. Adding “Associated Domains”

From the “Signing And Capabilities” section, we have to add a new “Capability”. This our new “Capability” will be “Assoicated Domains” as mentioned below.

Adding Associated Domain

Once “Associated Domains” capability is added, we need to add a new domain, which should start “applinks://” and then include your custom domain.

An Example Of A New Associated Domain

3. Creating of our “apple-app-site-assocation” json file for “Universal Link” as suggested by Apple. Here is an example:

{
"applinks": {
"apps": [],
"details": {
"YourAppID.com.yourAppName": {
"paths": [
"/profile/*",
"..."
]
}
}
}
}

4. When users are redirected to our application by “URL Scheme”, we’ll handle this incoming URL in our App Delegate or Scene Delegate class.

  • App Delegate
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:] ) -> Bool {
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
let paths = components.path,
let params = components.queryItems else {
print("Invalid URL or paths missing")
return false
}
/* ... */
}
  • Scene Delegate
func scene(_ scene: UIScene, 
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let urlContext = connectionOptions.urlContexts.first {
let sendingAppID = urlContext.options.sourceApplication
let url = urlContext.url
guard let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
let paths = components.path,
let params = components.queryItems else {
print("Invalid URL or paths missing")
}
/* ... */
}
/* ... */
}

5. When users are redirected to our application by “Universal Link”, we’ll handle this incoming URL in our App Delegate or Scene Delegate class.

  • App Delegate
func application(_ application: NSApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool
{
// Get URL components from the incoming user activity.
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
return false
}

guard let path = components.path,
let params = components.queryItems else {
return false
}
/* ... */
}
  • Scene Delegate
func scene(_ scene: UIScene, willConnectTo
session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let userActivity = connectionOptions.userActivities.first,
userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true) else {
return
}

guard let path = components.path,
let params = components.queryItems else {
return
}
/* ... */
}

JavaScript

I’ll create a “Node.js” project and add “Express.js” framework to run a server. We will then do DeepLink routing as mentioned below:

  1. Creating A New Node.js App and Adding Express.js
$ mkdir myapp
$ cd myapp
$ npm init
$ npm install express

Not: If you haven’t installed Node.js on your computer yet, you can download it from this link: https://nodejs.org/en

2. Running Our Application and Adding Our “apple-app-site-association” Json File

Folder Structure

With these codes that we wrote in “app.js” file, we created our server and added our “apple-app-site-association” json file to the “.well-known/” folder.

const express = require('express')
const app = express()
const port = 3000

app.get('/.well-known/apple-app-site-association', function(req, res) {
res.sendFile(__dirname + '/.well-known/apple-app-site-association');
});

app.get('/apple-app-site-association', function(req, res) {
res.sendFile(__dirname + '/.well-known/apple-app-site-association');
});

app.get('/profile/cameron', function(req, res) {
res.sendFile(__dirname + '/index.html')
}); // it's jus an example of profile scenario ^

app.listen(port, () => {
console.log(`Example app listening on port ${ port }`)
})

3. Creating “index.html” file

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<script>
window.onload = function () {
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (isMobile) {
const isUserComingFromInstagramReferral = document.referrer.includes("instagram");
if (isUserComingFromInstagramReferral) {
const url = window.location.href.replace("https://your-domain", "your-app-scheme://")
window.location = url;

setTimeout(function () {
// wait a second and then to go App Store or your Website
// if the user hasn't installed yet.
window.location = "your-web-site-or-app-store-link";
}, 1000);
}
}
}
</script>
</head>

<body>
<p>Hello, World!</p>
<img src="./public/your-app-icon.png" alt="" width="300" height="300"/>
</body>

</html>

In our “index.html” file above, after window is onloaded, we checked if users’ device is mobile or not. If the device is mobile, we checked that if the users are coming from Instagram referral or not. If users are coming from Instagram referral, we replaced our custom domain with our custom “URL Scheme” and we set a timer to check if the users have installed our app. The timer will start after one second, and if users aren’t redirected to our app, it’ll redirect them to our Website or App store.

And that’s it! We can automatically redirect users to our app when they click our link from Instagram Stories 🙌 🙌

Thank you for reading, and if you would like to provide feedback, I will enjoy reading it in the comments section 🙌

--

--