Dengar's Blog Logo

Dengar's blog...
We will see what I post, probably will be some random tutorials

Monday, 31 January 2011

Geo IP lookup - ipinfodb.com API integration using PHP

(this also explains the PHP DOM parser)

For one or the other reason, and be it that you want to determine the home country of your visitor for localisation and language options, you might find yourself looking at integrating an IP lookup through an external API.

I suppose they all work very similar, but I have just integrated my shopping cart with the API from IPInfoDB.com. How it works is explained below...

A word up-front, though: When using third party APIs - think! Do you really need to hit the API with every page request? Especially in this case, would it not be fair to assume that the whole sessions would be coming from the same IP and therefore the same country? To an extend, could you not assume that it is one user you are tracking here and that he would probably come back to your site from within the same country, even though his IP might have changed? Could you therefore store the result from the API in a browser session or in a cookie?
- I actually do store it in the DB per cookie, but that's not important for this little tutorial.

First up, you will need to have access to the API, so you need an API key, token-code or something to identify yourself with the API. On the IPInfoDB.com site you can register and receive your free key within seconds.

Got the key? - off we go then: Thankfully this is a pretty simple API that doesn't use SOAP, but requires a simple HTML request and returns a nicely formatted XML. Here is a result:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Status>OK</Status>
<CountryCode>GB</CountryCode>
<CountryName>United Kingdom</CountryName>
<RegionCode>P9</RegionCode>
<RegionName>Windsor and Maidenhead</RegionName>
<City>Hillingdon</City>
<ZipPostalCode></ZipPostalCode>
<Latitude>51.5167</Latitude>
<Longitude>-0.45</Longitude>
<Gmtoffset>0</Gmtoffset>
<Dstoffset>0</Dstoffset>
<TimezoneName></TimezoneName>
<Isdst></Isdst>
<Ip>217.42.247.86</Ip>
</Response>
So far so good... Let's create a corresponding PHP class that will make the usage easy portable to different projects.


  1. I create a class and bunch of variables and add getter methods to the class, so I can return the variables when I need them:
    class geoIP {

    var $apiKey = "XXXXYOURKEYHEREXXXX";
    var $city;
    var $country;


    function getCity() {
    return $this -> city;
  2. Now I know that API key will be available when I initialise the object. Moving on to making a call...
    It's quite easy in this instance, because we don't need to set SOAP headers or anything. It's a simple API and all information we need to give IPInfoDB can be parsed into the request URL. Here is how it looks:
    http://api.ipinfodb.com/v2/ip_query.php?key=YOURKEY&ip=IPTOCHECK&timezone=false
    So I create a method, let's say, "makeCityCall" that I can then send the IP to check to:


    function makeCityCall($ip) {
    $urler = 'http://api.ipinfodb.com/v2/ip_query.php?key='. $this -> apiKey .'&ip='. $ip .'&timezone=false';
    The "$this -> apiKey" will return the API key that we declared and initialised as a global variable for this class. The "$ip" is what I send to the method.

  3. I know when I load this URL, I get an XML response. XML is best parsed via a DOM-parser. The DOM parser comes standard with most versions of PHP and is an object in it's own rights. We have to instantiate this and can then give it the URL we declared ($urler) to load:
    $parser = new DOMDocument();
    $parser  -> load($urler);
  4. As we saw by the result returned above, the interesting bit is wrapped in a XML node called Response. We only get one, of course, but I will still ask the DOM parser to repeat the process of getting the values from all nodes that it finds:
    $nodes = $parser -> getElementsByTagName("Response");
    foreach ($nodes as $node) {
    I now want to get the values of the nodes contained within the Response node:
    $cc  = $node -> getElementsByTagName('CountryCode');
    $cc =  $cc -> item(0)->nodeValue;
    $this -> countryCode = $cc;

    $cty = $node -> getElementsByTagName('City');
    $cty = $cty -> item(0)->nodeValue;
    $this -> city = $cty;

    $ctry = $node -> getElementsByTagName('CountryName');
    $ctry = $ctry -> item(0) -> nodeValue;
    $this -> country = $ctry;
    Thus setting the variables that I later want to retrieve via the getter methods.

  5. Lastly, if I now want to make a call from a PHP application, I simply need to instantiate the new class, get the IP address from the site visitor (or from wherever) and use the method to make a request. I can then retrieve the results from the getter-methods:
    $ip = $_SERVER['REMOTE_ADDR'];
    include ('PATHTOPHPFILE/geoIP.php');
    $gIP = new geoIP();
    $countCall = $gIP -> makeCityCall($ip);
    I can then write this out onto the page or re-use it as I wish:
    echo $gIP -> getCountry() . '<br />';
    echo $gIP -> getCity() . '<br />';
    echo $gIP -> getCountryCode() . '<br />';

I hope this gets you further...

No comments: