ConfusedNoob
ConfusedNoob

Reputation: 10186

Redirect to application if installed, otherwise to App Store

I know it's possible to link directly to an app in iOS by registering a custom scheme (e.g. so://) and it's also possible to link to the app in the appstore via itunes.

In many cases, the ideal flow is to provide a link that redirects to the app if it's installed and to the store if not. Is this possible, and if so, how?

Added for clarity, the scenario is I'm opening a link (http) from an e-mail on my iphone that's inviting me to join a group in an application. If the user has the app installed on that device it should open, otherwise the http link should redirect to itunes.

Upvotes: 83

Views: 120444

Answers (9)

uzai sindiko
uzai sindiko

Reputation: 649

Solution: Redirecting to an App or App Store Based on Installation

you can implement a redirect that opens the app if installed, or navigates to the App Store if it's not. This can be achieved using a HTML page with JavaScript.

Here’s how the solution works:

  • Custom URL Scheme: The application should register a custom URL scheme (e.g., instagram://). When the link is clicked, the browser attempts to open this scheme. If the app is installed, it will launch; if not, the browser will not be able to find the app.

  • App Store and Play Store URLs: In addition to the custom URL, provide fallback URLs to the App Store and Play Store. This ensures that users can be directed to the app's download page if the app is not installed.

  • User Agent Detection: The script detects the user’s operating system (iOS or Android) using the user agent string. This is important because it determines which store link to use for redirection.

  • Loading Spinner: To enhance user experience, a loading spinner is displayed while the app is being opened. This visual feedback helps users understand that a process is ongoing.

  • Timeout Handling: A timeout is set to redirect users to the App Store or Play Store after a short delay (1.5 seconds). This delay allows time for the app to launch. If the user switches focus away from the window (indicating they may be using the app), the redirect timeout is cleared to avoid unnecessary navigation.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <title>Redirect</title>
    <style>
      .spinner {
        display: none;
        position: fixed;
        z-index: 999;
        top: 20%;
        left: 50%;
        width: 50px;
        height: 50px;
        margin-left: -25px;
        border: 8px solid rgba(0, 0, 0, 0.1);
        border-left-color: #0096ff;
        border-radius: 50%;
        animation: spin 1s linear infinite;
      }

      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }
        100% {
          transform: rotate(360deg);
        }
      }
    </style>
    <script>
      document.addEventListener("DOMContentLoaded", function () {
        var appUrl = "instagram://user";
        var appStoreUrl = "https://apps.apple.com/app/instagram/id389801252";
        var playStoreUrl = "https://play.google.com/store/apps/details?id=com.instagram.android";

        var isAndroid = /android/i.test(navigator.userAgent);
        var isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
        var timeout = 1500;
        var redirectTimeout;

        document.getElementById("spinner").style.display = "block";

        function redirectToStore() {
          var redirectUrl = isIOS ? appStoreUrl : playStoreUrl;
          window.location = redirectUrl;
          document.getElementById("spinner").style.display = "none";
        }

        function resetRedirectTimeout() {
          clearTimeout(redirectTimeout);
          redirectTimeout = setTimeout(redirectToStore, timeout);
        }

        window.location = appUrl;

        window.onblur = function () {
          clearTimeout(redirectTimeout);
        };

        window.onfocus = function () {
          resetRedirectTimeout();
        };
      });
    </script>
  </head>
  <body>
    <div id="spinner" class="spinner"></div>
  </body>
</html>

Explanation of the Code HTML Structure: The code begins with a standard HTML5 document structure, including a loading spinner styled with CSS.

JavaScript Functionality: The JavaScript code is executed when the DOM is fully loaded. It defines the app's URL scheme, the App Store URL, and the Play Store URL. It also handles user agent detection and manages the redirection process.

Timeout Mechanism: The script includes a timeout that allows a delay for the app to launch before redirecting to the store, providing a smooth experience for the user.

Upvotes: 0

Lata Tiwari
Lata Tiwari

Reputation: 51

If someone is still stuck in this issue and needs easiest solution, you will love node-deeplink

1.) If app is installed: Calling an app through deep linking will always call componentDidMount of root component. So you can attach a listener there. Like:

Linking.getInitialURL()
      .then(url => {
        if (url) {
          this.handleOpenURL({ url });
        }
      })
      .catch(console.error);

    Linking.addEventListener('url', this.handleOpenURL);



handleOpenURL(event) {
    if (event) {
      console.log('event = ', event);
      const url = event.url;
      const route = url.replace(/.*?:\/\//g, '');
      console.log('route = ', route);
      if(route.match(/\/([^\/]+)\/?$/)) {
        const id = route.match(/\/([^\/]+)\/?$/)[1];
        const routeName = route.split('/')[0];

        if (routeName === 'privatealbum') {
          Actions.privateAlbum({ albumId: id });
        }
      }
    }
  }

2.) If app is not installed: Just set up a route in your server and node-deeplink package will handle the bridging between web browser to app store when a app is not installed in your mobile.

By this, both the cases will be handled without any struggle

Upvotes: 2

Confused Vorlon
Confused Vorlon

Reputation: 10426

There are a bunch of complicated edge cases here, so the easiest solution is to let someone else handle that stuff.

This is what https://branch.io/ do. You can use their free plan to achieve exactly what you want, with a handful of bonus features

  • statistics
  • you can pass info along with the link, and it will be retrieved even if the user had to do an install first
  • link will work on the desktop (by default, it will text an install link to your mobile)

I'm not affiliated with Branch.io, but I do use their product.

Upvotes: 2

AFTAB MUHAMMED KHAN
AFTAB MUHAMMED KHAN

Reputation: 2186

There are few simple steps to achieve this Action

Step 1

Go -> Project (select target) -> info -> URL Types

enter image description here

Create URL Scheme in Xcode Like this

enter image description here here URL Scheme is myApp (it is better to have all character in lowercase).

Step 2

Setup Delegate if you have plan to receive parameters/Query strings from URL

Here is the code :

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {

     NSLog(@"APP : simple action %@",url.scheme);

    if ([url.scheme hasPrefix:@"myapp"]) {

        NSLog(@"APP inside simple %@",url.absoluteString);


        NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url
                                                    resolvingAgainstBaseURL:NO];
        NSArray *queryItems = urlComponents.queryItems;
        NSString * abc = [self valueForKey:@"abc"
                           fromQueryItems:queryItems];
        NSString * xyz = [self valueForKey:@"xyz"
                           fromQueryItems:queryItems];


        NSLog(@"Sid up = %@", abc);

        NSLog(@"PID up = %@", xyz);

      // you can do anything you want to do here



        return YES;
    }
return NO;
}

End of Xcode side Work.

Step 3

Referring @BananaNeil Code here as i am not Front end guy

(function() {
  var app = {
    launchApp: function() {
      window.location.replace("myApp://share?abc=12&xyz=123");
      this.timer = setTimeout(this.openWebApp, 1000);
    },

    openWebApp: function() {
      window.location.replace("http://itunesstorelink/");
    }
  };

  app.launchApp();
})();

Hope it will HELP you all

Upvotes: 5

Cerniuk
Cerniuk

Reputation: 15170

"Smart App Banners" - not sure when they showed up but after finding this post looking for same, then Smart App Banners, this is follow up.

Smart App Banners are a single line html meta tag in the header of each page you want to offer your app over the web experience :

<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">

which shows that icon at the top of the page and "Open this page in" with either the app or routing to the App Store.

enter image description here

The metadata for this page on the iPhone looks like this (anonymized of course):

<meta name="apple-itunes-app" content="app-id=605841731, app-argument=lync://confjoin?url=https://meet.rtc.yourcorporatedomain.com/firstName.lastName/conferenceID">

Apple Developer Documentation - Promoting Apps with Smart App Banners

Upvotes: 16

q0rban
q0rban

Reputation: 987

If you have a web page you link to from the email with the web page containing an iframe with the src set to the custom scheme for your App, iOS will automatically redirect to that location in the App. If the app is not installed, nothing will happen. This allows you to deep link into the App if it is installed, or redirect to the App Store if it is not installed.

For example, if you have the twitter app installed, and navigate to a webpage containing the following markup, you would be immediately directed to the app. If you did not have the Twitter app installed, you would see the text "The Twitter App is not installed."

<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    </head>
    <body>
        <iframe src="twitter://" width="0" height="0"></iframe>
        <p>The Twitter App is not installed</p>
    </body>
</html>

Here is a more thorough example that redirects to the App store if the App is not installed:

<!DOCTYPE html>
<html>
    <head>
    <title>iOS Automatic Deep Linking</title>
    <script src='//code.jquery.com/jquery-1.11.2.min.js'></script>
    <script src='//mobileesp.googlecode.com/svn/JavaScript/mdetect.js'></script>
    <script>
      (function ($, MobileEsp) {
        // On document ready, redirect to the App on the App store.
        $(function () {
          if (typeof MobileEsp.DetectIos !== 'undefined' && MobileEsp.DetectIos()) {
            // Add an iframe to twitter://, and then an iframe for the app store
            // link. If the first fails to redirect to the Twitter app, the
            // second will redirect to the app on the App Store. We use jQuery
            // to add this after the document is fully loaded, so if the user
            // comes back to the browser, they see the content they expect.
            $('body').append('<iframe class="twitter-detect" src="twitter://" />')
              .append('<iframe class="twitter-detect" src="itms-apps://itunes.com/apps/twitter" />');
          }
        });
      })(jQuery, MobileEsp);
    </script>
    <style type="text/css">
      .twitter-detect {
        display: none;
      }
    </style>
    </head>
    <body>
    <p>Website content.</p>
    </body>
</html>

Upvotes: 16

BananaNeil
BananaNeil

Reputation: 10762

I think the more simple answer would be to set up a page on your server with the following javascript:

(function() {
  var app = {
    launchApp: function() {
      window.location.replace("myapp://");
      this.timer = setTimeout(this.openWebApp, 1000);
    },

    openWebApp: function() {
      window.location.replace("http://itunesstorelink/");
    }
  };

  app.launchApp();
})();

This basically attempts to redirect to your app and sets a timeout to redirect to the app store if it fails.

You could even make the code a little more smart, and check the user agent to see if they are an ios user, an android user, or a webuser, and then redirect them appropriately.

Upvotes: 72

Lefteris
Lefteris

Reputation: 14667

There is no way to check for this. However, there is a nice workaround.

The idea is basically this:

  1. The first time you open your app, you open up mobile safari from within your app to a predefined URL on your server
  2. On that URL you set up a cookie, like appInstalled to the users mobile safari
  3. You then kick the user back to your app with your registered scheme (same as FB does with SSO)
  4. All your email links point to your website, but on the website you check if the browser is mobile Safari and if the appInstalled cookie exists
  5. If either the browser is not mobile Safari or the cookie is not found, you redirect to the AppStore, or stay in your webpage.
  6. If the conditions of #4 are true, you redirect the user to your app with the registered scheme
  7. If the app has been deleted by the user, so the custom url scheme fails, you have a fail-safe redirect to the appstore

The 2 last steps are explained on this SO post

Upvotes: 35

rooster117
rooster117

Reputation: 5552

Yeah its pretty easy. This requires the app you want to open to have a url scheme declared in the plist:

//if you can open your app
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"yourapp://"]])
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"yourapp://"]];
}
else
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"ituneappstorelink"]];
}

Upvotes: 10

Related Questions