Notice: As a few people have pointed out, this announcement from Google means Geocoding is now built in. Yet as more people have pointed out – it kinda sucks accuracy wise (think over a mile off on some postcodes!), whereas my method continues to be accurate.
Google Maps API provides a geocoding feature, for finding the latitude and longitude of places or addresses; but it does not work for UK postcodes. This is thanks to Royal Mail who have a copyright on the data, and are very restrictive with their (expensive) licenses for it.
There are various solutions out there for using 3rd party services and importing the data to be used with Google Maps, or for using community built databases for the info. However, I’ve had a few people ask me about doing it just though Google.
It is possible — Google AJAX Search API does provide geocoding for UK postcodes. We need to use the two APIs in harmony to achieve our result.
So here it is.
Step by step
I’ll assume you already know how to use Google Maps API, and you came here just looking how to add geocoding for the UK.
Step 1.
Grab a two API keys, if you already have your Google Maps API key, just grab an AJAX search key. You can get them here:
http://www.google.com/apis/maps/signup.html
http://code.google.com/apis/ajaxsearch/signup.html
Step 2.
Google will give you a sample page, you need to stick your two API keys at the top of the page, followed by a reference to your Javascript file:
<script src="http://maps.google.com/maps?file=api&v=2&key=*KEY*" type="text/javascript"></script> <script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=*KEY*" type="text/javascript"></script> <script src="gmap.js" type="text/javascript"></script>
Ensure the reference to your Javascript file comes after the two API keys.
Step 3.
In addition to the Google Maps API stuff, you need to stick a reference to Google local search at the top of your Javascript file:
var localSearch = new GlocalSearch();
You can grab my Javascript file right here, but remember you’ll need to change the API keys.
Step 4.
The key to this Geocoder is only a single function:
function usePointFromPostcode(postcode, callbackFunction) { localSearch.setSearchCompleteCallback(null, function() { if (localSearch.results[0]) { var resultLat = localSearch.results[0].lat; var resultLng = localSearch.results[0].lng; var point = new GLatLng(resultLat,resultLng); callbackFunction(point); }else{ alert("Postcode not found!"); } }); localSearch.execute(postcode + ", UK"); }
It takes 2 arguments; postcode
is the postcode you want to look for, and callbackFunction
is the function you wish to run on the results.
Why is it necessary to do it this way? It is the way AJAX, and thus Google AJAX Search API, works – the request is sent, and a callback function is designated to handle the results returned, when they are ready.
In our case, the callback function can do whatever you want with the results, which will come in the format of a GLatLng
(often just called a point); I’ve supplied 2 sample functions, placeMarkerAtPoint
and setCenterToPoint
which do pretty much what they sound like they do.
Step 5.
Putting aside accessibility and graceful degradation for the sake of simplicity in this tutorial, the last step we need is just to add some hooks into our Javascript:
<input type="text" id="postcode" size="10" /> <input type="submit" value="Place Marker" onclick="javascript: usePointFromPostcode(document.getElementById('postcode').value, placeMarkerAtPoint)" />
We have a field for inputting a postcode, and I’ve added a button for placing a marker there. Where I have placeMarkerAtPoint
you can put a reference to your own function, or you can even add a function right in there, like this:
<input type="submit" value="Do whatever" onclick="javascript: usePointFromPostcode(document.getElementById('postcode').value, function (point) { alert('Latitude: ' + point.lat() + '\nLongitude: ' + point.lng()); })" />
Demo
If you are coming in from an RSS reader, either visit this blog post on the site, or see the demo page.
Postcode:
Conclusion
Until Royal Mail sort get their act together, and relax the licensing agreement, hopefully this will help people who want a ‘pure’ Google solution and hadn’t come across this option. Please use the comments section to let me know if you are using this, or if you have any improvements or suggestions.
378 responses to “Geocoding UK Postcodes with Google Map API”
Sorry for the slow reply – I’ve been on holiday. 🙂
Malcan – I’m not sure. did you get this working? If not it is maybe something that would be worthwhile writing an article about?
Dan – Did you get your problem worked out?
photomorgana – So you’d like to have a map, place a pin in it, and then have a report on what postcode/town the pin is in? Have I got the right idea?
Raha – Yes, using it on a business website is fine, as long as you aren’t charging people to use the map. (per Googles TOS). If you are looking to extract the address information, I’m sure it can be done somehow, but am not 100%. If I get a chance I’ll have a tinker about and see.
shinji – Are you including both the Google script tags *before* including your own Javascript?
andrew – Looks like you are having the same problem as shinji. Do you have an example URL I can take a peak at?
hi, tom!
i was used your script for getting uk postcode in the form. but if the form is submitted the value of latitude & longitude isn’t followed posted. can u help me for this problem?
the script look like :
var a;
var b;
function retValue(){
usePointFromPostcode(document.getElementById(‘postcode’).value,
function (point) {
this.a = point.lat();
this.b = point.lng();
}
);
document.form1.long.value = this.b;
document.form1.lat.value = this.a
}
Prashant Shah – make sure that you’ve got your in there, and I found it helped to include width and height in a style.
Tom – 1 question for you – I’m putting my map on a dynamically generated page, and so I don’t want a form, I just want it to drop in the Postcode manually. But I’m having problems getting it to centre and place the marker, perhaps because it’s trying to run the functions before the map is loaded? Any thoughts as to the best way to achieve this?
ipunk-
Move your:
document.form1.long.value = this.b;
document.form1.lat.value = this.a;
Statements inside the callback function (replacing the 2
this.a = point.lat();
lines), and see what happens.Good luck 🙂
mrben-
There is a couple of methods you could use. The key is the
addLoadEvent
function, which tells Javascript to queue up a function to run after everything is done loading.One method might be to write a
<script>
tag into your page (at any point after the<script
tags already there) which has a function to act on the postcode, which is written by your server side script (I’ve used PHP as an example):The addLoadEvent ensures this is run after everything else is done, and so it should work fine.
Let me know how you get on! 🙂
OK – I’m making progress. I was almost there – was using window.onDomReady rather than addLoadEvent.
One of the strange side effects was an inability to both place a marker _and_ centre it – it seemed to only take the last argument as the one it performed. So I wrote an additional function into your gmap.js which does both.
Thanks so much for your help 🙂
mrben-
Depending on the implementation of
onDomReady
you are using, you might be able to right anaddDomReadyEvent
function, which works almost identically toaddLoadEvent
and allows you to queue up several events to happen.Your solution works though, and is probably the more efficient way to do it if you always want to center the map and place a marker at once.
Nice work. 🙂
Hi Tom,
This works extremely well, thank you for your efforts. I was wondering if I could pick your brains?
I have a page where PHP spits out DIV tags with unique ID’s (formed from the DB primary key) and attributes for postcode and name of company.
I then use jQuery to parse all the divs in the page which have the attribute showOnPage=”true”, get the postcode attribute and add a marker to the map using your code 🙂
However! What I really want to do is add an Info Window to each marker, but I’m struggling with the code. So far, my code will create all the markers and info windows, but the content of the info windows are all the same!
Any ideas on how you could adapt your code to produce info windows?
Thanks in advance, freshness
Sorry, the attribute above should have been ‘showOnMap=”true”‘. My bad 😀
I’m trying to do exactly the same thing as freshness and having exactly the same problem! Tried modifying the usePointFromPostcode function to take optional parameters with information about each marker that is then passed into the placeMarkerAtPoint function:
usePointFromPostcode(postcode, callbackFunction, optParam)
But with different parameters being passed in I’m finding that the callback function only ever sees the last optional parameter value. But the postcodes are different! I guess this is to do with the way callbacks work and although I’ve got a vague understanding of it got to admit I don’t understand fully. Any chance of a bit of advice on this Tom? Your great work so far on this is really appreciated!
Cheers,
Steve
freshness, Steve,
Try moving the line:
var localSearch = new GlocalSearch();
Inside the
usePointFromPostcode()
function. This will then create a seperate instance for each search, so the variables won’t get mangled.You can then pass your extra data as an additional parameter to the
usePointFromPostcode()
function, which in turn passes it on the callback function. Alternatively, inusePointFromPostcode()
, you can tack your extra info inside thepoint
you create from the results. In which case the function definition would look like:function usePointFromPostcode(postcode, callbackFunction, infoText)
And right after you create
point
you would add this line:point.infoText = infoText;
Now, any functions which use
point
can access the associated infoText (to create an info window, use as a tooltip or whatever you want).I hope that helps! 🙂
Tom,
I have an access database for London, the user hits an address field button, Access then loads googlemaps and goes to the postcode for the address field. But it’s not always accurate.
I would like to be able to get the Geocodes for the addresses in my database, (I have about 4,000) do you know where/what the best way to go about this would be. I don’t want to use this on a website and I don’t really understand how to code ASP/Java/Ajax, etc.
Hi Tom,
Wow, who would have thought it would be that simple! As you instructed, I moved the variable declaration inside usePointFromPostcode() and bingo – my info windows are no longer muddled! Thank you so much, great work.
freshness —
No problem – glad you got it all working 🙂
Vee —
I’m a little unsure of what you want to do. You *do* want to send people from your Access database to Google maps, right? Or is that a temporary solution? Bombard me with the details!
Tom,
I have a fixed number of routes (think delivery vehicles). The routes have waypoints along the way. Here is an example.
Waypoint Postcode:
South St. SE1
Gill St. SE1
Bridge Road SE1
Marshal Road EC1
Great Street EC1
Main Roundabout EC2
At the moment, My database will allow a user to click on any waypoint in any sequence, and will then compile a parsed search list of the addresses for GoogleMaps. When a user hits the ‘Do Route’ button, the program switches to googlemaps, sends the parsed list, and Google Maps then runs the route. It works quite well for streets/places it knows, but when GM encounters places like ‘Main Roundabout’ like the last item in my sample list, GM just falls over. So I figured the best solution is not to rely on postcodes, but use LAT/LON Geo co-oridnates instead.
The problem is that I have a very large table of Addresses and places already in postcode format, so I need a way of translating the addresses/postcodes into a Lat/Lon geo format using an automated method. This is purely for the MS Access internal data records. In other words it is used standalone and is not going to be a website/or backend for a website. (I am not web/http savvy.)
does this make better sense now?
regards
Vee
Just a quick note to say a big thanks for your May 4, 2007 @ 2:56 pm post Tom. For some reason just moving the GlocalSearch didn’t fix it with my code but putting the HTML in the point’s InfoText did. Cheers for the fix, you seem to be a man in demand at the moment!
Best regards, Steve
🙂 hi tom thanks for the tips
Simply amazing. Thanks for this.
hi tom
Thanks for this code.
However, after replacing the keys, the map doesn’t load.
No map, no error messages.
really would appreciate some help – am I doing something really stoopid?
thanks
Scott
OK – found the problem.
The map div requires size parms e.g:
all is right with the World ..
But, can you help me … I need to grab the lat and lng values to store in a db
– any ideas??