Google Maps API part 1: Accurate Geocoding for UK Postcodes

Google Maps API part 1: Accurate Geocoding for UK Postcodes

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.

<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<title>Lucky Larrys Google Maps Geocoder</title>
		<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=[YOUR API KEY]" type="text/javascript"></script>
		<script src="http://www.google.com/uds/api?file=uds.js&amp;v=1.0&amp;key=[YOUR API KEY]" 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">
 
   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.

</head>
<body>
<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>&nbsp;</td>
      <td><input name="addAddress" value="Add" type="submit"/></td>
    </tr>
</table>
    </form>
Server-Response:<br/>
<span name="results" id="results"></span>
</body>
</html>

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.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • TwitThis
  • Facebook
  • Google Bookmarks
  • MySpace
  • Technorati
  1. Creating XML from PHP/ MySQL for use with SPRY
  2. Using Javascript/ AJAX to post HTML form data
  3. Google Maps API part 2: Retrieving Postcodes from your database
  4. Using SPRY to fetch values from a URL
  5. Running multiple instances of Jboss on one server.
  6. Upload a File Using PHP
  7. Adding and changing Mod JK JVM route, URI encoding and thread settings for JBoss
  8. Quick popup/overlay show and hide a layer with Javascript and CSS
  9. Joining columns/ concatenate strings in Oracle PLSQL/ MySQL
  10. Setting the JDK version and compiler in JBoss for JSP pages