30.11.2006
Introduction to GeoIP
In case you’ve ever used Google Analytics or any simmilar tool where you can see exact location from where visitors of your site came from, you’ve probably wondered how they were able to dig that info. Is it magic or what? Of course, it’s not kind of magic, exact location of visitor is defined by visitor’s IP address, and technology used to locate user by his IP is well known as GeoIP.
Today we are going to look how to locate visitor of your site with PHP and Max Mind’s GeoIP database. In examples bellow we used free(lite) versions of GeoIP databases, because fully supported GeoIP databases are not free(you’d have to pay $50USD setup + $12USD update for GeoIP Country and $370USD + $90USD for GeoIP City base). Drawback of lite version is that it is not as accurate as fully supported GeoIP databases, but it is still very usefull and probably good enough for great majority of live projects.
MaxMind offer API for dozen of programming languages (full list is available here), details about PHP API are available here. This tutorial deal with so called “Pure PHP API”, there are also PECL extensions and apache mod_geoip modul available. Apache modul provide better perfomance, but Pure PHP API is easier to set up.
Just for a start let’s download all PHP API files from http://www.maxmind.com/download/geoip/api/php/, and save them somewhere inside of your Web tree(let say /htdocs/geoip). To use GeoIP Country you need to download lite database from here, and for GeoLiteCity download database from here. Just for the sake of simplicity, we are going to unpack both bases to the same dir where we saved our PHP API’s files (/htods/geoip in our example).
GeoIP Country
——————————–
Now, let’s see how country detection works:
<?php
/**
* GeoIP Country Database Example
*
* @version $Id$
* @package geoip
* @copyright © 2006 Lampix.net
* @author Dragan Dinic <dinke@lampix.net>
*/
require_once("geoip.inc");
$gi = geoip_open("GeoIP.dat", GEOIP_STANDARD);
$ip = $_SERVER['REMOTE_ADDR'];
//if you test on localhost use IP bellow for test
//since $_SERVER['REMOTE_ADDR'] would be 127.0.0.1
//$ip = "89.216.226.174";
$country_name = geoip_country_name_by_addr($gi, $ip);
$country_code = geoip_country_code_by_addr($gi, $ip);
if($country_name)
{
echo "Your country is: $country_name <br />";
echo "Country Code is: $country_code <br />";
}
else
{
echo "Sorry, we weren't able to locate you.";
}
geoip_close($gi);
?>
So, at the beggining we’ve included geoip.inc which contains all functions needed to use GeoIP country database, then we’ve created new instance of GeoIP class with geoip_open function, and at the end we called proper functions(geoip_country_name_by_addr and geoip_country_code_by_addr) to get country name/code in which detected IP address reside. Again, in case you test localy, don’t use $_SERVER[’REMOTE_ADDR’].
When you run script above you should get something like this as output:
Your country is: Serbia and Montenegro Country Code is: CS
GeoIP City
—————————-
Now, let’s extend visitor’s country data with exact location(like city, postal code etc.)
<?php
/**
* GeoIP City Database Example
*
* @version $Id$
* @package geoip
* @copyright © 2006 Lampix.net
* @author Dragan Dinic <dinke@lampix.net>
*/
require_once("geoipcity.inc");
$gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);
$ip = $_SERVER['REMOTE_ADDR'];
//if you test on localhost use IP bellow for test
//since $_SERVER['REMOTE_ADDR'] would be 127.0.0.1
//$ip = "89.216.226.174";
$record = geoip_record_by_addr($gi, $ip);
if(!$record)
{
echo "Sorry, we weren't able to locate you.";
}
else
{
echo "Country: " .$record->country_name . "<br />";
echo "Country Code: " . $record->country_code . "<br />";
echo "Country Code 2: " . $record->country_code3 . "<br />";
echo "Region: " .$record->region . "<br />";
echo "City: " .$record->city . "<br />";
echo "Postal Code: " .$record->postal_code . "<br />";
echo "Latitude: " .$record->latitude . "<br />";
echo "Longitude: " .$record->longitude . "<br />";
echo "DMA Code: " .$record->dma_code . "<br />";
echo "Area Code: " .$record->area_code . "<br />";
}
geoip_close($gi);
?>
As you see, PHP code is simmilar as in our country detection example, with exception that we used geoipcity.inc and GeoLiteCity.dat database. Function geoip_record_by_addr($gi, $ip) return instance of ‘geoiprecord’ class which contains in it’s properties location’s data we used in our example. After you run script you should get output like this one:
Country: Serbia and Montenegro Country Code: CS Country Code 2: SCG Region: 02 City: Beograd Postal Code: 11000 Latitude: 44.8186 Longitude: 20.4681 DMA Code: Area Code:
CaseStudy - Redirection depending of Country
————————————————————–
At the end, we are going to see some real GeoIP usage. Our goal is to redirect users on multy language site(blog) to proper language section on the site depending of their location. Here is how code looks like on my own blog:
<?php
/**
* Case Study - GeoIP Redirection
*
* @version $Id$
* @package geoip
* @copyright © 2006 Lampix.net
* @author Dragan Dinic <dinke@lampix.net>
*/
require_once("geoip/geoip.inc");
$gi = geoip_open("geoip/GeoIP.dat",GEOIP_STANDARD);
$country_code = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
geoip_close($gi);
if($country_code == 'CS')
{
header("HTTP/1.1 301 Moved Permanently");
header('Location: http://www.dinke.net/blog/sr/');
}
else
{
header("HTTP/1.1 301 Moved Permanently");
header('Location: http://www.dinke.net/blog/en/');
}
?>
Above example is used on this blog in order to redirect all users located out of Serbia to english version of the blog. Sending custom 301 redirection headers is important so bots(like google etc. google) are able to index blog pages without problems.

good tutorial, thanks. i have to try…
Great Tutorial.
I was ready to hurt someone as i could just not get it working.
Read the your tut and 2 mins later i have a GeoIP redirecting.
Thx
dinke, thanks for this great tutorial. but now, because i’m a newbie, so i don’t know how to figure out to detect commenter’s city, flag and country in my wordpress blog’s comment area. i just know the wordpress’s php function to detect/displaying commenter’s ip using
$comment->comment_author_IP or comment_author_IP!i wanna the output like this one:
comment from: city flag country
i’ve asked in wordpress support forum, but there’s no people know to do that. once again, i’m a newbie, so please be patient. :) please tell me the way.
[…] […]
Cool, I am looking for it long time, it is very happy to see it.
The Redirection depending of Country does not work :S
It redirects all surfers depending the country they are.
Anyone knows why?
yep, redirect does not work, I am in Serbia and I see the English version or this blog. oops!
Redirection works just fine for me, I am on SBB Network. Either your ISP IP is not listed in free db or you’re gengo cookie (plugin used for dual language blog) is set to english so you are always redirected to english version.
Just tested country code on my own server and got the same output as in time I wrotte this article:
Your country is: Serbia and Montenegro
Country Code is: CS
See for yourself:
http://www.dinke.net/geoip/country_test.php
Geoip country works for me, but i cant get geolite city to work no matter what i do. I have all the required files for it to work.
Oh, I found my mistake. I named geolite city, geoipcity.dat.