Recently I had to build a system that would take an address, pass it to google and return latitude and longitude values. The result is then stored for later use and display on Google maps.
However, firstly I found that the default XML geocoding service provided by Google that allows you to do bulk geocoding on a data source and the geocoding provided by their maps API/ AJAX library (GClientGeocoder) had huge differences in results. Most postal codes passed to googles XML geocoding service were miles out or just not recognised. Yet when using the same postcode in the maps API when calculated on the fly the results were more or less spot on.
You can take a look at a tutorial for using Googles XML geocoder service, PHP and MySQL here. They suggest that this way is good if you don’t want to repeatedly geocode the same address again and again and if you want to do bulk geocoding.
Which would be nice, if it was actually accurate! But this still leaves me with having to do bulk uploads or geocoding and get accurate results to build, for instance, a store locator around the data.
The solution is simple, we can utilise the Google maps API to do the geocoding for us on the fly and store the result passed back using some simple AJAX to send the data to PHP/ MySQL. While I geocode my records at the time of their entry, in the example below, you could just as easily use this to create some sort of bulk update. Check out my tutorial here about using AJAX to pass form data to PHP if you’re new to this.
Firstly you will need to signup to get a couple of free API keys from google, you don’t require much to get them and they’ll work just fine for a localhost.
Maps API key: http://www.google.com/apis/maps/signup.html
AJAX Search API key: http://code.google.com/apis/ajaxsearch/signup.html
OK so now we create a HTML page, form.htm, this will call in the Javascript libraries and do the geocoding work.
<script src="http://maps.google.com/maps?file=api&v=2&key=[YOUR%20API%20KEY]" type="text/javascript"> </script> <script src="http://www.google.com/uds/api?file=uds.js&v=1.0&key=[YOUR%20API%20KEY]" type="text/javascript"> </script>
We also build a function that creates an XML object in the DOM to store the data, which will then get passed to the PHP page. This works in exactly the same way as my tutorial here.
<script type="text/javascript" language="javascript"> //<![CDATA[ var http_request = false; function makePOSTRequest(url, parameters) { http_request = false; if (window.XMLHttpRequest) { // Mozilla, Safari,... http_request = new XMLHttpRequest(); if (http_request.overrideMimeType) { // set type accordingly to anticipated content type //http_request.overrideMimeType('text/xml'); http_request.overrideMimeType('text/html'); } } else if (window.ActiveXObject) { // IE try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!http_request) { alert('Cannot create XMLHTTP instance'); return false; } http_request.onreadystatechange = alertContents; http_request.open('POST', url, true); http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http_request.setRequestHeader("Content-length", parameters.length); http_request.setRequestHeader("Connection", "close"); http_request.send(parameters); } function alertContents() { if (http_request.readyState == 4) { if (http_request.status == 200) { //alert(http_request.responseText); result = http_request.responseText; document.getElementById('results').innerHTML = result; } else { alert('There was a problem with the request.'); } } }
The next bit is the function that takes the data from the form and geocodes it or you can use another source like XML or something. Firstly we declare a new instance of GlocalSearch() one of the google functions which we setup and configure its actions which will pass the results to GLatLng() to geocode. At the bottom of this function we then execute the localSearch function passing in the parameter of the postcode variable (declared at the top of the function) along with the the country, in this case, UK.
var localSearch = new GlocalSearch(); function get(obj) { var postcode = document.getElementById("postcode").value; 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); var poststr = "addressLine1=" + encodeURI( document.getElementById("addressLine1").value ) + "&addressLine2=" + encodeURI( document.getElementById("addressLine2").value ) + "&addressLine3=" + encodeURI( document.getElementById("addressLine3").value ) + "&town=" + encodeURI( document.getElementById("town").value ) + "&postcode=" + encodeURI( document.getElementById("postcode").value )+ "&lat=" + point.lat() + "&lng=" + point.lng(); makePOSTRequest('post.php', poststr); } else { alert("Postcode not found!"); } }); localSearch.execute(postcode + ", UK"); } //]]> </script>
This chunk of code above is what utilises the google maps keys, to pass the data to google, geocode it and return the record and I’ve written this inside of a function that gets called on the form submission, which in turn then uses the previously declared XML creation function.
The final stage of this HTML page is of course the form which sends the data and a span tag that displays the results if successful.
<form action="javascript:get(document.getElementById('myform'));" name="myform" id="myform">
<table width="600" border="0" cellspacing="5" cellpadding="5">
<tr>
<td width="130">Address Line 1:</td>
<td width="435"><input type="textfield" name="addressLine1" id="addressLine1" value="" /></td>
</tr>
<tr>
<td>Address Line 2:</td>
<td><input type="textfield" name="addressLine2" id="addressLine2" value="" /></td>
</tr>
<tr>
<td>Address Line 3:</td>
<td><input type="textfield" name="addressLine3" id="addressLine3" value="" /></td>
</tr>
<tr>
<td>Town:</td>
<td><input type="textfield" name="town" id="town" value="" /></td>
</tr>
<tr>
<td>Postcode:</td>
<td><input type="textfield" name="postcode" id="postcode" value="" /></td>
</tr>
<tr>
<td> </td>
<td><input name="addAddress" value="Add" type="submit" /></td>
</tr>
</table>
</form>Server-Response:
This then just leaves us the PHP page (post.php) that will then post the results, again nothing too disimilar to my previous tutorials on this. This is the bit where you would pass in the $_POST parameters and store them using MySQL etc… or save them to a text file.
<?php print_r($_POST); //write MySQL query here ?>
And there we have it, accurate geocoding from google that can be used as a service when data is entered, or you could use this same method by passing in XML created from your database and iterating over this passing each result to the API and returning a value.
Now you can build a store locator or whatever that actually returns accurate results, also you can then use this to integrate your database better with the full Google maps API – showing maps, placing markers on maps etc..
This content is published under the Attribution-Noncommercial-Share Alike 3.0 Unported license.
- Creating XML from PHP/ MySQL for use with SPRY
- Using Javascript/ AJAX to post HTML form data
- Google Maps API part 2: Retrieving Postcodes from your database
- Using SPRY to fetch values from a URL
- Running multiple instances of Jboss on one server.
- Upload a File Using PHP
- Adding and changing Mod JK JVM route, URI encoding and thread settings for JBoss
- Quick popup/overlay show and hide a layer with Javascript and CSS
- Joining columns/ concatenate strings in Oracle PLSQL/ MySQL
- Setting the JDK version and compiler in JBoss for JSP pages









Hello,
Just thought I’d let you know that I’ve just done something similar to geocode a database of postcodes. Interesting (and frustrating I didn’t find this on google sooner – would’ve saved a lot of time) to see someone else use pretty much the exact same method.
I’ve just completed doing something similar, but before trying again thought I’d see if I can improve my methods, and arrived here via google. I basically did the same, apart from that I don’t search and cache on the fly – I wrote similar code to trawl through a database of postcodes in advance.
It’s so annoying you can’t just get the postcode data straight from the geocoder service. Also, it can be really buggy on UK addresses: http://stackoverflow.com/questions/1115901/picking-the-most-accurate-geocode
Really nice site by the way. Really like the way photos are displayed on the homepage.
Cheers Rhys, I got bummed out by the lack of geocoding for UK postcodes – even doing 10 Downing Street can provide ‘interesting’ results… glad I’m not the only one who figured out this solution.
Hello
your code is working nicely. But can you help me to get postcode from a database?
Thanks
Hi Rabbul, I’m over in Canada right now, but I’ll write something up for you after I get back this weekend, hows that?
hi – I’ve been trying to get this to work but no joy so far
a page where you had it working would be good, then us dumbos could take that to bits to figure out what is the difference – oh but I guess Google might decide you were doing too many queries
cant see what I’m doing wrong..
FYI: google added a ‘sensor’ variable in map query string
and your form input type should be ‘text’ not ‘textfield’ !
This could be the case of a change in API keys…
Looks like Google now want you to use jsapi which with my code will give you an issue. When you signup for the ajax api you get a different API key, the js one rather than the one I use here. So I need to update the link I guess and the tutorial (already!)
You actually need the UDS api which I fear may be out dated and replaced in the meantime, can you post up the error you get? it should be a javascript error that states a function cant be loaded etc.. that’ll confirm its a difference in API’s.
In the mean time when I get chance I’ll try and rework the example starting with the info at:
http://code.google.com/apis/ajax/documentation/
hi – with a bit of hacking I have it working all I need – it’s a back end function for a cms so I only need the look up when an address is added and it can manage without any ajax
many thanks for making your script public!
are you a freelance developer? (php/mysql/js etc) I often have too much work to do myself… let me know if you’re interested, I’m in south west London
I only use the Ajax calls for the form submission part, just for pre-validation.
but I’ll still check into these API updates and reconfigure if necessary.
btw. I’m always around for small freelance projects…
thanks Larry
update : I used this method so I could force a look up of latitude and longitude and get accurate markers – a year ago the marker would only be accurate to first part of postcode e.g AB2 6.. (ignoring the last two letters) but it ‘seems’ the API is now accurate to the full postcode
(I cant find any confirmation that this is the case though)
Google API free does not have a UK license for postcodes hence the accuracy of using Google maps for store Locators is very poor. They also cannot Gecode Ireland, Developers and agency’s have awful get rounds which often show US towns instead of UK as only based on the first 4 digits of a postcode.
In all, no professional would use Google as there are specialists such as Bing and ViaMichelin would have the full kit available for business’s
Although while Bing/Multimap do have good coverage in the UK (And it is better than google if you use the APIs), it is considerably worse in other countries of which google is far better such as Italy, Czech etc… Also getting Multimap (bing) to work with Ireland and small islands such as the Isle of Man is just as problematic.
I found using google to be free, easier to work with and actually just as accurate for my needs as any other – providing you get around the limitations of the API and get a direct geocode from the maps site itself (its results are far more accurate than the API request calls).
I’ve not used ViaMichelin so can’t comment on that one. What we really need is an open standard but with the Post Office being the owner (and making alot of money from sales of the data) I can’t see this happening any time soon.
Google basis (free) does not provide address verification (Geocoding) as there is no UK postcode license.
This means postcode searches are very in-accurate. The proximity search is very poor, even for town searches, often not recognising locations.
This is why Google have a premier and a enterprise solution which still is more expensive and not as good as business mapping specialists like bing and Via Michelin who also have API’s and provide distance calculation.
Remember the solution you use on google.com is not the same one they supply to business, it’s just a Basic service with serious flaws and bugs.
As a free lance developer, so serious business would use Google as the system is weak and really provides a watered down solution. I could list 100 benefits of using better providers than Google but here are some of the main ones for why I choose Bing and Via Michelin (the better of the two), accuracy, customisation, user experience, SLA, support, proximity search taking into account natural boundaries, small town recognition, detail on the map, Experienced teams and ultimately brand, who wants to spend hundreds of thousand promoting their brand to offer a solution that does not recognise locations, shows the marker in the wrong place and offers limited directions and often does not work for hours at a time? How cheap does that look and the amount of times customers will simply go elsewhere is extraordinarily high !
Larry, ViaMichelin and bing cover about 240 each and have street level for over 34 countries in Europe including Spain, Germany, UK and all the usually places, they can even Geocode Ireland, where as Google simply cannot. If you want a free solution for your small business thats fine, but in a competitive world, you simply cannot offer a poor product and get away with it anymore (why do you think MCDonalds now only use 100% beef?, it’s because Burger King did and customers wanted something better!! You have to keep up or fall behind.
Nice essay but see my previous comments as you’ve not really added anything there I’d want to comment against other than the same contradictions raised.
I like to use both and I’d seriously give Michelin a try, I just find the Google one easier to develop with, though I’m no freelance developer.