Google Maps API Tutorial

Some Recommended Tools

Venkman Javascript Debugger

Venkman is the original Javascript Debugger for Firefox and Mozilla. Venkman forms part of the standard Mozilla package and is available as a Firefox extension. You can get the Firefox version here. It’s got a pretty steep learning curve.

I now recommend Firebug (see below) rather than Venkman.

Tidy HTML Validator

There are several HTML validation routines around. I happen to like this one because it’s not overly pedantic about tiny details, and it gives a neat concise explanation of the reasons why it thinks your HTML is incorrect.

It comes as a Firefox extension, and puts a little green tick on the status bar when it considers your code to be valid, so you don’t have to keep remembering to send your page to an external validator whenever you change something, you just watch to see if the green tick turns into a yellow triangle or a red cross.

The Windows version is here. There are Linux, MacOSX and FreeBSD versions here.

Web Developer

An indispensable Firefox Extension for general web development.

For Google maps API work, its “Information:View Javascript” facility is very useful for instantly collecting together all the Javascript contained in the webpage and in all the files that it loads. And the “Disable:Disable Styles:Disable Individual Stylesheet” comes in handy for spotting if any of the strange behaviours of your map are due to CSS settings.

Download the Firefox version here.

Javascript: The Definitive Guide

By David Flanagan. This is the book to read if you want to learn more about Javascript.

It’s part of the O’Reilly series of Definitive Guides, which are all excellent resources for their respective topics.


w3schools  is an excellent resource for finding details of almost any web-related technology. Of particular interest to API programmers are their Javscript Tutorial and their Javascript Reference, but their information on other topics can be very useful. If you just want to know about how to use one or two features of a technology like XSLT or CSS, you’ll find comprehensive information and clear examples.

The technologies covered are: HTML, XHTML, CSS, TCP/IP, XML, XSL, XSLT, XSL-FO, XPath, XQuery, XLink, XPointer, DTD, Schema, XML DOM, XForms, SOAP, WSDL, RDF, RSS, WAP, Web Services, JavaScript, HTML DOM, DHTML, VBScript, E4X, WMLScript, SQL, ASP, ADO, PHP, .NET, .NET Microsoft, .NET ASP, .NET Mobile, Media, SMIL, SVG and Flash.

And it’s all free.

MS Visual Web Developer Express

Some people have recommended this Microsoft tool. I can’t comment since my computer falls short of the system requirements in almost every category, so I’ve not tried it.


Provides a facility within MSIE that mimics Firebug.

It contains a DOM inspector, HTTP inspector, Javascript Inspector, Javascript console, HTML validator.

It’s still in beta, and performs very erratically on my machine, and interferes with the behaviour of Google Maps, but it’s an awful lot better than nothing.


Javascript debugger for MSIE.

Requires Microsoft Script Debugger.

I’ve not tried this out yet.


Embeds a copy of Internet Explorer inside a Mozilla/Firefox tab.

I think there are only versions for Windows.

This is a great tool for web developers, since you can develop your code in Firefox. Then, with a single click of the ieTab icon, you can see what sort of mess MSIE makes of it, and still be in a Firefox environment.


Firebug is an extension that integrates with Firefox to put a wealth of development tools at your fingertips while you browse. You can edit, debug, and monitor CSS, HTML, and JavaScript live in any web page.

Unlike Web Developer, Firebug works on the dynamic version of the page, so, for example, you can look at the way the html elements that contain the map change as you make calls to the API.

To get the best out of Firebug, you need to install the Firefox DOM Inspector. The DOM Inspector isn’t an extension, it’s an optional component of Firefox. To install the DOM Inspector you need to re-install Firefox and choose the “Custom Setup” option instead of “Standard”.

There seem to occasionally be severe conflicts between Venkman and Firebug, when Venkman tries to handle errors that are thrown by the Firebug code. I’ve ended up uninstalling Firebug for now, because I’ve already invested a lot of time learning Venkman. If you’re starting out from scratch, I’d suggest learning Firebug rather than Venkman plus Web Developer.

Chrome Inspector

View your page in Google Chrome, right-click on an element and select “Inspect Element”.

This gives you:

  • A detailed view of the dynamic HTML and styles, including the details of what’s going on inside the map structure.
  • A Javascript command console.
  • Information about the timing and size of resources such as image files and Javascript modules.


Useful for addressing performance issues. Provides standard performance tests for your web page.

Paste the URL of your page into

I recommend this rather than using the resources information from Firebug or Google Chrome because they give results that are distorted by the fact that connectivity to your own server may well be perceived as being much faster than other people will see it. The tests are performed with MSIE, which has performance issues which may need to be addressed which Firefox and Chrome don’t exhibit. You get the option to perform the tests over three different line speeds.

Custom Maps

Google Maps API Tutorial

Browser Connection Limits


This page was inspired by the fact that Google seem to have imposed timeouts on the tile fetches. That’s fine for Google tiles that are provided by fast servers, but if you have a slow server, it looks like the API doesn’t always wait long enough before giving up and deciding that the fetch has failed.

I noticed that fetching an individual tile from a page that exhibits the problem wasn’t much any longer than fetching an individual Google tile. The significant difference was that the Google map types were fetching more tiles at once, so the total time taken to fetch all the tiles was significantly shorter. Google achieve this effect by using aliases to break the browser connection limits.

What are Browser Connection Limits?

Although browsers are capable of fetching many files simultaneously, only two files will be fetched simultaneously from the same domain. This limit made some sense back in the days when the majority of Internet users had slow dial-up connections, but it makes no sense with today’s high speed connections. For most pages, the continuing existence of these limits doesn’t slow the page loading down to make it worthwhile for the limits to be redesigned, but they do have a significant effect on map tile fetches.

So what can we do?

What Google do is have four different subdomains,,,, and share the tile fetching between them. The browser doesn’t know that these are all aliases for the same machine, and allows two simultaneous fetches to each subdomain. So eight tiles get fetched at the same time, instead of two.

Here’s an example where I spread the load across four subdomains of

The code looks like this

        var subdomain=(a.x+a.y)%4;
        return "http://sub" +subdomain+ ""+a.x+"_"+a.y+"_"+(17-b)+".jpg"

The rest of the code is the same as that used in custommap1.htm.

I created “” etc., as subdomanins that have the same destination (or “Document root”) as “”, so there actually is only one set of tiles on the webserver, but the browser has no way of knowing that.

How much faster is it?

In those examples, you may not notice much speed difference visually, but when the pages are analysed with PageTest, the old one typically loads in 4.5 seconds and the new one in 3.4 seconds.

Even then, that doesn’t seem like a huge improvement, but if you compare the timings from the start of the first tile request to the completion of the last tile request, those times have gone down from 2.9 seconds to 1.4 seconds. If you have a slow server, the differences would be expected to be more significant.

The timings

I don’t know how long PageTest keeps the timing results, but for now you can see one set of results for the custommap1 at and for custommap1p

More advanced stuff

Google Maps API Tutorial

UK Posctcodes

The Problem

Since I wrote this page, The Problem seems to have gone away making this page unnecessary

Unlike other countries, the geographical information associated with UK postcodes is strictly controlled. The copyright is owned by the Royal Mail, who make a lot of money selling licences to use it.

For example, I just bought a new TV. The guy at the shop didn’t ask for my address, but just asked for my postcode and house number, and used that to find my full street address. The shop presumably finds it worthwhile fo pay the annual £85 licence per workstation, or the annual £75,000 corporate licence for all the workstations operated by that chain of stores, or one of the intermediate licences. Since large numbers of UK high street shops do the same thing, that adds up to an awful lot of money that the Royal Mail receive from licensing that data. Therefore they’re not keen to allow Google to give the information away for free via the API geocoder.

The Royal Mail have allowed Google to buy a licence to use the data on its own websites, but not to redistribute the data to other people.

This results in it being possible to find the exact location of “FY2 0HH, UK” at, but if you try the same search with the API geocoder you get a point that’s nearly a mile away.

What actually happens

The API geocoding database contains the locations of places like “FY2 0” and “FY2 9”. I.e. the “outcode” part of the postcode plus the numeric part of the “incode”.

When you reverse geocode a point, it gives the correct one of those locations as the Locality.PostalCode.PostalCodeNumber

When you forward geocode a UK postcode, the geocoder is only allowed to look at the “outcode” part. It then returns an arbitrary one of the “FY2 ?” locations, not necessarily the correct one. Which one of those locations actually gets returned is influenced ny things like country bias. There is a suggestion that it might even be biassed by the location of the user who is calling your page.


Use the full address

You could always ask your user to input their full address. That generally works.

The terms of the licence require the geocoder to discard the “incode” part of the postcode, and effectively performs a search for [street address] near [outcode]. In some extreme cases, even that won’t work. An example near where I live is “10 Bispham Road FY6 7PE, UK”. There are three “Bispham Road”s that are near FY6. One at “FY3 7HJ”. One at “FY5 1DG” and the one that I asked for at “FY6 7PE”. The API geocoder returns all three, but the one I asked for is the second placemark.

Use a non-google geocoding service

I don’t know of any commercial on-line services, but I’m sure there are some.

Buy the data from the Royal Mail

Put it on your server and perform your own lookups. I reckon that you need to pay the annuall £3,850 fee for a System Licence to do that.

Use the Google Local Search API

I’ve no idea how the licensing of this works, but calls to the Google Local Search API do correctly geocode full UK postcodes.

A Google spokesman did once say that this might not always be the case, so if you do use this strategy don’t be surprised if it suddenly stops working.

It’s not a good idea to use Google Local Search as a general purpose geocoder. It’s slower than the API geocoder and can sometimes get confused between placenames and business names. So if there’s a possibility that your search string might not be a UK postcode, it’s a good idea to test it first, see below.

Use GDirections

I’ve no idea how the licensing of this works, but calls to GDirections do correctly geocode full UK postcodes. The locations are slightly different from the locations, since they will have been snapped to the nearest street.

The strategy is to request a route from the postcode to itself, like “from: FY2 0HH to: FY2 0HH”, wait for the reply, then use .getPolyline().getVertex(0) to obtain the location.

If you do use this strategy don’t be surprised if it suddenly stops working.

It’s not a good idea to use GDirections as a general purpose geocoder. It’s slower than the API geocoder, has a lower daily quota, and can only handle one request at a time. So if there’s a possibility that your search string might not be a UK postcode, it’s a good idea to test it first, see below.

There’s also considerable doubt about whether this strategy is legal. Read section 10.12 of the Terms for yourself before implementing this strategy.

Testing if a string is a UK postcode

To test if a string looks like a UK post code you can use this regexp
^[A-Z]{1,2}[0-9R][0-9A-Z]? [0-9][ABD-HJLNP-UW-Z]{2}$.

That expession assumes that the string is in upper case, has exactly one space between outcode and incode, has no leading or trailing whitespace and no punctuation. That’s a bit more severe than we need, since GDirections and Google Local Search will accept any case and any punctuation and whitespace, so you might want to tidy it up first before performing the test.

That expression should be sufficient to distinguish a full UK postcode from anything else, but if you want to be more exact, there’s a long form in the Wikipedia. Don’t use the very long expression from the Wikipedia article that includes BFPO postcodes, because BFPO postcodes don’t represent fixed geographical locations, but groups of British Overseas Forces which may well be mobile.


Here’s an example that tests whether a search string is a UK postcode, and if so uses the GDirections trick rather than the GClientGeocoder to find the location.

More advanced stuff

Google Maps API Tutorial

Geocoding with error handling

The mechanics of geocoding without error handling are well explained in the official documentation but the examples shown there do not include error handling.

Geocoding requests can fail for a variety of reasons, so it’s a good idea to check for successful completion before attempting to plot markers using the returned information.

It’s also helpful to display the failure reason to your users, where possible, otherwise your users might waste their time doing things like trying to guess the correct spelling of “Sauchiehall Street, Glasgow, UK”, if the problem isn’t the spelling but the fact that you’ve used up youir geocoding quota already.

What you can do is to set up an array like this

 var reasons=[];

 reasons[G_GEO_SUCCESS]            = "Success";

 reasons[G_GEO_MISSING_ADDRESS]    = "Missing Address: The address was either missing or had
                                      no value.";

 reasons[G_GEO_UNKNOWN_ADDRESS]    = "Unknown Address:  No corresponding geographic location
                                      could be found for the specified address.";

 reasons[G_GEO_UNAVAILABLE_ADDRESS]= "Unavailable Address:  The geocode for the given address
                                      cannot be returned due to legal or contractual reasons.";

 reasons[G_GEO_BAD_KEY]            = "Bad Key: The API key is either invalid or does not match
                                      the domain for which it was given";

 reasons[G_GEO_TOO_MANY_QUERIES]   = "Too Many Queries: The daily geocoding quota for this site
                                      has been exceeded.";

 reasons[G_GEO_SERVER_ERROR]       = "Server error: The geocoding request could not be
                                      successfully processed.";

and display the text associated with the reply.Status.code.

When using geocoder.getLocations(), accessing the status code is straight forward, see this example

When using geocoder.getLatLng(), the status code is not returned. You could follow a failed getLatLng() with a getLocations() request and examine its status code. There is a possibility that the status code might be different, in particular, if there was a server timeout on the first attempt, the second attempt might even succeed.

I recommend avoiding geocoder.getLatLng(). It might seem to make the coding easier, but the lack of error handling makes things more difficult in the long run.

Fitting the zoom

The geocoder now returns an ExtendedData section which gives details of a Lat/Lon box that can be used to zoom the map appropriately. Here’s an example.

In that example, if you search for “France” you get zoom level 6. If you search for “123 Avenue des Champs-Elysees, Paris, France” you get zoom level 16.

Note that the Lat/Lng box isn’t a perfect fit for the target location. It’s just there to provide sensible zooming.

Potential Pitfalls

  1. Be aware that geocoder requests are asyncrhonous. The request is sent to the geocoder and processing continues immediately without waiting for the reply to come back.Make sure that all the code that operates on the results is placed inside the event handler function.
  2. Don’t send lots of requests at once. There’s a rate limit on the number of geocode requests that you can send per second.

The Basics

Google Maps API Tutorial


The GGeoXml() feature creates an overlay from a KML file.

You use it like this:

   var kml = new GGeoXml("");

Here’s an example

Potential Pitfalls

  1. The KML file must be accessible by the Google KML rendering server. It won’t work with KML files on your local computer. You don’t get any error messages if the KML file is inaccessible.
  2. GGeoXml overlays don’t support .hide() and .show() methods. To hide them, use map.removeOverlay().
  3. Calling map.removeOverlay() on a GGeoXml overlay recovers the memory used, and destroys the information. Once you use map.removeOverlay(xml), you have to re-create it before calling map.addOverlay(xml) again.