Is it possible to register a http+domain-based URL Scheme for iPhone apps, like YouTube and Maps?

Solution 1:

I think the least intrusive way of doing this is as follows:

  1. Check if the user-agent is that of an iPhone/iPod Touch
  2. Check for an appInstalled cookie
  3. If the cookie exists and is set to true, set window.location to your-uri:// (or do the redirect server side)
  4. If the cookie doesn't exist, open a "Did you know Your Site Name has an iPhone application?" modal with a "Yep, I've already got it", "Nope, but I'd love to try it", and "Leave me alone" button.
    1. The "Yep" button sets the cookie to true and redirects to your-uri://
    2. The "Nope" button redirects to "http://itunes.com/apps/yourappname" which will open the App Store on the device
    3. The "Leave me alone" button sets the cookie to false and closes the modal

The other option I've played with but found a little clunky was to do the following in Javascript:

setTimeout(function() {
  window.location = "http://itunes.com/apps/yourappname";
}, 25);

// If "custom-uri://" is registered the app will launch immediately and your
// timer won't fire. If it's not set, you'll get an ugly "Cannot Open Page"
// dialogue prior to the App Store application launching
window.location = "custom-uri://";

Solution 2:

It's quite possible to do this in JavaScript as long as your fallback is another applink. Building on Nathan's suggestion:

<html>
  <head>
    <meta name="viewport" content="width=device-width" />
  </head>
  <body>

    <h2><a id="applink1" href="fb://profile/116201417">open facebook with fallback to appstore</a></h2>
    <h2><a id="applink2" href="unknown://nowhere">open unknown with fallback to appstore</a></h2>
    <p><i>Only works on iPhone!</i></p>    

  <script type="text/javascript">

// To avoid the "protocol not supported" alert, fail must open another app.
var appstorefail = "itms://itunes.apple.com/us/app/facebook/id284882215?mt=8&uo=6";

function applink(fail){
    return function(){
        var clickedAt = +new Date;
        // During tests on 3g/3gs this timeout fires immediately if less than 500ms.
        setTimeout(function(){
            // To avoid failing on return to MobileSafari, ensure freshness!
            if (+new Date - clickedAt < 2000){
                window.location = fail;
            }
        }, 500);    
    };
}

document.getElementById("applink1").onclick = applink(appstorefail);
document.getElementById("applink2").onclick = applink(appstorefail);

</script>
</body>
</html>

Check out a live demo here.

Solution 3:

For iOS 6 devices, there is an option: Promoting Apps with Smart App Banners

Solution 4:

I found that the selected answer works for the browser apps but I was having issues with the code working in non browser apps that implement a UIWebView.

The problem for me was a user on the Twitter app would click a link that would take them to my site through a UIWebView in the Twitter app. Then when they clicked a button from my site Twitter tries to be fancy and only complete the window.location if the site is reachable. So what happens is a UIAlertView pops up saying are you sure you want to continue and then immediately redirects to the App Store without a second popup.

My solution involves iframes. This avoids the UIAlertView being presented allowing for a simple and elegant user experience.

jQuery

var redirect = function (location) {
    $('body').append($('<iframe></iframe>').attr('src', location).css({
        width: 1,
        height: 1,
        position: 'absolute',
        top: 0,
        left: 0
    }));
};

setTimeout(function () {
    redirect('http://itunes.apple.com/app/id');
}, 25);

redirect('custom-uri://');

Javascript

var redirect = function (location) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('src', location);
    iframe.setAttribute('width', '1px');
    iframe.setAttribute('height', '1px');
    iframe.setAttribute('position', 'absolute');
    iframe.setAttribute('top', '0');
    iframe.setAttribute('left', '0');
    document.documentElement.appendChild(iframe);
    iframe.parentNode.removeChild(iframe);
    iframe = null;
};

setTimeout(function () {
    redirect('http://itunes.apple.com/app/id');
}, 25);

redirect('custom-uri://');

EDIT:

Add position absolute to the iframe so when inserted there isn't a random bit of whitespace at the bottom of the page.

Also it's important to note that I have not found a need for this approach with Android. Using window.location.href should work fine.