How can I check if an app is installed from a web-page on an iPhone
I want to create a web-page, a page that will redirect an iPhone to the App Store if the iPhone does not have the application installed, but if the iPhone has the app installed I want it to open the application.
I have already implemented a custom URL in the iPhone application, so I have a URL for the application that is something like:
myapp://
And if this URL is invalid, I want the page to redirect to the App Store. Is this possible at all?
If I don't have the application installed on the phone and write the myapp:// URL in Safari, all I get is an error message.
Even if there exists an ugly hack with JavaScript, I would really like to know.
Solution 1:
As far as I know you can not, from a browser, check if an app is installed or not.
But you can try redirecting the phone to the app, and if nothing happens redirect the phone to a specified page, like this:
setTimeout(function () { window.location = "https://itunes.apple.com/appdir"; }, 25);
window.location = "appname://";
If the second line of code gives a result then the first row is never executed.
Similar questions:
- iPhone browser: Checking if iPhone app is installed from browser
- Is it possible to register a http+domain-based URL Scheme for iPhone apps, like YouTube and Maps?
Solution 2:
To further the accepted answer, you sometimes need to add extra code to handle people returning to the browser after launching the app - that the setTimeout function will run whenever they do. So, I do something like this:
var now = new Date().valueOf();
setTimeout(function () {
if (new Date().valueOf() - now > 100) return;
window.location = "https://itunes.apple.com/appdir";
}, 25);
window.location = "appname://";
That way, if there has been a freeze in code execution (i.e., app switching), it won't run.
Solution 3:
iOS Safari has a feature that allows you to add a "smart" banner to your webpage that will link either to your app, if it is installed, or to the App Store.
You do this by adding a meta
tag to the page. You can even specify a detailed app URL if you want the app to do something special when it loads.
Details are at Apple's Promoting Apps with Smart App Banners page.
The mechanism has the advantages of being easy and presenting a standardized banner. The downside is that you don't have much control over the look or location. Also, all bets are off if the page is viewed in a browser other than Safari.
Solution 4:
As of 2017, it seems there's no reliable way to detect an app is installed, and the redirection trick won't work everywhere.
For those like me who need to deep-link directly from emails (quite common), it is worth noting the following:
-
Sending emails with appScheme:// won't work fine because the links will be filtered in Gmail
-
Redirecting automatically to appScheme:// is blocked by Chrome: I suspect Chrome requires the redirection to be synchronous to user interaction (like a click)
-
You can now deep link without appScheme:// and it's better but it requires a modern platform and additional setup. Android iOS
It is worth noting that other people already thought about this in-depth. If you look at how Slack implements his "magic link" feature, you can notice that:
- It sends an email with a regular HTTP link (ok with Gmail)
- The web page has a big button that links to appScheme:// (ok with Chrome)
Solution 5:
@Alistair pointed out in this answer that sometimes users will return to the browser after opening the app. A commenter to that answer indicated that the times values used had to be changed depending on iOS version.
When our team had to deal with this, we found that the time values for the initial timeout and telling whether we had returned to the browser had to be tuned, and often didn't work for all users and devices.
Rather than using an arbitrary time difference threshold to determine whether we had returned to the browser, it made sense to detect the "pagehide" and "pageshow" events.
I developed the following web page to help diagnose what was going on. It adds HTML diagnostics as the events unfold, mainly because using techniques like console logging, alerts, or Web Inspector, jsfiddle.net, etc. all had their drawbacks in this work flow. Rather than using a time threshold, the JavaScript counts the number of "pagehide" and "pageshow" events to see whether they have occurred. And I found that the most robust strategy was to use an initial timeout of 1000 (rather than the 25, 50, or 100 reported and suggested by others).
This can be served on a local server, e.g. python -m SimpleHTTPServer
and viewed on iOS Safari.
To play with it, press either the "Open an installed app" or "App not installed" links. These links should cause respectively the Maps app or the App Store to open. You can then return to Safari to see the sequence and timing of the events.
(Note: this will work for Safari only. For other browsers (like Chrome) you'd have to install handlers for the pagehide/show-equivalent events).
Update: As @Mikko has pointed out in the comments, the pageshow/pagehide events we are using are apparently no longer supported in iOS8.
<html>
<head>
</head>
<body>
<a href="maps://" onclick="clickHandler()">Open an installed app</a>
<br/><br/>
<a href="xmapsx://" onclick="clickHandler()">App not installed</a>
<br/>
<script>
var hideShowCount = 0 ;
window.addEventListener("pagehide", function() {
hideShowCount++;
showEventTime('pagehide');
});
window.addEventListener("pageshow", function() {
hideShowCount++;
showEventTime('pageshow');
});
function clickHandler(){
var hideShowCountAtClick = hideShowCount;
showEventTime('click');
setTimeout(function () {
showEventTime('timeout function ' + (hideShowCount-hideShowCountAtClick) + ' hide/show events');
if (hideShowCount == hideShowCountAtClick){
// app is not installed, go to App Store
window.location = 'http://itunes.apple.com/app';
}
}, 1000);
}
function currentTime()
{
return Date.now()/1000;
}
function showEventTime(event){
var time = currentTime() ;
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createTextNode(time + ' ' + event));
}
</script>
</body>
</html>