Geolocation in the Browser

Tweet

Geolocation is undoubtably one of the most useful features of smartphones, and much attention has given to native apps that take advantage of it. Less appreciated is the fact that it’s now feasible to build web apps and sites with geolocation capabilities. The W3C Geolocation API Specification proposes a standard for accessing location services in the browser via Javascript. The spec is recent but is already widely supported by modern browsers. Now is the ideal time to consider how a location aware mobile site could benefit your users.

Current browser support for the W3C Geolocation API

  • iPhone 3.0 +
  • Android 2.0 +
  • Firefox 3.5
  • Safari 5.0
  • Chrome 5.0
  • Internet Explorer 9.0+

How the Browser Finds You

There are a number of methods employed in geolocation. Your browser may simply lookup your IP address, or ask Google for the location a nearby wifi hotspot. A desktop browser, with no access to GPS, will resort to one of these methods and they are not particularly accurate. Chrome misses my current location by about 15km, but it’s good enough to tell I’m in Melbourne, Australia.

Your phone has access to better information. It can access the position of the cell towers it’s talking to and take a reasonable stab at your actual location. Last but not least, the phone will activate its GPS hardware which can pin you down to within a few meters. The GPS chip draws significant power from a phones battery, so be considerate: if this level of accuracy isn’t necessary, don’t use it.

As with native apps, permission for the browser to use your location is always opt-in. Users will be receive a request to access their location, and can reset permissions at any time via their browser settings. The challenge is ensure users trust you to use their location responsibly, and for your site to offer value with—or without—access to the location data.

The Code

If geolocation is supported, a global navigator.geolocation object will be available:

if ( navigator.geolocation )
{
	navigator.geolocation.getCurrentPosition(handlePosition);
}

getCurrentPosition will request location from the browser and pass a position object to the specified callback:

function handlePosition(pos)
{
	alert("Your location is: " + pos.coords.latitude + ', ' + pos.coords.longitude);
}


Try it:


The position object should have the following properties:

  • coords.latitude in degrees.
  • coords.longitude in degrees.
  • coords.accuracy approximate, in meters.
  • coords.heading degrees from north (0…360).
  • coords.speed in meters per second.
  • coords.altitude in meters above sea level (approximate – I wouldn’t rely on it!).
  • coords.altitudeAccuracy in meters.
  • timestamp a DOMTimeStamp object.

There’s a good chance many of these will be null, you can only rely on coords.latitude and coords.longitude.

There are also a number of reasons getCurrentPosition may fail: location data may simply be unavailable, or the user may have denied access. A second callback can be specified to handle errors:

if ( navigator.geolocation )
{
	navigator.geolocation.getCurrentPosition(handlePosition, handleError);
}

function handleError(error)
{
	switch (error.code)
	{
		case error.PERMISSION_DENIED:
			// User denied access to location. Perhaps redirect to alternate content?
			alert('Permission was denied');
			break;
		case error.POSITION_UNAVAILABLE:
			alert('Position is currently unavailable.');
			break;
		case error.PERMISSION_DENIED_TIMEOUT:
			alert('User took to long to grant/deny permission.');
			break;
		case error.UNKNOWN_ERROR:
			alert('An unknown error occurred.')
			break;
	}
}

Your web app should handle all cases gracefully. If a user declines to share their location, consider offering alternative content or features that do not rely on geolocation. Further consideration can be given to your users with options passed to getCurrentPosition:

options = {
	enableHighAccuracy: false,
	timeout:            30000,  // milliseconds (30 seconds)
	maximumAge:         600000 // milliseconds (10 minutes)
}
navigator.geolocation.getCurrentPosition(handlePosition, handleError, options);

enableHighAccuracy is essentially a hint that you want GPS data (rather than less accurate methods such a cell tower triangulation). As mentioned above, GPS drains the phone battery and isn’t always required – set this to false if you only need a general area.

timeout specifies how long you’re willing to wait for location results.

maximumAge tells the browser you’re willing to accept a result from within, for example, the last 10 minutes. If the phone has done a location lookup in that time (possibly for another site/app) it will return a cached result. Again, this is a way of being kind to the phone’s battery life.

What if you need up-to-the-minute location data that updates when the user moves? You can use watchPosition:

if ( navigator.geolocation )
{
	navigator.geolocation.watchPosition(handlePosition, handleError, {
		enabledHighAccuracy: true,
		maximumAge: 60000
		});
}

function handlePosition(pos)
{
	console.log("Heading: " + pos.coords.heading);
	console.log("Speed:   " + pos.coords.speed);
}

In most instances this level of accuracy won’t be required. With valid privacy concerns around the use of location data, it’s important to only access information your need and use it responsibly. Some simple guidelines:

  1. Consider the value you’re providing to your users in return for their location – don’t simply collect data for the sake of it!
  2. Be kind to phone batteries – use enableHighAccuracy: false if you only need a broad location.
  3. If you store location data, make this clear through on your website (and in your site’s terms & conditions).

Google Maps

Now we’ve covered the basics of geolocation let’s see how it fits in with Google maps. Maps support can be added to your web app with:

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>

The sensor parameter indicates whether you are using a sensor – i.e. GPS – to detect location. For mobile applications this should be set to true. We can further tailor our map with some user agent detection – this snippet will give Android and iPhone users a full screen map:

function detectBrowser()
{
	var userAgent = navigator.userAgent;
	var mapDiv = document.getElementById("map");

	if (userAgent.indexOf('iPhone') != -1 || userAgent.indexOf('Android') != -1 )
	{
		mapDiv.style.width = '100%';
		mapDiv.style.height = '100%';
	}
	else
	{
		mapDiv.style.width = '600px';
		mapDiv.style.height = '800px';
	}
}

iPhones also pay attention the tag. This disables zooming the page so that pinch-to-zoom will be applied only to the map.

<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

Now to setup the map itself:

var map = new google.maps.Map(document.getElementById("map"), {
	zoom: 10,
	mapTypeId: google.maps.MapTypeId.ROADMAP
});

That’s all there is to it. See the Google Maps Developers Guide for the full set of map configuration options. We can now update our handlePosition function to use the map:

function handlePosition(pos)
{
	// Google maps use a different location object (LatLng) which we can convert to easily:
	latlng = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);

	// Center the map on the current location.
	map.setCenter(latlng);

	// Drop a marker on the current location
	marker = new google.maps.Marker
	({
		map: map,
		draggable: false,
		animation: google.maps.Animation.DROP,
		position: latlng
	});
}

Maps Example

Showing the user their current location isn’t the most useful application, but with the Geolocation API and Google maps at your disposal, you have an excellent set of tools for building location-based web apps. The challenge is to do something interesting! Happy geolocating.

Some further reading:

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://sitepoint.com Kristen Holden

    Great article Andrew! Very accurate on the geo-location example also, showed up the office here to within a few meters!

  • http://newarts.at Drazen Mokic

    Very nice and useful, thanks

  • Chris

    Very nice, I got spotted with my desktop computer.
    I’m wondering how it can be so precise considering my provider is from a near city.
    Chris

    • http://buildmobile.com Paul Bridgestock

      Hi Chris, and thanks for the ‘nice’ comment. As I am sure you read, there are several methods that could be employed, and in your desktop case perhaps a nearby hotspot was referenced. I also noticed different results in different browsers. If you want to share more details of your internet, location, and browser, we’ll give you even more feedback.

  • Ben Barber

    I would add a recommendation to only use Geolocation where there is an obvious benefit to the user or you risk them preemptively rejecting the location request. Wait to call getCurrentPosition or watchPosition until you’ve demonstrated how they’ll benefit from allowing their location to be shown AND you have made it clear how you are protecting their privacy or they’ll probably say “No Thanks”.

    • http://buildmobile.com Paul Bridgestock

      Hello Ben, thanks for that input. Completely agree, when we move examples like this into separate pages (that’s our plan), we will act on your suggestion for sure.

      • Ben Barber

        Oh, splitting the examples into their own pages is a great idea.

        I didn’t actually intend my comment to be a criticism of this article, but more of a recommendation to all users as they consider adding location-aware functionality to their mobile sites.

        My fear is that Geolocation will be the ‘popup window’ of HTML5, with site owners using it more for their benefit than the user’s benefit. Not only will it be annoying for users to be constantly prompted for their location but I’m afraid it will cause a rejection reflex in users that will harm developers who are actually trying to provide a better user experience.

        Developers can help the situation now by using Geolocation responsibly. Maybe an article topic in itself. :)

        • Andrew Markham

          That’s great advice Ben – earn the user’s trust before you even call getCurrentPosition. Requesting location on page load from new users should probably be considered bad practice.

          I agree constant location prompts could become an issue, however I predict browser options will mature in this department. My preference would be to skip the prompt altogether and deny by default; then manually whitelist the web apps I trust.

  • Dean

    I installed NodeDroid from Market but cant run it. Enter WHAT username? Enter What Password? What is Internode? I have tel svc from verizon. I sign in to VerizonWireless.com to check my acct every quarter. Is that the one? do I replace Internode with Verizon ??
    How about a Help button.
    Help

    • http://buildmobile.com Paul Bridgestock

      Hello Dean, quick note: please post your comment under the NodeDroid article from Bruce. You would use your provider username and password, but unfortunately the app doesn’t support Verizon. Bruce is looking for people to help him add more providers, you could help!

  • Brandon

    Is this particular example supposed to work in Safari on iPhone 4.3.3? In my case it doesn’t. Location services are ‘On’.

    • http://buildmobile.com Paul Bridgestock

      Sorry Brandon, bear with me on a better space for examples. Please check out the source code at https://github.com/buildmobile/browsergeolocation for your own use, plus a working hosted example of that code at http://3easy.org/buildmobile/geolocation/

      • http://twitter.com/adammessinger Adam Messinger

        Thanks for the tutorial; this will be helpful in implementing a geolocation-based feature I have in mind.

        FYI: This page’s example doesn’t seem to work well with the mobile version of BuildMobile, though the one on 3easy.org does (though the +/- zoom control is missing in mobile Safari).

        Neither the example on this page nor the one on 3easy.org work in Safari 5 or Firefox 4 for Windows. I just see a gray box instead of a map. Works fine in other Windows browsers, however.

        • Mark

          Ditto on the gray box with Safari 5.x

  • http://brianswebdesign.com Brian Temecula

    I guess I don’t see the reason why the user is asked to get their location. We already have ip2location, hostip.info, and other services, and we don’t need to ask. Getting the user’s IP address is easy, and getting their GPS coordinates is easy too, even without asking.

    • http://buildmobile.com Paul Bridgestock

      Hello Brian. You’re right that it’s simple to get your own location, and to get the location of commenter, based on IP address. But the idea is to enhance a website, take Decaf Sucks on a mobile browser for example. I love a nice cup of coffee, and this website pairs my location with great coffee shops suggested by other users. You have to love that, make sense?