74

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.

jscs
  • 62,161
  • 12
  • 145
  • 186
ConfusedNoob
  • 8,909
  • 14
  • 55
  • 80
  • 1
    I think the ideal solution would mean that you could redirect to an itunes link with an instruction. Something like: https://itunes.apple.com/us/app/clear/id492134154?mt=8&uo=4&open=true where open=true tells the ios app store to open the app... – ConfusedNoob Dec 27 '12 at 01:27

8 Answers8

63

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.

BananaNeil
  • 8,263
  • 6
  • 37
  • 53
  • 12
    iOS throws a rather unfriendly, "Safari cannot open the page because the address is invalid" message if the app is not installed with this method. – Real World Oct 02 '17 at 13:48
  • 3
    @RealWorld That sounds like a new addition to ios 11. These days, for this topic, I would recommend implementing universal linking. It might be worth writing up a new answer to this question outlining how that works. – BananaNeil Oct 02 '17 at 17:31
  • @BananaNeil I created Universal link and uploaded apple-app-site-association but it is not working ? Any idea ? It always opening only website if app already installed in device. – Mitesh Dobareeya Jun 11 '18 at 11:29
  • @MiteshDobareeya I wouldn't be able to help you without more details. If you are viewing your website from your safari of your phone and you've set up universal linking correctly, you should be able to scroll to the very top and see an "open in app" button. If that's there, clicking it will enable your phone to use universal linking for that website. If it's not there, you'll need to double check your implementation. – BananaNeil Jun 11 '18 at 20:23
  • 3
    it used to work but it has stopped working in ios 12 I believe. Or something else is going wrong cause it stopped working suddenly. – Chaudhry Waqas Nov 28 '18 at 19:30
  • 2
    Yes this used to work before IOS 12, now unfortunately it opens an app and link both as well – Jaymin Sep 25 '19 at 10:19
  • Any idea how to deal with the problem that iOS 12+ is opening both the app and link? – ErebosM Nov 25 '19 at 14:16
  • @ErebosM have you received any solution for same. – shikha kochar Feb 28 '20 at 06:18
  • @shikhakochar have you find any solution for this. – Yogendra Patel Jun 09 '20 at 13:23
  • @ErebosM have you find any solution for this. – Yogendra Patel Jun 09 '20 at 13:23
  • @Jaymin have you find any solution for this. – Yogendra Patel Jun 09 '20 at 13:48
29

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

Community
  • 1
  • 1
Lefteris
  • 14,002
  • 2
  • 52
  • 90
15

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>
q0rban
  • 655
  • 7
  • 9
  • For the record, this is what we are doing on Syfy.com. Go to http://www.syfy.com/live to see the site automatically deep link you into the app if you have it installed. – q0rban Jan 21 '15 at 15:30
  • This is the correct answer to the question. Instead of detecting iOS in the page itself, I check the user-agent header in the get request and serve the redirect page or a page with the request to the user to open the link in an iOS device. Out of curiosity, how did you know iframe would behave this way? Couldn't find this in the iframe html documentation. – Carlos Guzman Jun 19 '15 at 15:18
  • 1
    Thanks @CarlosGuzman! I didn't know that it would work this way, I just kept trying different things until it worked! :) – q0rban Jun 30 '15 at 15:08
  • Well, that was a great find then! Unfortunately, this no longer seems to work in iOS 8. Do you find that it still works for you in iOS 8 and later? Seems to be related to Apple blocking apple store automatic redirection. – Carlos Guzman Jul 01 '15 at 18:57
  • 1
    Downvoted for downlading code directly from SVN repository. Repo owner can push crypto miner to the repo anytime. – sesm Apr 04 '18 at 15:41
12

"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

Cerniuk
  • 11,544
  • 1
  • 25
  • 26
8

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"]];
}
rooster117
  • 5,432
  • 1
  • 18
  • 19
  • Sorry, my scenario perhaps wasn't clear - this assumes I'm opening from another app. In this case it would be from an e-mail or SMS via a http web link - so the remote Web Server would need to redirect to appropriate link. – ConfusedNoob Dec 27 '12 at 01:25
  • You may have to link to a web page which attempts to open the app in the same way through Javascript and if it doesn't open it then redirects to the iTunes link. I don't have source for that but it can work. – rooster117 Dec 27 '12 at 01:27
3

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

AFTAB MUHAMMED KHAN
  • 2,673
  • 3
  • 13
  • 24
2

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.

Confused Vorlon
  • 7,561
  • 1
  • 36
  • 40
1

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