<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Che Hodgins &#187; geolocation</title>
	<atom:link href="http://www.chehodgins.com/category/geolocation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.chehodgins.com</link>
	<description>Musings on Web Development</description>
	<lastBuildDate>Tue, 24 Nov 2009 02:39:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Advanced Geolocation</title>
		<link>http://www.chehodgins.com/web/advanced-geolocation/</link>
		<comments>http://www.chehodgins.com/web/advanced-geolocation/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 04:43:05 +0000</pubDate>
		<dc:creator>chehodgins</dc:creator>
				<category><![CDATA[geolocation]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://www.chehodgins.com/?p=295</guid>
		<description><![CDATA[I write this in honor of the Firefox web browser. I still remember when it was first released November 9th, 2004, and gave me hope for a better, nicer, non-IE world. Today, Firefox 3.5 is released. Building upon nearly 5 years of success, they have continued innovating and I thank them for making the web [...]]]></description>
			<content:encoded><![CDATA[<p>I write this in honor of the Firefox web browser. I still remember when it was first released November 9th, 2004, and gave me hope for a better, nicer, non-IE world. Today, Firefox 3.5 is released. Building upon nearly 5 years of success, they have continued innovating and I thank them for making the web a better place.</p>
<p>Feel free to <a href="http://www.chehodgins.com/geo.html">Skip to the demo</a>.</p>
<p>I <a href="http://www.chehodgins.com/php/free-and-fast-geolocation-in-php/">previously wrote</a> about using IP based Geolocation. Although this method is widely used, the downsides are obvious: inaccurate results, proxies, false positives, and a lack of privacy control for the end user. </p>
<p><strong>The Future of Geolocation</strong></p>
<p>The new generation of browsers are implementing the <a href="http://dev.w3.org/geo/api/spec-source.html">Geolocation API specification</a>. This gives the browser the job of figuring out where you are. There are some positive points and negative points to this. Firstly, the position of the user can be more accurate. In IP-based Geolocation, the only data available is the IP address. The browser has access to much more precise data such as WiFi networks and GPS devices (iPhone!). Secondly, privacy settings. The browser should be able to ask the user if they will allow such information to be shared, ideally even the level of accuracy that should be shown. This is possible if implemented in the browser. One negative point is something we are all familiar with: cross-browser compatibility. Different implementations in different web browser will make developers miserable, but hey, that&#8217;s what standards are for, right? <img src='http://www.chehodgins.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Browser Support</strong></p>
<p>As of today a few web browsers support geolocation. Here&#8217;s the status of the mainstream browsers:</p>
<ul>
<li>Firefox: Available in version 3.5, released today.</li>
<li>iPhone Safari: Available in OS3.</li>
<li>IE: Experimental in version 8.</li>
<li>Opera: Available in <a href="http://labs.opera.com/news/2009/03/26/">nightly builds</a> since March 2009.</li>
<li>Chrome: Available through <a href="http://veerasundar.com/blog/2009/06/coming-up-in-html5-geolocation-api-support-in-browsers/">Google Gears API</a></li>
<li>Safari: Unknown.</li>
</ul>
<p>Here is how to request a users location (see line 26 for the goods):</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:500px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> knownLocation<span style="color: #009900;">&#40;</span>position<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> latitude<span style="color: #339933;">,</span> longitude<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>position.<span style="color: #660066;">coords</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// iPhone</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; latitude <span style="color: #339933;">=</span> position.<span style="color: #660066;">coords</span>.<span style="color: #660066;">latitude</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; longitude <span style="color: #339933;">=</span> position.<span style="color: #660066;">coords</span>.<span style="color: #660066;">longitude</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">// Firefox</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; latitude <span style="color: #339933;">=</span> position.<span style="color: #660066;">latitude</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; longitude <span style="color: #339933;">=</span> position.<span style="color: #660066;">longitude</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> div <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'geo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;Latitude: &quot;</span> <span style="color: #339933;">+</span> latitude <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;br/&gt;Longitude: &quot;</span> <span style="color: #339933;">+</span> longitude<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">function</span> unknownLocation<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> div <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'geo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;Unknown Location&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
window.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> div <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'geo'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;Browser: &quot;</span> <span style="color: #339933;">+</span> navigator.<span style="color: #660066;">appName</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot; (&quot;</span> <span style="color: #339933;">+</span> navigator.<span style="color: #660066;">appVersion</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;)&lt;br/&gt;&quot;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>navigator.<span style="color: #660066;">geolocation</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; navigator.<span style="color: #660066;">geolocation</span>.<span style="color: #660066;">getCurrentPosition</span><span style="color: #009900;">&#40;</span>knownLocation<span style="color: #339933;">,</span> unknownLocation<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> div.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;Browser not supported&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>This then prompts the user for their approval:</p>
<p><a href="http://www.chehodgins.com/wp-content/uploads/2009/06/firefox3.5_geolocation.png"><img src="http://www.chehodgins.com/wp-content/uploads/2009/06/Picture-1-1024x139.png" alt="Geolocation in Firefox 3.5" title="Geolocation in Firefox 3.5" width="1024" height="139" class="aligncenter size-large wp-image-313" /></a></p>
<p>Similarly, on the iPhone:</p>
<p><img alt="" src="http://farm4.static.flickr.com/3620/3673686739_65c1cae92f.jpg?v=0" title="Geolocation on iPhone Safari" class="alignnone" width="320" height="480" /></p>
<p><strong>Conclusion</strong></p>
<p>This is really cool. With geolocation implemented in the browser, great precision can be achieved. For example, on the iPhone the GPS is used, so visiting the <a href="http://www.chehodgins.com/geo.html">demo page</a> from my living room gives different coordinates than when visiting from my kitchen. I can imagine many useful applications of this. Another thing I love is that I can deny my location to certain sites, which I will absolutely use on certain sites.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.chehodgins.com/web/advanced-geolocation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Free and Fast Geolocation in PHP</title>
		<link>http://www.chehodgins.com/php/free-and-fast-geolocation-in-php/</link>
		<comments>http://www.chehodgins.com/php/free-and-fast-geolocation-in-php/#comments</comments>
		<pubDate>Thu, 21 May 2009 12:08:24 +0000</pubDate>
		<dc:creator>chehodgins</dc:creator>
				<category><![CDATA[geolocation]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[geoip]]></category>

		<guid isPermaLink="false">http://www.chehodgins.com/?p=246</guid>
		<description><![CDATA[
table#benchmarks {
   border: 1px solid black;
}
table#benchmarks td,th {
   padding: 4px;
   border: 1px solid black;
}

Geo* (as I call them) are the web technologies that provide a link between online content and Earth&#8217;s geography. Examples includes Geocoding (finding latitude/longitude based on street addresses), Geotagging (tagging media with latitude/longitude coordinates), and Geolocation [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">
table#benchmarks {
   border: 1px solid black;
}
table#benchmarks td,th {
   padding: 4px;
   border: 1px solid black;
}
</style>
<p>Geo* (as I call them) are the web technologies that provide a link between online content and Earth&#8217;s geography. Examples includes Geocoding (finding latitude/longitude based on street addresses), Geotagging (tagging media with latitude/longitude coordinates), and Geolocation (finding latitude/longitude of a computer).</p>
<p>Geolocation is a particularly cool technique because it allows you to estimate a person&#8217;s geographic location, thus allowing you to provide a custom tailored experience on your website, among other things. This can be <a href="http://www.google.com/latitude/intro.html">useful</a> as much as it can be <a href="http://www.hulu.com/support/geofilter">annoying</a>. There are several methods of Geolocation, some as simple as asking the user where they are located. This article focuses on adding IP based Geolocation to your PHP website for free all the while keeping it fast.</p>
<p><strong>Problems</strong></p>
<p>If IP addresses are to be used to determine a persons physical location then a few possible problems come to mind:</p>
<ul>
<li>How accurate is the mapping between an IP address and a geographical location?
<ul>
<li>From maxmind.com&#8217;s Geolocation service: &#8220;99.8% accurate on a country level, 90% accurate on a state level, and 83% accurate for the US within a 25 mile radius.&#8221;. Doing some research, the matching is done using either the address of the ISP that owns that IP [<a href="http://www.zipwise.com/geomap/geotargeting-database.php">link</a>], or by buying the data from websites that ask for users locations [<a href="http://www.maxmind.com/app/faq#accurate">link</a>].</li>
</ul>
</li>
<li>What about users behind proxies?
<ul>
<li>Some Geolocation databases <a href="http://www.maxmind.com/app/faq#anonproxy">flag</a> the IPs of potential anonymous proxy servers.</li>
<li><a href="http://en.wikipedia.org/wiki/X-Forwarded-For#Proxy_servers_and_caching_engines">Most proxy servers</a> send X-Forwarded-For and Client-IP headers that you can use.</li>
</ul>
</li>
</ul>
<p>This is <a href="http://stefan.rusek.org/Posts/Don-t-use-IP-geolocation-to-lock-out-users/9/">not perfect</a>, but in many cases the approximate geographical location of a user can be inferred.</p>
<p><strong>Demo time</strong></p>
<p>This demo will use the free Geolocation database provided by Maxmind.com. I believe this is the ideal choice for normal (i.e. not Facebook) websites for several reasons:</p>
<ul>
<li>It is free (there is a paid version with higher accuracy)</li>
<li>It is fast. <a href="http://www.maxmind.com/app/benchmark">They report</a> up to 1 million queries per second on 1 machine.</li>
<li>It is extensible. The database can be upgraded to the paid version by just replacing the binary.</li>
<li>They like developers. They provide implementations in over 10 different programming languages, with benchmarks.</li>
<li>Their website is full of valuable information. They provide benchmarks, an explanation of how they collect their data, and more. I haven&#8217;t seen this with any other IP Geolocation services.</li>
</ul>
<p>There are two options for us PHP developers. The pure PHP library or a <a href="http://pecl.php.net/package/geoip">PECL package</a> implementing the C library. For reasons that will be discussed below, the PECL package will be used. If you do not want to use a PECL package or are on a hosted server, then you can download the pure PHP classes <a href="http://geolite.maxmind.com/download/geoip/api/php/">here</a>.</p>
<p>First, the GeoIP C library must be downloaded (<a href="http://geolite.maxmind.com/download/geoip/api/c/">link</a>) and installed. Note that this can be installed on windows as well. No special options are needed to install it:<br />
<br/></p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mbpro:GeoIP-1.4.6 chehodgins$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> .<span style="color: #000000; font-weight: bold;">/</span>configure<br />
mbpro:GeoIP-1.4.6 chehodgins$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span><br />
mbpro:GeoIP-1.4.6 chehodgins$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></td></tr></tbody></table></div>
<p><br/><br />
Then the PECL package can be installed:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mbpro:~ chehodgins$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> pecl <span style="color: #c20cb9; font-weight: bold;">install</span> geoip<br />
downloading geoip-1.0.7.tar ...<br />
...<br />
You should add <span style="color: #ff0000;">&quot;extension=geoip.so&quot;</span> to php.ini</div></td></tr></tbody></table></div>
<p><br/><br />
Next, add this extension to php.ini (i.e. extension=geoip.so), restart apache and check out phpinfo():</p>
<p><div id="attachment_253" class="wp-caption aligncenter" style="width: 628px"><a href="http://www.chehodgins.com/wp-content/uploads/2009/05/picture-2.png"><img class="size-full wp-image-253" title="GeoIP in phpinfo()" src="http://www.chehodgins.com/wp-content/uploads/2009/05/picture-2.png" alt="GeoIP in phpinfo()" width="618" height="174" /></a><p class="wp-caption-text">GeoIP in phpinfo()</p></div><br />
<br/></p>
<p>The final step before writing code is to download the actual <a href="http://www.maxmind.com/app/geolitecity">database</a>. It is updated monthly so remember to stay up to date. The directory that should contain the file is OS dependent, so create a quick php script to see where the directory is:<br />
<br/></p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">ini_set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'display_errors'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">error_reporting</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">E_ALL</span> <span style="color: #339933;">|</span> <span style="color: #009900; font-weight: bold;">E_STRICT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> geoip_record_by_name<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'72.30.81.165'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p><br/><br />
Gives us:</p>
<p><a href="http://www.chehodgins.com/wp-content/uploads/2009/05/picture-3.png"><img class="aligncenter size-large wp-image-254" title="Determine the binary directory" src="http://www.chehodgins.com/wp-content/uploads/2009/05/picture-3-1024x99.png" alt="Determine the binary directory" width="1024" height="99" /></a><br />
<br/><br />
Now save the binary to the directory mentioned in the php warning, reload your script, and the warning should disappear. Let&#8217;s try again with some more code:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">ini_set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'display_errors'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">error_reporting</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">E_ALL</span> <span style="color: #339933;">|</span> <span style="color: #009900; font-weight: bold;">E_STRICT</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$functions</span> <span style="color: #339933;">=</span> <span style="color: #990000;">get_extension_funcs</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'geoip'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$functions</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> geoip_record_by_name<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'72.30.81.165'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p><br/><br />
Gives:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;height:500px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #990000;">array</span><br />
<span style="color: #cc66cc;">0</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_database_info'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">19</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">1</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_country_code_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">26</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">2</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_country_code3_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">27</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">3</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_country_name_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">26</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">4</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_continent_code_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">28</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">5</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_org_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">17</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">6</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_record_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">7</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_id_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">16</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">8</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_region_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">20</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">9</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_isp_by_name'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">17</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">10</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_db_avail'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">14</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">11</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_db_get_all_info'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">21</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">12</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_db_filename'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">17</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">13</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_region_name_by_code'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">25</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #cc66cc;">14</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'geoip_time_zone_by_country_and_region'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span>37<span style="color: #009900;">&#41;</span><br />
<br />
<span style="color: #990000;">array</span><br />
<span style="color: #0000ff;">'continent_code'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'NA'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'country_code'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'US'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'country_code3'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'USA'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'country_name'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'United States'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">13</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'region'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'CA'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'city'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'Sunnyvale'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">9</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'postal_code'</span> <span style="color: #339933;">=&gt;</span> string <span style="color: #0000ff;">'94089'</span> <span style="color: #009900;">&#40;</span>length<span style="color: #339933;">=</span><span style="color: #cc66cc;">5</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #0000ff;">'latitude'</span> <span style="color: #339933;">=&gt;</span> float <span style="color:#800080;">37.4249000549</span><br />
<span style="color: #0000ff;">'longitude'</span> <span style="color: #339933;">=&gt;</span> float <span style="color: #339933;">-</span><span style="color:#800080;">122.007400513</span><br />
<span style="color: #0000ff;">'dma_code'</span> <span style="color: #339933;">=&gt;</span> int <span style="color: #cc66cc;">807</span><br />
<span style="color: #0000ff;">'area_code'</span> <span style="color: #339933;">=&gt;</span> int <span style="color: #cc66cc;">408</span></div></td></tr></tbody></table></div>
<p><br/><br />
With only an IP address we can easily get the country, postal code, longitude and latitude, and even the area code of the user.</p>
<p><strong>Performance</strong></p>
<p>I initially thought that the PECL version would outperform the pure PHP version by a small percentage. I was wrong. The PECL version was much faster. Here are some informal benchmarks. <br/></p>
<table id="benchmarks">
<tbody>
<tr>
<th></th>
<th>Iterations</th>
<th>Total</th>
<th>Avg</th>
<th>Notes</th>
</tr>
<tr>
<td>PECL GeoIP</td>
<td>10,000</td>
<td>0.7s</td>
<td>.007ms per request</td>
<td></td>
</tr>
<tr>
<td>Pure PHP</td>
<td>10,000</td>
<td>49.2s</td>
<td>4.92ms per request</td>
<td></td>
</tr>
<tr>
<td>PECL GeoIP</td>
<td>1</td>
<td>0.08ms</td>
<td>0.08ms per request</td>
<td>Typical real world usage</td>
</tr>
<tr>
<td>Pure PHP</td>
<td>1</td>
<td>2.4ms</td>
<td>2.4ms per request</td>
<td>Typical real world usage</td>
</tr>
</tbody>
</table>
<p>As a validation of my results I benchmarked the pure PHP library being used in a web application and had comparable results to my benchmarks (5.9ms per IP lookup versus the 2.4ms above).</p>
<p><strong>Conclusion</strong></p>
<p>Because of the ease of implementation, the low cost, and the minimal performance losses, there is much to be gained by adding IP Geolocation to your web application. The PECL package is the ideal configuration because it provides a faster experience with less code to maintain. The pure PHP library is none the less still relatively fast and thus still worth it. This is still far from a perfect solution. False positives can occur, anonymous proxies mess everything up, and IP addresses are constantly changing. Also, what about users&#8217; who simply do not want to share their location? There are privacy issues. This is currently a hot topic, with the <a href="http://dev.w3.org/geo/api/spec-source.html">W3C geolocation API</a> being actively worked on, including the efforts of <a href="http://labs.mozilla.com/2008/10/introducing-geode/">Mozilla</a>, <a href="http://labs.opera.com/news/2009/03/26/">Opera</a> and others to improve the situation of location awareness on the web, something I am looking forward to it.</p>
<p>More reading:</p>
<p><a href="http://www.slideshare.net/rsarver/w3c-geolocation-api-making-websites-locationaware">Interesting Geolocation presentation</a><br />
<a href="http://ca3.php.net/manual/en/ref.geoip.php">GeoIP functions in the PHP manual</a><br />
<a href="http://toys.lerdorf.com/archives/49-Select-from-World.html">Cool Geo* stuff at Y!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.chehodgins.com/php/free-and-fast-geolocation-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
