<?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>Snipe.Net &#187; web dev</title>
	<atom:link href="http://www.snipe.net/tags/web-dev/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.snipe.net</link>
	<description>Bitterness never tasted so sweet</description>
	<lastBuildDate>Thu, 29 Jul 2010 05:03:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Making the Leap to All-CSS Website Layout</title>
		<link>http://www.snipe.net/2008/12/getting-started-all-css-website-layout/</link>
		<comments>http://www.snipe.net/2008/12/getting-started-all-css-website-layout/#comments</comments>
		<pubDate>Wed, 31 Dec 2008 08:43:37 +0000</pubDate>
		<dc:creator>snipe</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[validation]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web dev]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false">http://www.snipe.net/?p=665</guid>
		<description><![CDATA[If you&#8217;ve been designing sites for a while, you probably started off designing using tables for layouts. Using tables for page layout has gone against W3C standards for several years now, but it wasn&#8217;t until the last few years that browser-support for CSS had really come far enough to give you any choice in the [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F12%2Fgetting-started-all-css-website-layout%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F12%2Fgetting-started-all-css-website-layout%2F&amp;source=snipeyhead&amp;style=normal&amp;service=bit.ly&amp;service_api=R_92bd97f4f8b9fa8a40675b36ea291223" height="61" width="50" /><br />
			</a>
		</div>
<p>If you&#8217;ve been designing sites for a while, you probably started off designing using tables for layouts. Using tables for page layout has gone against W3C standards for several years now, but it wasn&#8217;t until the last few years that browser-support for CSS had really come far enough to give you any choice in the matter. <span id="more-665"></span></p>
<p>If you&#8217;re newer to designing websites, you&#8217;ve probably been taught CSS layout design and it&#8217;s already become a part of how you do things, but back in the day, CSS just wasn&#8217;t reliable enough to use as primary site layout for sophisticated designs. If you&#8217;ve been designing for at least 5+ years, you&#8217;ve (hopefully) already been using CSS for quite some time, for typographical formatting, basic page attributes, and so on, but may have still relied heavily on tables for the actual structural layout.</p>
<p>Now that solid, all-CSS layouts are a reality, where does an old-timer start in getting their CSS up to snuff to actually handle complex all-CSS layouts? It can be intimidating to get started, but thanks to the amazing community of design bloggers, you&#8217;ve got some great resources at your fingertips.</p>
<p>Note: Everything covered here is making the assumption that you are basically coding by hand and not using a WYSIWYG editor for layout &#8211; and that you have at least a basic understanding of how CSS works. If you&#8217;re interested in learning how to create CSS-based layouts in Dreamweaver, there is a great tutorial (including source files) <a href="http://www.vineyardesigns.com/resources/dreamweaver/div_css_site.shtml" target="_blank">available here</a>, and another dealing with CSS layouts by way of Photoshop and Dreamweaver <a href="http://hv-designs.co.uk/2007/10/10/coding-your-1st-psd-tutorial/" target="_blank">here</a>.</p>
<h2>Before You Begin</h2>
<p>Making this transition is TOTALLY do-able, no matter how long you&#8217;ve been designing with tables &#8211; it just requires a little patience. When I first started web design, there were were only a handful of books on HTML (nothing on CSS) and not a web design class to be found. (Yes, and dinosaur&#8217;s roamed the earth, and cars were a dollar. Hush.) If I could make this transition, anyone can.</p>
<p><strong>First, I think its important to demonstrate exactly how far CSS has come, and how incredibly robust it is for site layout. </strong>One of the best examples out there is <a href="http://www.csszengarden.com/" target="_blank">CSS Zen Garden</a>, which shows you multiple site layouts that are all very different, that <em>all use the exact same HTML file</em>, swapping <em>only</em> the CSS file. Click through to the different designs, and it won&#8217;t take long for you to see just how far CSS has come.</p>
<h2>Taking the Plunge</h2>
<p>The very first tutorial I would recommend is called <strong><a href="http://www.subcide.com/tutorials/csslayout/index.aspx" target="_blank">Creating a CSS Layout from Scratch</a></strong>, on the <a href="http://www.subcide.com/" target="_blank">Subcide web site</a>. This is a long tutorial, but worth every page if you actually follow the steps. The author does a fantastic job of explaining why you use each and every attribute, how it impacts the design step-by-step, and potential pitfalls you might run into. It actually moves a lot faster than you might imagine, and you can get through it in about 20 minutes if you&#8217;re actually making changes to a sample file as you go (which I highly recommend myself, being a visual learner.) Follow the steps, making the changes discussed, and previewing your changes every time, so you get a clear idea of how each little CSS change makes a big impact on the end-result.</p>
<p>Also be sure to check out the <strong><a href="http://www.alistapart.com/articles/holygrail">Holy Grail article</a></strong> by <a href="http://www.alistapart.com/">A List Apart</a>. In one page, you&#8217;ll see exactly how to create a liquid 3-column layout with very simple code.</p>
<p>Another great step-by-step, real-world CSS layout tutorial is by Webreference which <strong><a href="http://www.webreference.com/authoring/style/sheets/layout/advanced/" target="_blank">walks you through a specific layout goal</a></strong>, providing code and explanations along the way.</p>
<p>Or, if you don&#8217;t need such a granular approach, SitePoint&#8217;s article, <strong><a href="http://www.sitepoint.com/article/breaking-out-of-the-box/" target="_blank">Breaking out of the Box with CSS</a></strong>, has a similar step-by-step method.</p>
<p>Also be sure to check out this list of <strong><a href="http://blog.themeforest.net/resources/12-fantastic-psd-to-html-tutorials/" target="_blank">12 PSD to HTML/CSS tutorials</a>.</strong></p>
<p><strong>An aspect of CSS design that is absolutely critical but can be a bit confusing for newbies is the float.</strong> Smashing Magazine does a great job illustrating where floats are appropriate, which ones you need where for a specific end result, and known bugs/workarounds in their article <a href="http://www.smashingmagazine.com/2007/05/01/css-float-theory-things-you-should-know/" target="_blank">CSS Float Theory: Things You Should Know</a>. <a href="http://css.maxdesign.com.au/floatutorial/" target="_blank">Floatutorial</a> is another great step-by-step that walks through how floats work in a very simple and visual manner. That one doesn&#8217;t go into quite as much detail as the Subcide tutorial does, which may be better for you if you feel you&#8217;ve already got a decent handle on CSS concepts, but might be confusing to someone a little greener.</p>
<p><strong>One way you&#8217;ll really get a good idea of how CSS works for layout is by checking out some of the existing, semi-standardized layouts.</strong> You can use these as templates for your own designs, or just observe the different ways people have solved similar problems using CSS. There&#8217;s a <a href="http://www.noupe.com/css/css-layouts-40-tutorials-tips-demos-and-best-practices.html" target="_blank">great list of sample CSS layouts</a> available on the Noupe website, and a list of <a href="http://mashable.com/2007/09/13/one-column-website-templates/" target="_blank">40 CSS layouts</a> available on Mashable.Com. If those examples are a little too detailed and confusing, be sure to check out the <a href="http://www.thenoodleincident.com/tutorials/box_lesson/boxes.html" target="_blank">Little Boxes demo</a>, which shows you a small collection of very basic layouts (one box, two box, three column, etc) and then slightly more advanced variations.</p>
<h2>Next Steps</h2>
<p><strong>Once you&#8217;ve mastered the basics, you should try creating some simple layouts from scratch using your newly acquired powers. </strong>Once you&#8217;ve got those nailed, you can create more sophisticated samples, or convert an existing table-based site into a CSS-based site, with a little help (or maybe more than a little help) from <a href="http://www.mardiros.net/liquid-css-layouts.html" target="_blank">this tutorial from Liquid CSS</a>. Incidentally, that tutorial does a great job of illustrating how the z-axis works in CSS, a concept that can be a sticking point for some people. Doing a table-to-CSS conversion will be time-consuming (and at times, possibly more than a little frustrating), but it will be great practice (since you already know what the site is supposed to look like) and will give you a practical reason to go back and update some of your old, bloated table-based layout code. Win win!</p>
<p><strong>Soon you&#8217;ll be ready to check out some more advanced concepts in CSS</strong>, including fancy <a href="http://www.smashingmagazine.com/2006/10/25/css-techniques-tutorials-layouts/" target="_blank">lightbox image effects and graphs</a>, <a href="http://www.webdesignerwall.com/tutorials/advanced-css-menu/" target="_blank">navigation menu image rollovers</a>, <a href="http://particletree.com/features/rediscovering-the-button-element/" target="_blank">prettier form buttons</a>, <a href="http://www.456bereastreet.com/archive/200705/creating_bulletproof_graphic_link_buttons_with_css/" target="_blank">reliable image-based buttons</a>, <a href="http://www.oscaralexander.com/tutorials/how-to-make-sexy-buttons-with-css.html" target="_blank">sexy image buttons</a>, and <a href="http://www.willmayo.com/2007/02/10/css-speech-bubbles/" target="_blank">CSS speech bubbles</a>. You may already be using some of these within your table-based layout, but how they work (or occasionally don&#8217;t work) may make a little more sense to you once you&#8217;ve gone through the process of learning CSS layout. Two more gems for great tips and techniques are <a href="http://www.noupe.com/css/using-css-to-do-anything-50-creative-examples-and-tutorials.html" target="_blank">Using CSS to Do Anything</a> and <a href="http://www.noupe.com/design/101-css-techniques-of-all-time-part-1.html" target="_blank">101 CSS Tips of All Time</a>, both from Noupe.</p>
<p>I strongly recommend checking out <a href="http://www.smashingmagazine.com/category/css/" target="_blank">Smashing Magazine</a>, <a href="http://www.noupe.com/category/css" target="_blank">Noupe.Com</a>, and <a href="http://css-tricks.com/" target="_blank">CSS-Tricks.Com</a> for some of the most thorough and advanced tips, tricks and tutorials you&#8217;ll find online. Add their RSS feeds to your newsreader if you haven&#8217;t already.</p>
<h2>Best Practices</h2>
<p>Like any other new technology (and by new, I mean new to you), reading up on and implementing established best practices will go a long way. There is an outstanding breakdown of best practices in the Smashing Magazine article <a href="http://www.smashingmagazine.com/2007/05/10/70-expert-ideas-for-better-css-coding/" target="_blank">70 Expert Ideas for Better CSS Coding</a>. Seventy may sound like a daunting number, but many of these tips address workflow, naming conventions and other aspects that are less confusing as learning the actual CSS, but will save you tons of time as you begin to make CSS more of a workhorse in your own designs. (I&#8217;m a big fan of having strong fundamentals, planning and workflow, so I may be a little biased here, but its served me well over the past fifteen years of developing websites professionally.)</p>
<p>Many of these tips are not for the faint of heart, and will require a pretty solid understanding of CSS before they will be meaningful, so you may want to get some practice in before tackling this article.</p>
<h2>CSS Frameworks</h2>
<p><strong>Now that you&#8217;ve got a decent handle on CSS layout principles, you may want to look into using a CSS framework. </strong>(I leave this part for the end because understanding the fundamentals is key, and it&#8217;s tempting to skip right to using a framework instead of teaching yourself how to do it right on your own.) There are several decent CSS frameworks out there, each with their own pros and cons.</p>
<p>If you&#8217;re not sure what a CSS framework is, <a href="http://en.wikipedia.org/wiki/CSS_framework" target="_blank">the Wikipedia entry</a> says it well:</p>
<blockquote><p>A CSS framework is a pre-prepared library that is meant to allow for easier, more standards-compliant styling of a webpage using the Cascading Style Sheets language. Just like programming and scripting language libraries, CSS frameworks (usually packaged as external .css sheets inserted into the header) package a number of ready-made options for designing and outlaying a webpage.</p></blockquote>
<p>Wikipedia also has an <a href="http://en.wikipedia.org/wiki/List_of_CSS_frameworks" target="_blank">extensive list of available CSS frameworks</a>. Before you jump head-first into the CSS framework shortcut, Smashing Magazine has an <a href="http://www.smashingmagazine.com/2007/09/21/css-frameworks-css-reset-design-from-scratch/" target="_blank">excellent overview of CSS frameworks</a>, including pros and cons (of which there are many on both sides), and a brief review of some of the more popular ones. The article is from 2007, but the principles remain important and valid today. If CSS franeworks interest you, you may also want to check out the blog post and comments on <a href="http://mondaybynoon.com/2007/08/27/please-do-not-use-css-frameworks/" target="_blank">this article on the Monday by Noon website</a>.</p>
<p>I personally almost never use CSS frameworks, for many of the reasons outlined in the Smashing Magazine article, but that absolutely doesn&#8217;t mean that I discourage you from investigating them and using them as a tool where appropriate.</p>
<h2>Conclusion</h2>
<p>Not that I necessarily agree with <a href="http://giveupandusetables.com/" target="_blank">this website</a>, but it makes me chuckle every time I see it. Obviously, there may be times when you&#8217;re under deadline, and you just don&#8217;t have the luxury of learning under the gun.</p>
<p>Realistically speaking, if you were to devote your full attention and effort to the basics tutorials here, making sure to actually follow along and do the code step-by-step, you would have a pretty decent grasp on pure CSS layouts within several hours. Several hours might seem like a long time to spend on this, and you might be looking for a shortcut, but if you really want to understand it, it&#8217;s worth investing the time, especially if this is what you do for a living. Find the time. It&#8217;s important.</p>


<p>Possibly related posts:<ol><li><a href='http://www.snipe.net/2009/02/photoshop-tutorials-that-will-change-your-life/' rel='bookmark' title='Permanent Link: Photoshop Tutorials That Will Change Your Life'>Photoshop Tutorials That Will Change Your Life</a> <small>Photoshop tutorials are a dime a dozen, and simply googling...</small></li>
<li><a href='http://www.snipe.net/2008/06/compare-website-stats-using-google-trends/' rel='bookmark' title='Permanent Link: Compare Website Stats Using Google Trends'>Compare Website Stats Using Google Trends</a> <small>Google Trends has a newly-added ability to show unique visitor...</small></li>
<li><a href='http://www.snipe.net/2009/01/creating-a-wordpress-theme/' rel='bookmark' title='Permanent Link: Creating A WordPress Theme'>Creating A WordPress Theme</a> <small>If you&#8217;ve already got some design chops and a WordPress...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.snipe.net/2008/12/getting-started-all-css-website-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using IP Geolocation and Radius Searching with PHP/MySQL</title>
		<link>http://www.snipe.net/2008/12/ip-geolocation-radius-search-in-php/</link>
		<comments>http://www.snipe.net/2008/12/ip-geolocation-radius-search-in-php/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 19:05:50 +0000</pubDate>
		<dc:creator>snipe</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[PHP/mySQL]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.snipe.net/?p=538</guid>
		<description><![CDATA[Delivering content relative to the physical location of your users is an excellent (and fairly easy) way to fine-tune the content you&#8217;re delivering to be most relevent to the people visiting your site. Two simple ways of doing this are to use an IP-based geolocation lookup, or to do a manual radius search (like a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F12%2Fip-geolocation-radius-search-in-php%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F12%2Fip-geolocation-radius-search-in-php%2F&amp;source=snipeyhead&amp;style=normal&amp;service=bit.ly&amp;service_api=R_92bd97f4f8b9fa8a40675b36ea291223" height="61" width="50" /><br />
			</a>
		</div>
<p>Delivering content relative to the physical location of your users is an excellent (and fairly easy) way to fine-tune the content you&#8217;re delivering to be most relevent to the people visiting your site. Two simple ways of doing this are to use an IP-based geolocation lookup, or to do a manual radius search (like a &#8220;store finder&#8221; type of functionality), where the user manually enters a postal code. Both function on the same logic &#8211; the real difference is that one requires a third-party service that can fetch the user&#8217;s latitude and longitude based on IP address. This functionality can be used to show content such as local news, local store branches, etc &#8211; as soon as the user visits your page.</p>
<p><span id="more-538"></span></p>
<p>The nuts and bolts of IP-based geolocation is as follows:</p>
<ol>
<li>User lands on the web page</li>
<li>User&#8217;s IP is captured and posted to a third-party geolocation service, which returns a latitude and longitude for the IP address</li>
<li>Website performs a radius database search using the latitude and longitude provided by the third party service and returns content relative to that location</li>
</ol>
<p>Bear in mind, your database must contain data that is stored with a latitude and longitude for this to work. You cannot compare a user&#8217;s latitude and longitude to the lat/long of a piece of data if you have no lat/long associated to your content.</p>
<p>Also, please note: the services mentioned here &#8211; and the code provided &#8211; is intended for US-based geolocation. The code will remain basically the same for non-US lookups, but you may need to use alternate third-party services if your country is not covered by the ones mentioned here.</p>
<h2>1. Getting Latitude/Longitude for Your Database Data</h2>
<p>The first part of this process starts with you tagging your existing or newly added database data with the correct latitude and longitude. Each item you wish to include in the radius search should have a valid lat/long value in the latitude and longitude fields. If you are modifying an existing database, you would execute an alter table command to add the new lat/long fields. For this example, we&#8217;ll be using a table called stores:</p>
<pre class="brush: sql">CREATE TABLE `stores` (
`store_id` INT NOT NULL AUTO_INCREMENT ,
`store_address` VARCHAR( 40 ) NULL ,
`store_city` VARCHAR( 40 ) NULL ,
`store_state` VARCHAR( 2 ) NULL ,
`store_country` VARCHAR( 2 ) NULL ,
`store_phone` VARCHAR( 15 ) NULL ,
UNIQUE (`store_id`));</pre>
<p>And then we add the new latitude and longitude fields to our stores table, using the DOUBLE datatype:</p>
<pre class="brush: sql">ALTER TABLE `stores` ADD `latitude` DOUBLE NULL ,
ADD `longitude` DOUBLE NULL ;</pre>
<p>Now our table is set up to store the latitude and longitude data, but from where do we actually get the data, short of manually looking it up for each row of data in our stores table?  Easy. There is a fabulous free service available at <a href="http://rpc.geocoder.us/" target="_blank">rpc.geocoder.us</a> that lets you post an address to their API, to which it responds with the latitude and longitude values for that address. The easiest way to handle this process is to set up a cURL request in the admin area where you&#8217;re managing your data &#8211; otherwise you&#8217;ll need to write a script to cycle through the rows of data, fetching the latitude and longitude.(You will, of course, need to have PHP configured with cURL support for this to work.) Using this service, free lookups are throttled by your IP address to one request every 15 seconds &#8211; this may cause issues when you&#8217;re initially trying to get the lat/long data into your database for existing records, but shouldn&#8217;t be much of an issue afterwards.</p>
<p>First let&#8217;s set up a small function to handle the cURL request:</p>
<pre class="brush: php">function curl_string ($url){
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_TIMEOUT, 120);
$result = curl_exec ($ch);
curl_close($ch);
return $result;
</pre>
<p>The format you will be sending the query to the rpc.geocoder.us API is: <span class="linkification-ext"><a class="linkification-ext" title="Linkification: http://rpc.geocoder.us/service/csv?address=1600+Pennsylvania+Ave%2C+Washington+DC" href="http://rpc.geocoder.us/service/csv?address=1600+Pennsylvania+Ave%2C+Washington+DC">http://rpc.geocoder.us/service/csv?address=1600+Pennsylvania+Ave%2C+Washington+DC</a></span></p>
<pre class="brush: php">
// set the url of the API using the address, city and state we want to query

$url_page = &quot;http://&quot;.&quot;rpc.&quot;.&quot;.geocoder&quot;.&quot;.us/service/csv&quot;;
$url_page .=&quot;?address=&quot;.urlencode($address).&quot;,&quot;.urlencode($city).&quot;,&quot;.$state;

// execute the cURL request
$string = curl_string($url_page);

// turn the comma separated csv data turned into an array,
// so we can easily see that a match was found and use the pieces
$address_pieces= explode(&quot;,&quot;, $string);

// make sure the array contains data
if (count($address_pieces) &gt; 0) {

// update the database
$sql = &quot;update stores set latitude=&#039;&quot;.$address_pieces[0].&quot;&#039;, &quot;;
$sql .=&quot;longitude=&#039;&quot;.$address_pieces[1].&quot;&#039;, &quot;;
$sql .=&quot;zip=&#039;&quot;.$address_pieces[5].&quot;&#039; where id=&#039;&quot;.$store_id.&quot;&#039;&quot;;

if ($update_latlong = mysql_query($sql)) {
echo &#039;Lat/long updated!&#039;;
} else {
// if the query failed, print out an error
echo mysql_error();
}

// if the array does not contain data, no match was found in geocoder.us, so suggest using google maps to find the lat/long manually
} else {
echo &#039;No geolocation match.&#039;;

}</pre>
<p>The code above will help you update your existing data if you were to use it in a script that cycles through your database records, or you can use it as part of your store administration area, doing the cURL request every time a new store is saved to the database.</p>
<h2>2. Getting the Latitude and Longitude of the User</h2>
<p>Now that you have base lat/long data for the data in your database, you have to obtain the lat/long for the user visiting the site. For this next part, you will again need to access a third-party service, this time to get the latitude and longitude based on the user&#8217;s IP address. I use a commercial service available from <a href="http://www.maxmind.com/app/city" target="_blank">MaxMind.Com</a>. It&#8217;s not free, but their prices are very reasonable ($20 per 50,000 queries) &#8211; and by using a cookie to store whether or not the user&#8217;s lat/long has already been returned, you can save on the number of accesses you use up on a busy site.</p>
<pre class="brush: php">// begin the session
session_start();

$expireTime = 60*60*24*30; // 30 days
session_set_cookie_params($expireTime);

if ((!isset($_SESSION[&#039;geo_country&#039;])) || ($_SESSION[&#039;geo_country&#039;]==&#039;&#039;))    {

// enter your MaxMind license key here
$license_key=&#039;XXXXXXXXXXXXXXX&#039;;
$ip = $_SERVER[&#039;REMOTE_ADDR&#039;];

$query = &quot;http://&quot;.&quot;geoip1.&quot;.&quot;maxmind&quot;.&quot;.com/b?l=&quot; . $license_key . &quot;&amp;amp;amp;amp;amp;amp;amp;amp;amp;i=&quot; . $ip;
$url = parse_url($query);
$host = $url[&quot;host&quot;];
$path = $url[&quot;path&quot;] . &quot;?&quot; . $url[&quot;query&quot;];
$timeout = 1;
$fp = fsockopen ($host, 80, $errno, $errstr, $timeout)
or die(&#039;Can not open connection to server.&#039;);

if ($fp) {
fputs ($fp, &quot;GET $path HTTP/1.0\nHost: &quot; . $host . &quot;\n\n&quot;);

while (!feof($fp)) {
$buf .= fgets($fp, 128);
} // endwhile

// split the output into an array
$lines = split(&quot;\n&quot;, $buf);
$data = $lines[count($lines)-1];
fclose($fp);

$geo = explode(&quot;,&quot;,$data);
$user_geo_country = $geo[0];
$user_geo_state = $geo[1];
$user_geo_city = $geo[2];
$user_geo_lat = $geo[3];
$user_geo_lon = $geo[4];

$_SESSION[&#039;geo_country&#039;] = $user_geo_country;
$_SESSION[&#039;geo_state&#039;] = $user_geo_state;
$_SESSION[&#039;geo_city&#039;] = $user_geo_city;
$_SESSION[&#039;geo_lat&#039;] = $user_geo_lat;
$_SESSION[&#039;geo_lon&#039;] = $user_geo_lon;

setcookie(&quot;geolocCookieCountry&quot;, $user_geo_country, time()+$expireTime, &quot;/&quot;);
setcookie(&quot;geolocCookieCity&quot;, $user_geo_city, time()+$expireTime, &quot;/&quot;);
setcookie(&quot;geolocCookieState&quot;, $user_geo_state, time()+$expireTime, &quot;/&quot;);
setcookie(&quot;geolocCookieLat&quot;, $user_geo_lat, time()+$expireTime, &quot;/&quot;);
setcookie(&quot;geolocCookieLon&quot;, $user_geo_lon, time()+$expireTime, &quot;/&quot;);

} // endif $fp

} // endif session set
</pre>
<p>Now, you&#8217;ll only be querying MaxMind if the user hasn&#8217;t already accessed the site before and had their latitude and longtude stored in the cookie. Note the $license variable in the code above. When you sign up for the MaxMind Web Service, you will be given a license number, which you&#8217;ll insert there.</p>
<h2>3. Putting the Two Together to Return Results Within X Miles</h2>
<p>To tie the two together and query the database, returning only results that are within a specified number of miles of the user&#8217;s IP address, we&#8217;ll need two classes:</p>
<pre class="brush: php">class RadiusCheck {

var $maxLat;
var $minLat;
var $maxLong;
var $minLong;

function RadiusCheck($Latitude, $Longitude, $Miles) {
global $maxLat,$minLat,$maxLong,$minLong;
$EQUATOR_LAT_MILE = 69.172;
$maxLat = $Latitude + $Miles / $EQUATOR_LAT_MILE;
$minLat = $Latitude - ($maxLat - $Latitude);
$maxLong = $Longitude + $Miles / (cos($minLat * M_PI / 180) * $EQUATOR_LAT_MILE);
$minLong = $Longitude - ($maxLong - $Longitude);
}

function MaxLatitude() {
return $GLOBALS[&quot;maxLat&quot;];
}
function MinLatitude() {
return $GLOBALS[&quot;minLat&quot;];
}
function MaxLongitude() {
return $GLOBALS[&quot;maxLong&quot;];
}
function MinLongitude() {
return $GLOBALS[&quot;minLong&quot;];
}

}</pre>
<p>and</p>
<pre class="brush: php">class DistanceCheck {

function DistanceCheck() {
}

function Calculate(
$dblLat1,
$dblLong1,
$dblLat2,
$dblLong2
) {
$EARTH_RADIUS_MILES = 3963;
$dist = 0;

//convert degrees to radians
$dblLat1 = $dblLat1 * M_PI / 180;
$dblLong1 = $dblLong1 * M_PI / 180;
$dblLat2 = $dblLat2 * M_PI / 180;
$dblLong2 = $dblLong2 * M_PI / 180;

if ($dblLat1 != $dblLat2 || $dblLong1 != $dblLong2)
{
//the two points are not the same
$dist =
sin($dblLat1) * sin($dblLat2)
+ cos($dblLat1) * cos($dblLat2)
* cos($dblLong2 - $dblLong1);

$dist =
$EARTH_RADIUS_MILES
* (-1 * atan($dist / sqrt(1 - $dist * $dist)) + M_PI / 2);
}
return $dist;
}

}</pre>
<p>And then, to perform the actual query:</p>
<pre class="brush: php">
// set a default number of miles to search within
$Miles = &#039;50&#039;;

// set the user&#039;s latitude and longitude as the one to search against
$Latitude = $user_geo_lat;
$Longitude = $user_geo_lon;

$zcdRadius = new RadiusCheck($Latitude,$Longitude,$Miles);
$minLat = $zcdRadius-&gt;MinLatitude();
$maxLat = $zcdRadius-&gt;MaxLatitude();
$minLong = $zcdRadius-&gt;MinLongitude();
$maxLong = $zcdRadius-&gt;MaxLongitude();

$sql = &quot;SELECT store_address, store_city, store_state, store_phone, &quot;;
$sql .= &quot;SQRT((((69.1*(latitude-$Latitude))*(69.1*(latitude-$Latitude)))+((53*(longitude-$Longitude))*(53*(longitude-$Longitude))))) &quot;;
$sql .= &quot;AS calc FROM stores where  &quot;;
$sql .= &quot;latitude &gt;= &#039;$minLat&#039; &quot;;
$sql .= &quot;AND latitude &lt;= &#039;$maxLat&#039; &quot;;
$sql .= &quot;AND longitude &gt;= &#039;$minLong&#039; &quot;;
$sql .= &quot;AND longitude &lt;= &#039;$maxLong&#039; &quot;;
$get_data = mysql_query($sql);

// loop through the matching database results
while($storedata = mysql_fetch_assoc($get_data)) {

// calculate the number of miles away the result is
$zcdDistance = new DistanceCheck;
$Distance = $zcdDistance-&gt;Calculate($Latitude,$Longitude,$storedata[&#039;latitude&#039;],$storedata[&#039;longitude&#039;]);

// and for the non-US people, here&#039;s the km calculation
$calc_km = round(($Distance * 1.609344),2);

echo &#039;&lt;li&gt;&#039;.$storedata[&#039;store_address&#039;].&#039;&lt;br /&gt;&#039;.$storedata[&#039;store_city&#039;].&#039;, &#039;;
echo $storedata[&#039;store_state&#039;].&#039; &#039;.$storedata[&#039;store_country&#039;].&#039;&lt;br /&gt;&#039;;
echo $storedata[&#039;store_phone&#039;].&#039;&lt;br /&gt;&#039;;
echo &#039;Distance: &#039;.$Distance.&#039; (&#039;.$calc_km.&#039; km)&#039;;
}</pre>
<p>And that&#8217;s really all there is to it.</p>
<h2>Store Locator Only</h2>
<p>If you want to create a store-locator style script without automagically getting the user&#8217;s current location, you&#8217;d use the code above, almost verbatim. The difference is that you&#8217;d need an additional table of zipcodes with associated lat/long, available for purchase (again, not very expensive) from <a href="http://www.zipcodedownload.com/" target="_blank">ZipCodeDownload.Com</a>. The process would go as follows:</p>
<ol>
<li>User arrives at your site, and enters a zip code and mile radius they wish to search using your search form &#8211; clicks submit</li>
<li>The script queries the zip code table to find the latitude and longitude associated with the postal code the user has entered, and uses THAT latitude and longitude as the values for $Latitude and $Longitude in the code above, and uses the user-entered values for $Miles from the search form.</li>
</ol>
<p>Everything else stays exactly the same. Naturally, you&#8217;ll probably want to add some sanity checks in your own code (gracefully displaying default content if no latitude and longitude is returned, etc) but I decided to skip that here so as not to confuse anyone.</p>
<p>Enjoy, and if you end up using this anywhere, let me know how it works out.</p>


<p>Possibly related posts:<ol><li><a href='http://www.snipe.net/2002/06/alternating-row-colors-in-phpmysql/' rel='bookmark' title='Permanent Link: Alternating Row Colors in PHP/mySQL'>Alternating Row Colors in PHP/mySQL</a> <small>Using alternating row colors in a PHP database application is...</small></li>
<li><a href='http://www.snipe.net/2006/06/creating-a-multi-level-listbox-in-phpmysql/' rel='bookmark' title='Permanent Link: Creating a Multi-Level Listbox in PHP/mySQL'>Creating a Multi-Level Listbox in PHP/mySQL</a> <small>This lets you create a nested multi-level category menu through...</small></li>
<li><a href='http://www.snipe.net/2002/06/phpmysql-breadcrumb-trail/' rel='bookmark' title='Permanent Link: PHP/mySQL Breadcrumb Trail'>PHP/mySQL Breadcrumb Trail</a> <small>This lets you automatically create a breadcrumb trail navigation through...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.snipe.net/2008/12/ip-geolocation-radius-search-in-php/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Planning Your Facebook Application</title>
		<link>http://www.snipe.net/2008/09/planning-a-facebook-application/</link>
		<comments>http://www.snipe.net/2008/09/planning-a-facebook-application/#comments</comments>
		<pubDate>Sat, 27 Sep 2008 05:38:27 +0000</pubDate>
		<dc:creator>snipe</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[PHP/mySQL]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[social networks]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.snipe.net/?p=277</guid>
		<description><![CDATA[This is part one of a series &#8211; the technical how-to of creating the application will be discussed in a separate article. This article is intended to help you plan out your application to best prepare for coding and best leverage the new aspects of Facebook for exposure and social interaction. Having created several Facebook [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F09%2Fplanning-a-facebook-application%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F09%2Fplanning-a-facebook-application%2F&amp;source=snipeyhead&amp;style=normal&amp;service=bit.ly&amp;service_api=R_92bd97f4f8b9fa8a40675b36ea291223" height="61" width="50" /><br />
			</a>
		</div>
<p>This is part one of a series &#8211; the technical how-to of creating the application will be discussed in a separate article. This article is intended to help you plan out your application to best prepare for coding and best leverage the new aspects of Facebook for exposure and social interaction.</p>
<p><span id="more-277"></span></p>
<p>Having created several Facebook applications, I had this article in the back of my head for quite some time now.</p>
<p>The code and Facebook functionality mentioned in this series is current as of September 26, 2008, and deals primarily with the &#8220;new&#8221; Facebook. I will try to keep it updated in the future as they continue to change things.</p>
<p><strong>The planning phase is absolutely critical and directly relates to the success of your application. </strong>This is <em>especially</em> important in Facebook applications, since <em>good planning can literally make or break the popularity of your application</em>. If you overlook one of the profile boxes, or fail to implement social actions such as inviting friends or posting actions to the user&#8217;s newsfeed, you&#8217;re going to lose out on some of the key viral aspects that make Facebook applications become popular in the first place.</p>
<h2>Application Canvas Page</h2>
<p>The application canvas page is the standalone page that your application lives on. It has the widest available page real estate, since the application doesn&#8217;t have to share the page with anything else, other than a narrow column of ads on the right-hand side (not shown).</p>
<div id="attachment_299" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/fb_canvas.jpg"><img class="size-full wp-image-299" title="Facebook application canvas page" src="http://www.snipe.net/wp-content/uploads/2008/09/fb_canvas.jpg" alt="Facebook application canvas page" width="500" height="336" /></a><p class="wp-caption-text">Facebook application canvas page</p></div>
<p>You can use a few built-in features of Facebook&#8217;s scripting language, called FBML, to easily create the ability for users to invite their friends to the application. We&#8217;ll go into more of the built-in tab tags in the next article, but its important to make it easy for users to get their friends engaged. Here&#8217;s some sample code:</p>
<pre class="brush: php">&lt;fb :tabs&gt;
&lt;fb :tab-item href=&quot;invite.php&quot; title=&quot;Invite Friends&quot;/&gt;
&lt;/fb&gt;</pre>
<blockquote><p><strong>NOTE: </strong><strong>Never require that your friends invite people in order to use your app.</strong> It&#8217;s lame, and although it may boost the number of people who install the application, your number of active users will not benefit as much as if you use honest methods to encourage people to involve their friends. Its a lousy business practice, and you will drive away users who don&#8217;t enjoy being forced into spamming their friends with an application that they haven&#8217;t even been able to try yet.</p>
<p>Genuine, organic interaction is what will provide you with long-term active users, not underhanded tricks. When users trust your application, they will be more likely to stay active and invite all of their friends, instead of just the ones they are required to invite to check out your application.</p></blockquote>
<p>Since FBML will also allow you to deliver specific content based on whether or not the user has added your application to their profile or boxes page (discussed below), be sure to include a button that prompts the user to add it. Many users are still confused by Facebook&#8217;s new layout and functionality, so the easier to make it for people to add your app to their profile, the better.</p>
<p><a href="http://www.snipe.net/wp-content/uploads/2008/09/add_popup.jpg"><img class="aligncenter size-full wp-image-315" title="add_popup" src="http://www.snipe.net/wp-content/uploads/2008/09/add_popup.jpg" alt="" width="500" height="367" /></a></p>
<p>To create this button, simple include the following code where you want the button to appear:</p>
<pre class="brush: php">&lt;fb :if-section-not-added section=&quot;profile&quot;&gt;
&lt;fb :add-section-button section=&quot;profile&quot; /&gt;
&lt;/fb&gt;</pre>
<h2>Application Content Boxes</h2>
<p>Let&#8217;s get started by discussing the various places your application content can live on Facebook. The main application lives on a canvas page in Facebook &#8211; that&#8217;s the page at <em><a class="linkification-ext" title="Linkification: http://apps.facebook.com/" href="http://apps.facebook.com/">http://apps.facebook.com/</a>&lt;yourappname&gt;</em> &#8211; but that&#8217;s not the only place your application can appear. There are several content boxes available to you &#8211; or more specifically, to your potential application users &#8211; and each one serves a slightly different purpose. To further complicate (or arguably improve) matters, the content you deliver in those boxes can be customized for the user who has added the application AND for a user who is looking at the box on someone else&#8217;s profile or fan page, delivering specific content for each state.</p>
<h3>1. Application Profile Boxes &#8211; Old Vs. New</h3>
<p>Application profile boxes are the boxes where your application has a presence on the profile of the user who has interacted with it.</p>
<p>With the &#8220;new&#8221; Facebook launch, the location and specs of these boxes have changed drastically. Prior to the Facebook redesign, when a user added an application, it would appear on their profile page, either as a wide box or a narrow box, depending on the application settings. Users could move the box from its default location into the opposite column if they so chose. When a user added an application, the application&#8217;s profile box would show up <em>by default</em> in the user&#8217;s profile. They always had the option to remove the box, but it showed up by default.</p>
<div id="attachment_290" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/old_facebook.jpg"><img class="size-medium wp-image-290" title="Old Facebook application profile box" src="http://www.snipe.net/wp-content/uploads/2008/09/old_facebook-300x276.jpg" alt="Old Facebook application profile box" width="300" height="276" /></a><p class="wp-caption-text">Old Facebook application profile box</p></div>
<p>This layout has since changed &#8211; in fact, if you use Facebook at all, you&#8217;ll have noticed that the entire profile layout and interface has changed. The change has resulted in a reduced presence of applications on the profile pages. On the new Facebook, users no longer &#8220;add&#8221; an application, they &#8220;allow&#8221; it &#8211; and the application doesn&#8217;t show up anywhere in their profile without them deliberately going out of their way to add it. This means that you have more of an obligation to give the user a compelling reason to add your application to their main profile page.</p>
<p>Additionally, the old wider boxes in old profiles are no more. <strong>Profile application boxes are 200 pixels, with 8 pixels of padding on each side for an actual usable width of 184 pixels &#8211; and are limited to 250 pixels in height</strong>. If your application box is longer than 250 pixels, everything below the 250 mark will be hidden from view, so plan around these dimensions.</p>
<div id="attachment_293" class="wp-caption aligncenter" style="width: 452px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/new_fb.jpg"><img class="size-full wp-image-293" title="New Facebook application profile box" src="http://www.snipe.net/wp-content/uploads/2008/09/new_fb.jpg" alt="New Facebook application profile box" width="442" height="604" /></a><p class="wp-caption-text">New Facebook application profile box</p></div>
<p>If your application is created properly, the user will also have the option to move the application box to their (new) &#8220;Boxes&#8221; screen.</p>
<p><a href="http://www.snipe.net/wp-content/uploads/2008/09/new_bf_closeup.jpg"><img class="aligncenter size-full wp-image-295" title="new_bf_closeup" src="http://www.snipe.net/wp-content/uploads/2008/09/new_bf_closeup.jpg" alt="" width="356" height="301" /></a></p>
<h3>2. User Profile &#8220;Boxes&#8221; Screen</h3>
<p>The new Facebook includes a tab labeled &#8220;Boxes&#8221;, that serves as a shortcut to the applications they choose to include in that area. Applications that the user frequently interacts with might be added here, so the user can get to them quickly. Users can opt to drag their box to the wide or narrow column in the boxes screen.</p>
<div id="attachment_296" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/boxes_tab.jpg"><img class="size-medium wp-image-296" title="New Facebook Boxes tab" src="http://www.snipe.net/wp-content/uploads/2008/09/boxes_tab-300x201.jpg" alt="New Facebook Boxes tab" width="300" height="201" /></a><p class="wp-caption-text">New Facebook Boxes tab</p></div>
<p>Because the user has the option of narrow or wide, you should make sure you account for both wide and narrow views for the boxes tab. As you&#8217;re designing your application, take into consideration that there are dramatic size differences between the wide and narrow layouts, and <em>design appropriate displays for both versions</em>.</p>
<h3>3. Fan Pages</h3>
<p>Fan pages and application pages also received an overhaul in the new Facebook design. Previously, application&#8217;s &#8220;about&#8221; page &#8211; the page that shows the user information about your application, the developers, and allows users to leave reviews of your application &#8211; did not allow you to add external applications to an existing application about page. The new design allows you to do so. Previously, if you were running a marketing effort that included a Facebook application to advertise a product or event, you needed to create a separate fan page where users could upload photos and video, &#8220;fan&#8221; the page, and so on. Because Facebook has changed this format to allow application administrators to add external applications to application fan pages, you may decide to use the application fan page as the one destination for fans. This can cut out confusion on the part of the user, who may not understand why there are two fan pages for the same product or service.</p>
<p><a href="http://www.snipe.net/wp-content/uploads/2008/09/fanpage.jpg"><img class="aligncenter size-full wp-image-300" title="fanpage" src="http://www.snipe.net/wp-content/uploads/2008/09/fanpage.jpg" alt="" width="499" height="505" /></a></p>
<p>To encourage engagement, you can enable discussion boards, reviews, photo and video galleries, wall posts and more, allowing your application fan page to be a community portal for the people who interact with your application.</p>
<h3>4. Application Tab</h3>
<p>In the new Facebook, users have the option of adding a shortcut to their favorite apps right on their profile. This allows them to jump right to the application, without having to dig through their application menu. You MUST set this option up in the application settings page. (It will ask you for a url for your tab page. If you leave this blank, the user will not be able to add your application as an application tab.)</p>
<div id="attachment_308" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/app_tab.jpg"><img class="size-full wp-image-308" title="Application tabs" src="http://www.snipe.net/wp-content/uploads/2008/09/app_tab.jpg" alt="Application tabs" width="500" height="476" /></a><p class="wp-caption-text">Application tabs</p></div>
<p>The contents of the tab page (for example, tab.php) are not unlike the contents of your main canvas page. No special code is required, so you can basically just copy the code from your canvas page (minus the wide and narrow specs) and echo it out to the page.</p>
<h3>Social Actions</h3>
<p>The user&#8217;s mini-feed (or newsfeed) is a critical aspect of your Facebook application. Many people never browse the application directory, but instead primarily learn about new applications solely by seeing what their friends are interacting with. Some will be more apt to accept a direct invitation, and others won&#8217;t even need an invitation. They will see social actions posted to their friends newsfeed, and if they are compelled by the action or message, they will frequently add the application based simply on the fact that their friends are using it, and they trust their friends, so &#8220;it must be good&#8221;.</p>
<div id="attachment_301" class="wp-caption aligncenter" style="width: 370px"><a href="http://www.snipe.net/wp-content/uploads/2008/09/picture-8.png"><img class="size-medium wp-image-301" title="Social actions are displayed in the user's newsfeed and profile wall" src="http://www.snipe.net/wp-content/uploads/2008/09/picture-8-300x180.png" alt="Social actions are displayed in the user's newsfeed and profile wall" width="360" height="216" /></a><p class="wp-caption-text">Social actions are displayed in the user</p></div>
<p>Social actions are displayed on the user&#8217;s profile &#8220;wall&#8221;, and also in the mini-feed page of their friends.</p>
<p>Facebook does have some restrictions on social action messages. For example, every application is limited to 10 social newsfeed messages per user per 24 hour period. If the user interacts with your application in a way that triggers newsfeed messages more than 10 times in a day, the subsequent newsfeed messages will simply not be displayed.</p>
<p>Additionally, the user must take an action that triggers the social action newsfeed item. For example, you could not have an application that adds a newsfeed item every 4 hours regardless of whether or not the user has interacted with the application that day. In the Mr. Right application, which was the source for many of the screenshots in this article, we wanted the fictional &#8220;boyfriend&#8221;, Mr. Right, to send the users gifts. Those gifts would then be inserted into the user&#8217;s minifeed, encouraging social actions. However since it would be against the Facebook terms of service to automatically fire off newsfeed items, we had to create a button in the application that allowed users to request that Mr. Right send them a gift. When they clicked on the &#8220;Let me give you something&#8221; button, the newsfeed was allowed, since the user took a specific action in the application to trigger it.</p>
<p>When planning your newsfeed items, be sure to make them interesting, relevant and FUN. If users feel as though your application is spamming them or their friends, they will be quick to uninstall it and never look back.</p>
<h2>Conclusion</h2>
<p>So in conclusion, there are a total of 6 application views you should be planning for:</p>
<ol>
<li>Widest &#8211; application canvas page</li>
<li>Narrow &#8211; profile box  (184 x 250)</li>
<li>Wide &#8211; boxes tab (380 wide, can expand in height)</li>
<li>Narrow &#8211; boxes tab  (184 wide, can expand in height)</li>
<li>Wide &#8211; fan page</li>
<li>Widest &#8211; application tab</li>
</ol>
<p>Additionally, each of these application views can deliver content based on:</p>
<ol>
<li>Whether or not the user has added (or &#8220;allowed&#8221;) the application</li>
<li>Whether or not the user has added the application to their profile box</li>
</ol>
<p>Ideally, you&#8217;ll want to <strong>tailor each of the box view variations based on the user states mentioned above.</strong> This potentially means designing 12 different box display variations. This may seem like a lot of work, however by taking the time to plan this out in advance, you&#8217;ll be sure to deliver truly tailored content to your users, making it more compelling for them to interact with your application and add it to their profile, putting it in a place where their friends will see it.</p>
<p>Customizing the view will deliver meaningful messages to users who have already allowed the application, and perhaps more importantly, can deliver a call to action for users who haven&#8217;t. For example:</p>
<ul>
<li>The user who has allowed the application will see a leaderboard of their friends, or information directly related to the way they have previously interacted with the application. (&#8220;Friends Leaderboard&#8221;, or &#8220;This is your Mr. Right&#8221;)</li>
<li>The user who has not allowed the application and is viewing it on a friend&#8217;s profile will be given a call to action. (&#8220;To get your own Mr. Right, click here&#8221;)</li>
</ul>
<p>Including <strong>social actions into the user&#8217;s newsfeed </strong>will also be a very effective way to leverage the viral aspects of Facebook applications. Carefully planned social action messages will pique the curiosity of the friends of the user who is interacting with it, making it far more likely that they will interact with it themselves.</p>
<p>And of course, you should <strong>make it as easy as possible for users to invite and engage their friends</strong> by integrating built-in &#8220;invite your friends&#8221; functionality, and (if it makes sense for your application) leaderboards or galleries that invite friendly competition between friends.</p>
<p>For more information on application planning, visit the <a href="http://developers.facebook.com/get_started.php?tab=anatomy" target="_blank">Anatomy of an Application page on the Facebook Developer&#8217;s website</a>. The Anatomy of an Application page also addresses some additional functions such as a media publisher that allows user to publish rich content to their profiles, although it may not be appropriate for all applications.</p>
<p>Don&#8217;t miss <strong><a href="http://www.snipe.net/2008/12/planning-a-facebook-application-part-two/" target="_blank">part two of this series</a></strong>, where we walk through creating a simple Facebook application based on the dicussion in this article.</p>


<p>Possibly related posts:<ol><li><a href='http://www.snipe.net/2008/12/planning-a-facebook-application-part-two/' rel='bookmark' title='Permanent Link: Planning a Facebook Application: Part Two'>Planning a Facebook Application: Part Two</a> <small>I know I promised you that we&#8217;d get into some...</small></li>
<li><a href='http://www.snipe.net/2009/04/facebook-application-tabs/' rel='bookmark' title='Permanent Link: %$#^%$* Facebook Application Tabs'>%$#^%$* Facebook Application Tabs</a> <small>So this is new. And by new I mean painfully...</small></li>
<li><a href='http://www.snipe.net/2009/06/fb-fanpages-fbml-box/' rel='bookmark' title='Permanent Link: Static FBML: Not Every Facebook Fan Page Needs An Application'>Static FBML: Not Every Facebook Fan Page Needs An Application</a> <small>You don&#8217;t always need a custom application for your Facebook...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.snipe.net/2008/09/planning-a-facebook-application/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Generate lists of banned words for forums and other applications</title>
		<link>http://www.snipe.net/2008/07/generate-lists-of-banned-words-for-forums-and-other-applications/</link>
		<comments>http://www.snipe.net/2008/07/generate-lists-of-banned-words-for-forums-and-other-applications/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 04:35:28 +0000</pubDate>
		<dc:creator>snipe</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[web dev]]></category>

		<guid isPermaLink="false">http://www.snipe.net/?p=182</guid>
		<description><![CDATA[If you develop software for a living, or if you moderate any online forums, you may have found yourself in the situation where you need a list of banned or blocked words. The problem is, what works for one application doesn&#8217;t work for another. A forums targeted at adults can probably have a little more [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F07%2Fgenerate-lists-of-banned-words-for-forums-and-other-applications%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.snipe.net%2F2008%2F07%2Fgenerate-lists-of-banned-words-for-forums-and-other-applications%2F&amp;source=snipeyhead&amp;style=normal&amp;service=bit.ly&amp;service_api=R_92bd97f4f8b9fa8a40675b36ea291223" height="61" width="50" /><br />
			</a>
		</div>
<p>If you develop software for a living, or if you moderate any online forums, you may have found yourself in the situation where you need a list of banned or blocked words. The problem is, what works for one application doesn&#8217;t work for another. A forums targeted at adults can probably have a little more latitude than a game designed for children.</p>
<p>Rather than maintaining multiple lists for multiple audiences, check out <a href="http://www.banbuilder.com" target="_blank">BanBuilder.Com</a>, a website that lets you generate a list of banned words based on rating (PG, PG-13, R), location (US swear words versus UK, etc) and export them into various formats including csv, text, sql insert statements and more. The service is free and there&#8217;s nothing to sign up for. Just use it when you need it.</p>
<p>Note: the export function isn&#8217;t working just yet &#8211; but you can help the project by adding your own swear words to the database. Check back in a day or two for the export feature.</p>
<p>And if you have suggestions, post them here, since this is my own little pet project!</p>


<p>Possibly related posts:<ol><li><a href='http://www.snipe.net/2008/07/identify-and-fix-sql-injection-vulnerabilities-in-web-applications/' rel='bookmark' title='Permanent Link: Identify and Fix SQL Injection Vulnerabilities in Web Applications'>Identify and Fix SQL Injection Vulnerabilities in Web Applications</a> <small>Scrawlr is a free software for scanning SQL injection vulnerabilities...</small></li>
<li><a href='http://www.snipe.net/2002/06/truncate-text-to-x-number-of-words/' rel='bookmark' title='Permanent Link: Truncate text to x number of words'>Truncate text to x number of words</a> <small>This code will truncate given text to a certain length,...</small></li>
<li><a href='http://www.snipe.net/2009/01/advertising-on-facebook-applications-an-experiment/' rel='bookmark' title='Permanent Link: Advertising on Facebook Applications &#8211; An Experiment'>Advertising on Facebook Applications &#8211; An Experiment</a> <small>This article has been deprecated, and has been replaced by...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.snipe.net/2008/07/generate-lists-of-banned-words-for-forums-and-other-applications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
