@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>