How to Display Unique Content Based on Geolocation

Unique Content and Geolocation

Unique Content and GeolocationWikipedia defines geolocation as “the identification of the real-world geographic location of an object, such as a radar, mobile phone or an Internet-connected computer terminal.” Obviously in our example we will be referring to the Internet-connected computer terminal. While there is a simple way to establish geolocation by using the Geolocation API (which we have already written about on this blog), it requires the visitor through a browser prompt to allow the website to access that information. Furthermore, the Geolocation API is only available to Internet Explorer 9 and up. With our more compatible method, we are able to skip the prompt and automatically implement our unique data. This tutorial will teach you how to serve unique content to visitors within a 50 mile radius of a certain city. We will use PHP and JSON but will not require intimate knowledge of either.

First and foremost, we need to find our visitor’s IP address which we can do with this simple request:

<?php $ip = $_SERVER['REMOTE_ADDR']; ?>

Next we need to use the IP address to find out more about our visitor. We can do that by using http://www.freegeoip.net/, a public web service for searching geolocation of IP addresses and host names. We make a JSON request to them with the following code:

<?php
$url = "http://freegeoip.net/json/" . $ip;
$json = file_get_contents($url);
$data = json_decode($json, TRUE);
?>

The file_get_contents($url) function gets the contents of the url, which is http://freegeoip.net/json/whatever-ip-address-our-visitor-has. If you were to visit that website using your IP address you would see all sorts of nifty information about you, including your city, state, zipcode and more. Since it is listed in JSON format, we use the json_decode function to pass the data into a variable.

Next, we need to pass our visitor’s city and state into variables:

<?php $city = print_r($data['city'], true); ?>
<?php $state = print_r($data['region_code'], true); ?>

Since the JSON data is in an array, we need to use the print_r() function to extract the individual city. Since we want to store the data in a variable, we use the return parameter by setting the second value of the print_r() function to true. At this point, you now have the city of your visitor stored in the variable $city. We also got the region code for the state because a lot of towns and cities do not have unique names (ie: Portland, Oregon and Portland, Maine).

Note: The reason I cross reference by city, state is because in testing, those were always returning with a value. Zipcode was not. While I found it simpler to find all zipcodes in a radius, I had to go the extra step to ensure my script would always work. I was not able to find a faster, more accurate process to find all the cities, but if you know of one please write and let me know! Now we need to get a list of all towns and cities in a 50 mile radius of our desired location. Our tutorial example will be Dallas, TX. First, lets get the zipcodes. There are several sites we can use, but I found a wonderful one at http://www.freemaptools.com/find-zip-codes-inside-radius.htm which puts our zip codes in CSV format. We will go there and put in our Dallas zipcode ‘75001’ and set the radius to 50 miles. This gives us 401 results. Wow! Fortunately we do not have to look these cities up one zipcode at a time. I found another great website at http://pp19dd.com/zipcode-lookup/ to do it for us. Copy and paste those zipcodes into a text file and upload it to that website. It will give you a download of those zipcodes formatted in a .CSV document. Next, arrange those files in the .CSV to be all in one column. (I used this tutorial since I am no Excel wiz: http://office.microsoft.com/en-us/excel-help/rotate-data-by-converting-columns-to-rows-or-vice-versa-HP005203138.aspx). After they are in one column, save it as a new file and upload that new file to the same website. You will receive an output file with cities attached to each of those zipcodes. Format that data (Delete duplicates, order A->Z, put on one line) and put it in your code as such:

<?php
$dallas_cities_in_50_mile_radius = "Addison Allen Alvarado Anna Argyle Arlington Aubrey Azle Bailey Balch Springs Bedford Benbrook Blue Ridge Boyd Burleson Caddo Mills Carrollton Carswell Afb Cedar Hill Celeste Celina Cockrell Hill Colleyville Collinsville Copeville Coppell Crandall Crowley Dallas De Soto Decatur Denton Duncanville Ennis Era Euless Everman Farmers Branch Farmersville Fate Ferris Flower Mound Forney Forreston Fort Worth Frisco Garland Grand Prairie Grapevine Greenville Gunter Haltom City Haslet Heath Highland Village Howe Hurst Hutchins Irving Josephine Joshua Justin Kaufman Keller Kennedale Krum Lake Dallas Lakewood Village Lancaster Lavon Leonard Lewisville Lillian Lindsay Mansfield Maypearl Mc Kinney Melissa Mesquite Midlothian Murphy Nevada Newark North Richland H Ovilla Palmer Pilot Point Plano Ponder Princeton Prosper Quinlan Randolph Rhome Rice Richardson River Oaks Rockwall Rowlett Royse City Sachse Saginaw Sanger Scurry Seagoville Sherman Southmayd Terrell The Colony Tioga Tom Bean Trenton Trophy Club Valley View Van Alstyne Venus Village Watauga Waxahachie Westminster White Settlement Whitewright Wilmer Wylie";
?>

Now we’re ready to cross reference our visitor’s city and state with our list of cities in the 50 mile radius. This is very simple:

<?php
if ((strpos($dallas_cities_in_50_mile_radius,$city) !== false) AND ($state == "TX")) {
    echo 'Visitor is within 50 miles of Dallas, TX';
}
else {
    echo 'Visitor is not within 50 miles of Dallas, TX';
}
?>

Using the strpos() function, we reference the visitor’s location against our list of all towns and cities in the 50 mile radius as well as make sure their state is the same. We then echo out our unique content based on whether or not they fall within that 50 mile radius. Here is the code all together:

<?php 
$ip = $_SERVER['REMOTE_ADDR'];
$url = "http://freegeoip.net/json/" . $ip;
$json = file_get_contents($url);
$data = json_decode($json, TRUE);
$city = print_r($data['city'], true);
$state = print_r($data['region_code'], true);
$dallas_cities_in_50_mile_radius = "Addison Allen Alvarado Anna Argyle Arlington Aubrey Azle Bailey Balch Springs Bedford Benbrook Blue Ridge Boyd Burleson Caddo Mills Carrollton Carswell Afb Cedar Hill Celeste Celina Cockrell Hill Colleyville Collinsville Copeville Coppell Crandall Crowley Dallas De Soto Decatur Denton Duncanville Ennis Era Euless Everman Farmers Branch Farmersville Fate Ferris Flower Mound Forney Forreston Fort Worth Frisco Garland Grand Prairie Grapevine Greenville Gunter Haltom City Haslet Heath Highland Village Howe Hurst Hutchins Irving Josephine Joshua Justin Kaufman Keller Kennedale Krum Lake Dallas Lakewood Village Lancaster Lavon Leonard Lewisville Lillian Lindsay Mansfield Maypearl Mc Kinney Melissa Mesquite Midlothian Murphy Nevada Newark North Richland H Ovilla Palmer Pilot Point Plano Ponder Princeton Prosper Quinlan Randolph Rhome Rice Richardson River Oaks Rockwall Rowlett Royse City Sachse Saginaw Sanger Scurry Seagoville Sherman Southmayd Terrell The Colony Tioga Tom Bean Trenton Trophy Club Valley View Van Alstyne Venus Village Watauga Waxahachie Westminster White Settlement Whitewright Wilmer Wylie";

if ((strpos($dallas_cities_in_50_mile_radius,$city) !== false) AND ($state == "TX")) {
    echo 'Visitor is within 50 miles of Dallas, TX';
}
else {
    echo 'Visitor is not within 50 miles of Dallas, TX';
}
?>

That is it!

Note: The website http://freegeoip.net/ is a free service and as such has a max 10,000 lookups across all users per hour. Fortunately it is open source and you can set it up on your webserver if you ever get the dreaded Error 403 Forbidden! The other free website tools I used to aid me in my tutorial were found with simple google searches. If for any reason these services cease to exist in the future, I have no doubt newer and better ones will replace them. You will just have to search for them. And I suppose a disclaimer is in line: IP address lookups are not perfect and will sometimes list inaccurate information. Using a 50 mile radius is a pretty big net however and will more than likely catch your visitor.

2 Comments
  1. remi says:

    very cool ! great usage of a free tool to implement geolocalized content !
    how would you handle the cloaking aspect (from a seo standpoint) ?

  2. GP says:

    I believe you are talking about a topic that is important especially nowadays when it is important to be social’n’local but I will like to point you on a different direction especially because it’s known that freegeoip has limits, not only speaking about number of queries but it may be not accurate.

    So, what’s next, you will ask…

    Well, you may know for sure that FreeGeoIP works using mainly GeoLite database from MaxMind, and a serious business company will prefer to buy a the “Pro” version directly from their database that it’s way much more accurate than their lite version.

    It’s also true that opensource and/or free is even better than paying so maybe another alternative is to use the already PHP and Pear functions that will allow you to get the location of a visitor without affecting also the performance of your website. Yes, each query it may cost precious ms or seconds during the loading and MaxMind won’t allow you to cache or store the IP locations in a database at is against their TOS.

    But if you are lucky enough to work with dedicated servers or VPS you may create your own database of locations (and then maybe selling it) by using the whois functions installed in each server.

    WhoIS is not just for domain but it’s used indeed to gather useful information about generally all that is a network address, for example:

    By querying: whois 64.XXX.XX.XX

    What you will obtain are correct informations about an IP address, updated almost everyday by the IP range owners:

    OrgName: Network Operations Center Inc.
    OrgId: NOC
    Address: PO Box 591
    City: Scranton
    StateProv: PA
    PostalCode: 18501-0591
    Country: US

    Then what you need to do is simply preg_match and taking the provided information and store them in a database, then creating contents for various radius that you will store in a multidimensional array (so you can work with different states instead of using different if/else statements) and showing customized contents maybe using SR tags that you can change on the flight by using just str_replace.

Recent Blog Posts in Local SEO, Web Development
My First Professional Website Launch On November 1, 1996, 20 years ago today, Bob Whitset and I launched the Cyrix Corporation website. As a team we convinced Cyrix that they could not...
Starting a new business in Dallas isn’t for the faint of heart. You’ve chosen a challenging market, but with great challenges come even greater rewards and we have had the pleasure of helping...
Have you heard about Facebook Services? Is this another step toward their quest of local search domination? You may have even glanced at the landing page and thought, “Yeah, yeah, another search...