1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

GEO Targeting Made EASY! (For PHP)

Discussion in 'PHP' started by KLB, Mar 22, 2007.

  1. #1
    Okay I've seen many threads with people wanting to easily implement geo targeting on their website for things like Yahoo. Well over the past several days I had worked on developing a really simple to implement geo targeting script that does not require module installs or MySQL. Since I figured others could benefit from my efforts, I thought I'd share my methods with folks here. The strengths of my methodology is that it does not require a database server as it works from a CSV file, It only requires adding one function to your site AND it is FREE.

    Step 1) download a current IP "database" from http://software77.net/cgi-bin/ip-country/geo-ip.pl. There is a link to download the database part way down the right hand side of the page.

    Step 2) extract the CSV file to a folder on your website.

    Step 3) add the following function to your website scripts (I placed it in my "functions.inc" include). I should note that this function is based on ideas presented on http://webnet77.com/scripts/geo-ip/index.html and http://www.php.net/manual/en/function.fseek.php. The idea is to create a fully binary search that uses as little server processor time as possible while still storing the IP data in a flat file that could be easily updated (any suggested improvements would be appreciated):
    	function ipcountrycode($ip){
    		$ip=ip2long($ip);
    
    		$low = 130;
    
    		// Open the csv file for reading
    		$csvfilename="ip2country.csv"; // Change to proper filename and path.
    		$fp = fopen($csvfilename, "r");
    		fseek($fp, 75000, SEEK_END);
    		$high = ftell($fp);
    		
    		while ($low <= $high) {
    			$mid = floor(($low + $high) / 2); // C floors for you
    			
    			//Seek to half way through
    			fseek($fp, $mid);
    			
    			// Moves to proper line
    //			if($mid != 0){
    				$line=fgets($fp);
    //				}
    
    			// Read line
    			$line=fgets($fp);
    			$line = str_replace("\"", "",$line);
    			$ipdata = explode(",",$line);
    			if ($ip >=$ipdata[0] && $ip<=$ipdata[1]){
    				$low=$high+1;
    				}
    			elseif($ip >=$ipdata[0]){
    				$low = $mid + 1;
    				}
    			else {
    				$high = $mid - 1;
    				}
    			}
    		fclose($fp);
    		$line="";
    		return $ipdata[4];
    		}
    Code (markup):
    Step 4) Call the above function from the top of the script and store the user's two digit country code in a string that can be referenced where needed:
    	$strCountryCode=ipcountrycode($REMOTE_ADDR);
    Code (markup):
    The ipcountrycode function should really only be called once per page load and stored in a string variable for use throughout the script to reduce server overhead.To further reduce server load, the the code in step four could be replaced with the following code, which sets the geo location information into a cookie that expires after say seven days:
    	if(strlen(addslashes($_COOKIE['GeoLocation']))==2){ 
    		$strCountryCode=$_COOKIE['GeoLocation'];
    		}
    	else{
    		$strCountryCode=ipcountrycode($REMOTE_ADDR);
    
    		//	Sets cookie for geo location.
    		$HostDomain=str_replace("http://","",$_SERVER['HTTP_HOST']);
    		$SetCookieExpire=mktime() +604800; //Set cookie for one week
    		setcookie ("GeoLocation", $strCountryCode, $SetCookieExpire, "/", $HostDomain, 0) ;
    		}
    Code (markup):
    This has the disadvantage that users could muck with the cookie, but it would also eliminates the need to run the ipcountrycode function after the first page view, which reduces server load. If one really needed to ensure the integrity of cookie, the country code could be encrypted using a hash with half of the salt for the hash being in the cookie and the other half being hard coded into the script. As always if relying on the cookie, make sure to validate the string before feeding it into a SQL query.

    There you have it, a very simple and very clean way to get the country code of your users to do things like geo target ads. Oh make sure to periodically download updates to the IP CSV file so that your targeting remains as accurate as possible.
     
    KLB, Mar 22, 2007 IP
    streety and Ritu like this.
  2. KLB

    KLB Peon

    Messages:
    1,167
    Likes Received:
    68
    Best Answers:
    0
    Trophy Points:
    0
    #2
    I discovered a couple of errors that were causing some IP addresses not tor return country codes. :( I have fixed those errors and the following function should be used instead of the function above:
    	function ipcountrycode($ip){
    		// convert IP to decimal
    		$ip=sprintf("%u", ip2long($ip));
    
    		// set initial low
    		$low = 0;
    
    		// Open the csv file for reading
    		$csvfilename="ip2country.csv"; // Change to proper filename and path for IP dataset.
    		$fp = fopen($csvfilename, "r");
    
    		// Set initial high
    		fseek($fp, 0, SEEK_END);
    		$high = ftell($fp);
    
    		while ($low <= $high) {
    			$mid = floor(($low + $high) / 2); // C floors for you
    			
    			//Seek to half way through
    			fseek($fp, $mid);
    			
    			// Moves to end of line
    			if($mid != 0){
    				$line=fgets($fp);
    				}
    
    			// Read line
    			$ipdata=fgetcsv($fp,100);
    
    			if ($ip >=$ipdata[0] && $ip<=$ipdata[1]){
    				$low=999999999;
    				}
    			elseif($ip >$ipdata[0]){
    				$low = $mid + 1;
    				}
    			else {
    				$high = $mid - 1;
    				}
    			}
    		fclose($fp);
    		$line="";
    		return $ipdata[4];
    		}
    Code (markup):
    The primary error was in how IP addresses were turned into integers. Apparently PHPs ip2long() function sometimes returns a negative integer, which had to be adjusted. I also took the opportunity to streamline some pieces of code to try and reduce processor requirements.
     
    KLB, Mar 23, 2007 IP
  3. timelf123

    timelf123 Peon

    Messages:
    897
    Likes Received:
    24
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Cool! Thanks for this!
     
    timelf123, Mar 23, 2007 IP
  4. 3l3ctr1c

    3l3ctr1c Peon

    Messages:
    380
    Likes Received:
    14
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Thank you very much for this! Will surely test this out!
     
    3l3ctr1c, Mar 24, 2007 IP