Data Management

Match users to their geo-location with PHP and PEAR Net:Geo

Small Web sites can use PHP and HTML to map a user's IP address to a geographical database to identify their location.

Ever wondered how sites like Google and Yahoo! always seem to know which country you're in, and automatically redirect you to the most appropriate country sub-site? Or how some Web sites display advertisements perfectly targeted to your city or region? Well, it isn't magic -- these sites are simply mapping your IP address to a geographical database to identify your location, and then using this information to send you precisely-targeted data.

The coolest thing about this, though, isn't the technology. It's the fact that even small Web site owners and developers can access and use this technology, if they know a little PHP and HTML. And that's where this brief article comes in. I will introduce you to some simple tools that you can use to set up geo-location on your own Web site.

Installation

The first order of business is to install all the required pieces. I'll assume here that you have a working PHP and Apache installation, and so first direct you to the PEAR Net_GeoIP package. This package provides an object-oriented framework to retrieving geographical information from an IP address. You can install this package directly from the Web, either by downloading it or by using the instructions provided.

Once you've got that installed, the next step is to download and install the free MaxMind country database. This database contains an extensive list of IP address ranges mapped to countries, and provides the foundation for the geo-location code we're going to write in the next section. The database is supplied only in binary format, and is required by the Net_GeoIP package.

Ensure that both the Net_GeoIP class files and the MaxMind binary database file are located under the Web server document root, and are readable by the Web server user.

Note:MaxMind provides both commercial and free versions of its databases, and each is subject to different license terms and usage restrictions. For our purposes, the free version is sufficient; however, if your application requires extremely precise geo-location, you should consider investing in one of the commercial solutions. Remember to read the license terms before using either version on your Web site to ensure you are in compliance.

Basic Usage

With the pieces in place, let's look at a simple example of geo-location. Create a PHP script with the following lines of code (Listing A):

Listing A


<?php
// include class
include("GeoIP.php");

// initialize object
// open database
$geo = Net_GeoIP::getInstance("GeoIP.dat");

// look up IP address
$country = $geo->lookupCountryName("216.239.115.148");
echo "IP mapped to: " . $country;

// close database
$geo->close();

// acknowledgement, required by MaxMind
echo "This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/."
?>

First, the getInstance() static method is used to initialize a new instance of the Net_GeoIP class. This method must be passed the path to the MaxMind binary database file. Once this relationship has been established, the lookupCountryName() method is invoked with an IP address as argument. As the name suggests, this method looks up the IP address in the MaxMind database file and retrieves the corresponding country code. The database connection is then closed with a call to close(), and the country name is printed to the page.

The steps above make up a fairly standard process, and you'll see them in all the scripts that follow. Here's what the output looks like:

IP mapped to: United States

If all you have is a domain name, no sweat -- simply use the native PHP gethostbyname() function to retrieve the corresponding IP address. Listing B shows you how (the output is equivalent to that of the script above):

Listing B


<?php
// include class
include("GeoIP.php");

// initialize object
// open database
$geo = Net_GeoIP::getInstance("GeoIP.dat");

// look up IP address
$country = $geo->lookupCountryName(gethostbyname("www.techrepublic.com"));
echo "IP mapped to: " . $country;

// close database
$geo->close();

// acknowledgement, required by MaxMind
echo "This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/."
?>

And if you'd prefer two-letter country codes instead of names, Net_GeoIP can do that too (Listing C):

Listing C


<?php
// include class
include("GeoIP.php");

// initialize object
// open database
$geo = Net_GeoIP::getInstance("GeoIP.dat");

// look up IP address
$code = $geo->lookupCountryCode("216.239.115.148");
echo "IP mapped to: " . $code;

// close database
$geo->close();

// acknowledgement, required by MaxMind
echo "This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/."
?>

And the output is:

IP mapped to: US

Geographically-targeted advertising

Now that you know the basics, let's try a real-world application: a simple script that displays advertisement banners customized to the user's current geographic location. First, create a directory structure for the banner images, making sure that each directory name corresponds to the standard two-letter country codes, as follows:

images/
            US/
            GB/
            IN/
            ..

Within each directory, place ad banner images specific to that country, numbered in the format xxx.gif. You can have as many banner images as you like (I assume 10 in this example), but the number should be consistent between countries.

Next, create the following PHP script (Listing D) in the top-level directory:

Listing D


<html>
<head></head>
<body>
<p align="center">

<?php
// include class
include("GeoIP.php");

// initialize object
// open database
$geo = Net_GeoIP::getInstance("GeoIP.dat");

// look up IP address
$code = $geo->lookupCountryCode($_SERVER['REMOTE_ADDR']);

// generate random banner number between 1 and 10
$img = sprintf("%03d", rand(1,10));

// retrieve localized banner image and display
echo "<img border=1 src=\"images/$code/$img.gif\">";

// close database
$geo->close();
?>

</p>

-- Page body here --

This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/.

</body>
</html>

This script does the hard work of identifying the client's current location and randomly displaying a banner from the corresponding country directory. Note, however, that unlike previous examples which used a hard-wired IP address, in this case the client's IP address is dynamically retrieved using the special PHP environment variable $_SERVER['REMOTE_ADDR']. This address is then used by the lookupCountryCode() method to identify the client's country and two-letter country code. Next, the rand() function is used to randomly generate a number between 1 and 10, and the corresponding banner image is retrieved and displayed from the country directory with an <img ... /> tag. Finally, the database connection is closed via a call to close().

While this script is somewhat primitive, it should serve to demonstrate the basic idea behind geo-targeted advertising. Play with it a little and drop me a line if you come up with an interesting use for it. Happy coding!

Note: If you plan to use this script on your own site, you will need to refine it, perhaps allowing for a variable number of available images per country and adding business logic to ensure that if the user's country of origin cannot be identified, a default ad banner is used instead. However, these are minor enhancements and should not pose significant problems.

2 comments
andy
andy

Great and clear HowTo. However, a big problem rests for people on shared hosting that cannot install the software. For this I use geoplugin.com (http://www.geoplugin.com/). That provides an interface to the Maxmind database. Easy to use examples and a PHP class.