- Jul. 21st, 2006
- 4 comments
This class can be used to detect where a site visitor is located and tailor their page content accordingly. For example, you may want to say "We surrender!" for French users, instead of the usual "Hello." No offense to Frenchies of course; but I had to poke some fun to make this post less dry
To do this, we need to include this class in our application; the code below the class definition implements the aforementioned example. Many thanks to MaxMind for providing their free database; additionally, they have a better, more accurate version for a fee. Keep in mind that although this code automatically updates only after 30 days (not every time you call the "updateDB()" function, it downloads a rather large file. This will cause a delay for that first user who hits your site after 30 days. You are better off cronning the job instead. In any case — happy programming!
<?
/*
// +———————————————————————-+
// | SimpleGeoTarget |
// | Class for targeting content for specific geographical regions |
// | http://www.SEOEgghead.com/ |
// +———————————————————————-+
// | Copyright (c) 2004-2006 Jaimie Sirovich |
// +———————————————————————-+
// | This program is free software; you can redistribute it and/or |
// | modify it under the terms of the GNU General Public License |
// | as published by the Free Software Foundation; either version 2 |
// | of the License, or (at your option) any later version. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU General Public License for more details. |
// | |
// | You should have received a copy of the GNU General Public License |
// | along with this program; if not, write to the Free Software |
// | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
// +———————————————————————-+
// | Author: Jaimie Sirovich <jsirovic@gmail.com> |
// +———————————————————————-+
SCHEMA:
CREATE TABLE `simple_geo_target` (
`id` int(11) NOT NULL auto_increment,
`start_ip_text` varchar(15) collate latin1_general_ci NOT NULL default '',
`end_ip_text` varchar(15) collate latin1_general_ci NOT NULL default '',
`start_ip_numeric` bigint(20) NOT NULL default '0',
`end_ip_numeric` bigint(20) NOT NULL default '0',
`country_code` char(2) collate latin1_general_ci NOT NULL default '',
`country_name` varchar(50) collate latin1_general_ci NOT NULL default '',
`date_updated` date default NULL,
PRIMARY KEY (`id`),
KEY `start_ip_numeric` (`start_ip_numeric`,`end_ip_numeric`),
KEY `country_code` (`country_code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
*/
class SimpleGeoTarget
{
function insert($info)
{
if (class_exists('DB')) {
return DB::insert('simple_geo_target', $info);
} else {
$table_name = 'simple_geo_target';
$names = array();
$values = array();
foreach ($info as $name => $value) {
$names[] = $name;
$values[] = "'" . mysql_real_escape_string($value) . "'";
}
$implode_names = implode(",", $names);
$implode_values = implode(",", $values);
$q = " INSERT INTO " . $table_name . " ($implode_names) VALUES ($implode_values) ";
$tmp = mysql_query($q);
if ($tmp) {
return ($id = mysql_insert_id()) ? $id : false;
} else {
return false;
}
}
}
function update($id, $info)
{
if (class_exists('DB')) {
return DB::update('simple_geo_target', $id, $info);
} else {
// We don't use update here, so I won't do this one.
}
}
function delete($id, $key_name = 'id')
{
if (class_exists('DB')) {
return DB::delete('simple_geo_target', $id, $key_name);
} else {
$table_name = 'simple_geo_target';
if (!$id) return false;
$q = " DELETE FROM " . $table_name . " WHERE ";
$q .= $key_name . ' = ' . "'" . mysql_real_escape_string($id) . "'";
$tmp = mysql_query($q);
return mysql_affected_rows();
}
}
function purgeWholeTable()
{
if (class_exists('DB')) {
return DB::purgeWholeTable('simple_geo_target');
} else {
$table_name = 'simple_geo_target';
$q = " DELETE FROM " . $table_name;
$tmp = mysql_query($q);
return mysql_affected_rows();
}
}
function getOldestDate()
{
$q = " SELECT MIN(date_updated) AS `0` FROM simple_geo_target ";
if (class_exists('DB')) {
return DB::queryOneVal($q);
} else {
$tmp = mysql_fetch_assoc(mysql_query($q));
return $tmp[0];
}
}
function get($id = 0, $start_ip_text = '', $end_ip_text = '', $start_ip_numeric = 0, $end_ip_numeric = 0, $country_code = '', $country_name = '',
$test_ip_value = '', $date_updated_begin = '', $date_updated_end = '', $order = '', $order_asc = '', $hash_col = '')
{
if (class_exists('DB')) {
$q = " SELECT simple_geo_target.* FROM simple_geo_target WHERE TRUE ";
if ($id)
$q .= DB::cond('id', $id);
if ($start_ip_text)
$q .= DB::cond('start_ip_text', $start_ip_text);
if ($end_ip_text)
$q .= DB::cond('end_ip_text', $end_ip_text);
if ($start_ip_numeric)
$q .= DB::cond('start_ip_numeric', $start_ip_numeric);
if ($end_ip_numeric)
$q .= DB::cond('end_ip_numeric', $end_ip_numeric);
if ($country_code)
$q .= DB::cond('country_code', $country_code);
if ($country_name)
$q .= DB::cond('country_name', $country_name);
if ($test_ip_value) {
$test_ip_value = ip2long($test_ip_value);
$q .= ' AND ( ' . ' start_ip_numeric ' . ' <= ' . $test_ip_value . ' AND ' . ' end_ip_numeric ' . ' >= ' . $test_ip_value . ' ) ';
}
$q .= DB::queryDateRange('date_updated', $date_updated_begin, $date_updated_end);
$q .= DB::orderBy($order, $order_asc);
return DB::queryRows($q, $hash_col);
} else {
$q = " SELECT simple_geo_target.* FROM simple_geo_target WHERE TRUE ";
if ($id) {
$id = (int) $id;
$q .= " AND id = $id ";
}
if ($start_ip_text) {
$start_ip_text = mysql_real_escape_string($start_ip_text);
$q .= " AND start_ip_text = '$start_ip_text' ";
}
if ($end_ip_text) {
$end_ip_text = mysql_real_escape_string($end_ip_text);
$q .= " AND end_ip_text = '$end_ip_text' ";
}
if ($start_ip_numeric) {
$start_ip_numeric = (int) $start_ip_numeric;
$q .= " AND start_ip_numeric = $start_ip_numeric ";
}
if ($end_ip_numeric) {
$end_ip_numeric = (int) $end_ip_numeric;
$q .= " AND end_ip_numeric = $end_ip_numeric ";
}
if ($country_code) {
$country_code = mysql_real_escape_string($country_code);
$q .= " AND country_code = '$country_code' ";
}
if ($country_name) {
$country_name = mysql_real_escape_string($country_name);
$q .= " AND country_name = '$country_name' ";
}
if ($test_ip_value) {
$test_ip_value = sprintf("%u", ip2long($test_ip_value));
$q .= ' AND ( ' . ' start_ip_numeric ' . ' <= ' . $test_ip_value . ' AND ' . ' end_ip_numeric ' . ' >= ' . $test_ip_value . ' ) ';
}
// the rest is unimplemented, because we don't use it.
$tmp = mysql_query($q);
$rows = array();
while ($_x = mysql_fetch_assoc($tmp)) {
$rows[] = $_x;
}
return $rows;
}
}
function get1($id)
{
if (class_exists('DB')) {
return DB::get1(SimpleGeoTarget::get($id));
} else {
$tmp = SimpleGeoTarget::get($id);
return current($tmp);
}
}
function updateDB($do_duration_check = true, $duration = '-10 days', $last_check_filename = '')
{
// Do not set $do_duration_check to false unless you are cronning it!
if ($do_duration_check) {
if (!$last_check_filename) {
$last_check_filename = '/tmp/_simple_geo_target_' . md5($_SERVER['HTTP_HOST']);
}
$last_check = @file_get_contents($last_check_filename);
}
if (!$do_duration_check || ($last_check < strtotime($duration))) {
SimpleGeoTarget::_importDB(SimpleGeoTarget::_getGeoDB());
$f = fopen($last_check_filename, 'w');
if (!fputs($f, time())) {
echo 'ERROR: Cannot write to SimpleGeoTarget last check file ' . $last_check_filename . ' in current working directory of ' . getcwd();
exit();
}
}
}
function getRegion($ip)
{
$tmp = SimpleGeoTarget::get(0, '', '', 0, 0, '', '', $ip);
if (class_exists('DB')) {
return DB::get1($tmp);
} else {
return current($tmp);
}
}
function isRegion($country_code, $current_ip = '')
{
if (!$current_ip) {
$current_ip = $_SERVER['REMOTE_ADDR'];
}
$tmp = SimpleGeoTarget::getRegion($current_ip);
return ($tmp['country_code'] == $country_code);
}
function _getGeoDB()
{
ini_set("memory_limit", "100M");
$tmp_filename = tempnam('/tmp', 'GEO_');
$tmp_file_handle = fopen($tmp_filename, 'w+');
fwrite($tmp_file_handle, file_get_contents('http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip'));
$zip = zip_open($tmp_filename);
if ($zip) {
$zip_entry = zip_read($zip);
if (zip_entry_open($zip, $zip_entry, "r")) {
$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
} else {
return false;
}
}
zip_close($zip);
fclose($tmp_file_handle);
unlink($tmp_filename);
return $buf;
}
function _importDB($buf)
{
ini_set("memory_limit", "100M");
$tmp_filename = tempnam('/tmp', 'GEO_');
$tmp_file_handle = fopen($tmp_filename, 'w+');
fwrite($tmp_file_handle, $buf);
rewind($tmp_file_handle);
if (class_exists('DB')) {
DB::query('LOCK TABLES simple_geo_target WRITE');
} else {
mysql_query('LOCK TABLES simple_geo_target WRITE');
}
SimpleGeoTarget::purgeWholeTable();
$update_time = (class_exists('DB') ? DB::unixToSQL(time()) : date('Y-m-d', time()));
while (($data = fgetcsv($tmp_file_handle, 10000, ",")) !== false) {
SimpleGeoTarget::insert(array('start_ip_text' => $data[0], 'end_ip_text' => $data[1], 'start_ip_numeric' => $data[2],
'end_ip_numeric' => $data[3], 'country_code' => $data[4], 'country_name' => $data[5], 'date_updated' => $update_time));
}
if (class_exists('DB')) {
DB::query('UNLOCK TABLES');
} else {
mysql_query('UNLOCK TABLES');
}
fclose($tmp_file_handle);
unlink($tmp_filename);
}
}
$_SERVER['REMOTE_ADDR'] = '160.92.103.98';
SimpleGeoTarget::updateDB();
if (SimpleGeoTarget::isRegion('FR')) {
echo 'We surrender!';
} else {
echo 'Hello.';
}
?>
Related posts:
"4 Wise Comments Banged Out Somewhere On The Internet ..."» Increase AdSense Revenue by 800% in Just 10 Minutes - Part 2 » $250/Day » Blog Archive[...] While looking for ways to improve on the Translation Gold script I found a nice little Geo Targeting PHP script that (with a little tweaking), when used in conjunction with Translation Gold, allows you to automatically offer your site in the relevant language of the person viewing your site based on their country of origin [...] Simple GeoTarget PHP Library at Sandboxing[...] SEO Egghead » Blog Archive » Simple GeoTarget PHP Library - This class can be used to detect where a site visitor is located and tailor their page content accordingly. For example, you may want to say "We surrender!" for French users, instead of the usual "Hello." No offense to Frenchies of course; but I had to poke some fun to make this post less dry [...] Uwe tippt. » GeoTargeting und so[...] Brauch man ja immer mal - etwas Cloaking, um den Engländer vom Deutschen anhand der IP zu unterscheiden. Mit waaas man file_get_contents regelmäsig füttert, bleibt ja jedem selbst überlassen… [...]
|
















