File Under: APIs, Location

Get Started With Google Geocoding via HTTP

Google’s mapping API is one of the most-used application interfaces on the web. It’s largely responsible for the recent explosion of map-based mashups. The massive popularity of Google Maps has also given rise to a new word in the web developer’s lexicon — geocodes.

Maps require a latitude and longitude point to plot specific locations. Whenever you’re programming a custom map using Google’s API, you will nee to convert the relevant city name, ZIP code, or address to latitude and longitude points. This process is called geocoding.

Google currently makes the process available via the GClientGeocoder Javascript class. That JavaScript class makes the geocode available immediately to the browser. But sometimes, such on the fly access isn’t enough. We want to store location information for later use. In that case, we need another service to grab the geocodes permanently.

That’s where geocoding via HTTP comes in handy.


Contents

  1. What You’ll Need
  2. How to Proceed
    1. Step 1: Start a Search
    2. Step 2: View the Results
    3. Step 3: Interpret the Results
    4. Where to Go From Here

What You’ll Need

  • Basic knowledge of XML and HTML
  • A Google API key. This is the same as your Maps API key. If you don’t have one, it only takes a minute to register, but you’ll need to provide a domain name (yoursite.com) where the actions will take place.
  • To incorporate results with an application, you’ll need some programming skills. I’ll be showing code examples in PHP.


How to Proceed

Step 1: Start a Search

Google lets you search for places with the geocoder much like you would using maps.google.com. Only, instead of typing into a form, we pass it an address and a city in a URL.

For example, here’s the address for Wired.com, the home of Webmonkey:

520 3rd Street San Francisco, CA

To ask Google to geocode this address, pass it off to a URL like this (remember to include your API key):

http://maps.google.com/maps/geo?key=yourkeyhere&output=xml&q=520+3rd+Street+San+Francisco+CA

That may look like a lot of gobbledygook, so here’s a breakdown of the pieces:

  • Everything before the question mark is the address for Google’s geocoder.
  • key= is how we tell Google our API key. Be sure to put yours in place of “yourkeyhere” in the example!
  • output= tells Google the format we want back. There are a few options, but we’re using XML right now.
  • q= is the most important part — it’s where we give Google our address (q stands for query).


Now let’s check out what Google sends back.


Step 2: View the Results

When we searched for the Webmonkey offices, we received a bunch of XML that looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<kml xmlns="http://earth.google.com/kml/2.0">

  <Response>



    <name>520 3rd Street San Francisco CA</name>

    <Status>

      <code>200</code>

      <request>geocode</request>



    </Status>

    <Placemark id="p1">

      <address>520 3rd St, San Francisco, CA 94107, USA</address>

      <AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0">

      <Country>



        <CountryNameCode>US</CountryNameCode>

        <AdministrativeArea>

          <AdministrativeAreaName>CA</AdministrativeAreaName>

            <SubAdministrativeArea>

              <SubAdministrativeAreaName>San Francisco</SubAdministrativeAreaName>



              <Locality>

                <LocalityName>San Francisco</LocalityName>

                <Thoroughfare>

                  <ThoroughfareName>520 3rd St</ThoroughfareName>

                </Thoroughfare>



                <PostalCode>

                  <PostalCodeNumber>94107</PostalCodeNumber>

                </PostalCode>

              </Locality>

            </SubAdministrativeArea>



          </AdministrativeArea>

        </Country>

      </AddressDetails>

      <Point>

        <coordinates>-122.395228,37.780860,0</coordinates>



      </Point>

    </Placemark>

  </Response>

</kml>


In XML, pieces of data are wrapped in tags that look a lot like HTML. There are a lot of tags in this result because Google is trying to provide a general format that works for every country.

Reading through, you can see Google’s geocoder reiterated some of the stuff we already knew: The state, California (abbreviated CA), is listed under AdministrativeAreaName. The address is listed a couple different places, and “3rd Street” query has been shortened to just 3rd St. Rewritten street names could help our applications remain consistent. It’s not a big deal, but it’s nice.

Google also passes along the ZIP code, which we didn’t know before. It even tells us the country, but hopefully that’s not a surprise.

The most useful pieces of information for mapping are the coordinates. These are listed as “longitude,latitude,elevation” though the elevation is not currently used. It’s always zero now. Latitude and longitude are all we need to plot a location on the map, so we should be fine.

In fact, if we only want the coordinates, Google provides an even easier way to get at that information. In the geocoder URL, just change the output= from xml to csv. This provides very minimal results in comma separated value format:

200,8,37.780860,-122.395228

Here we’re given HTTP status code (200 is what we want to see here), accuracy (if we supply a full address, this will be 8. Otherwise, it would be lower. More about accuracy here), latitude, and longitude.

We’ll interpret both of these output formats in the next step.


Step 3: Interpret the Results

We’ll be using PHP for these examples. Most web languages will have some method of interpreting XML, which is all that is necessary to use results from Google’s geocoder.

Since I’m using PHP, I’ll be relying on cUrl and SimpleXML. Each of these libraries is usually installed along with PHP 5. cUrl makes HTTP calls to retrieve content from web pages or services, such as the Google’s geocoder. SimpleXML takes XML content and converts it to an object, so that individual elements can easily be picked out from XML.

Create a new PHP file in a web directory with this content to test out the geocoder. I’m calling mine test_geocoder.php:

<?

/*** REMEMBER to use your own API key ***/

$apikey = "yourkeyhere";

$geourl = "http://maps.google.com/maps/geo?q=520+3rd+Street+San+Francisco+CA&output=xml&key=$apikey";



// Create cUrl object to grab XML content using $geourl

$c = curl_init();

curl_setopt($c, CURLOPT_URL, $geourl);

curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);

$xmlContent = trim(curl_exec($c));

curl_close($c);



// Create SimpleXML object from XML Content

$xmlObject = simplexml_load_string($xmlContent);



// Print out all of the XML Object

print header("Content-type: text/plain");

print_r($xmlObject);

?>



Now load test_geocoder.php in your browser. The output should look like this:



SimpleXMLElement Object

(

  [Response] => SimpleXMLElement Object

    (

      [name] => 520 3rd Street San Francisco CA

      [Status] => SimpleXMLElement Object

        (

          [code] => 200

          [request] => geocode

        )

      [Placemark] => SimpleXMLElement Object

        (

          [@attributes] => Array

            (

              [id] => p1

            )

          [address] => 520 3rd St, San Francisco, CA 94107, USA

          [AddressDetails] => SimpleXMLElement Object

            (

              [@attributes] => Array

                (

                  [Accuracy] => 8

                )

              [Country] => SimpleXMLElement Object

                (

                  [CountryNameCode] => US

                  [AdministrativeArea] => SimpleXMLElement Object

                    (

                      [AdministrativeAreaName] => CA

                      [SubAdministrativeArea] => SimpleXMLElement Object

                        (

                          [SubAdministrativeAreaName] => San Francisco

                          [Locality] => SimpleXMLElement Object

                            (

                              [LocalityName] => San Francisco

                              [Thoroughfare] => SimpleXMLElement Object

                                (

                                  [ThoroughfareName] => 520 3rd St

                                )

                              [PostalCode] => SimpleXMLElement Object

                                (

                                  [PostalCodeNumber] => 94107

                                )

                            )

                        )

                    )

                )

            )

          [Point] => SimpleXMLElement Object

            (

              [coordinates] => -122.395228,37.780860,0

            )

        )

    )

)




To access individual elements, such as the postal code, provide the path to the element like this:


print ($xmlObject->Response->Placemark->AddressDetails->Country->AdministrativeArea->SubAdministrativeArea->Locality->PostalCode->PostalCodeNumber);


Think that's ridiculously long? Me too. If you are using several pieces of data from one section, say Locality, you could shorten a bit by setting a variable to a partial path, like so:

$localObject = $xmlObject->Response->Placemark->AddressDetails->Country->AdministrativeArea->SubAdministrativeArea->Locality;

print ($localObject->PostalCode->PostalCodeNumber);

print ($localObject->LocalityName);


That's still ugly, so if all you need are the coordinates, the comma separated values might be the way to go. You can bypass the entire XML process and only have a few pieces of data. Here's the PHP to print out the latitude using the CSV option:

<?

/*** REMEMBER to use your own API key ***/

$apikey = "yourkeyhere";

$geourl = "http://maps.google.com/maps/geo?q=520+3rd+Street+San+Francisco+CA&output=csv&key=$apikey";



// Create cUrl object to grab XML content using $geourl

$c = curl_init();

curl_setopt($c, CURLOPT_URL, $geourl);

curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);

$csvContent = trim(curl_exec($c));

curl_close($c);



// Split pieces of data by the comma that separates them

list($httpcode,$long, $lat, $elev) = split(",", $csvContent);



print header("Content-type: text/plain");

print $lat;

?>


When all you need are the coordinates to plot a point on a map, use the CSV option. It will be quicker, because only a small amount of data has to be retrieved and processed. And your code will be simpler, because you don't need to spelunk down a deeply nested chunk of XML.


Where to Go From Here

Being able to geocode addresses opens the doors to becoming a power user of the mapping APIs. The Google geocoder gives you the data you need, so you can focus on the cooler aspects of your applications. Here are some ideas to help you take the next steps:

  • When asking users for their address, you can determine the correct format and the ZIP code to ensure a good address.
  • Pre-process common locations and store the latitude and longitude in a database for easy, quick access.
  • The best place to go from here hasn't yet been plotted on a map. Go do it!