<?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>SeoExploration</title> <atom:link href="http://www.seoexploration.com/feed/" rel="self" type="application/rss+xml" /><link>http://www.seoexploration.com</link> <description>discovering new optimisation techniques</description> <lastBuildDate>Fri, 11 Nov 2011 14:37:05 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.2.1</generator> <item><title>WP-DBManager Error</title><link>http://www.seoexploration.com/2011/09/wp-dbmanager-error/</link> <comments>http://www.seoexploration.com/2011/09/wp-dbmanager-error/#comments</comments> <pubDate>Wed, 07 Sep 2011 17:38:06 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[WordPress]]></category> <category><![CDATA[wordpress]]></category> <category><![CDATA[WP-DBManager]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=249</guid> <description><![CDATA[I have just migrated a wp site to a new host and all went well. I created a new database and imported the db backup from the old host. I then uploaded the home directory files which were backed up from the old host. I changed the &#8220;wp-configuration.php&#8220;  file settings  to reflect the new database, [...]]]></description> <content:encoded><![CDATA[<p>I have just migrated a wp site to a new host and all went well.</p><ul><li>I created a new database and imported the db backup from the old host.</li><li>I then uploaded the home directory files which were backed up from the old host.</li><li>I changed the &#8220;<strong>wp-configuration.php</strong>&#8220;  file settings  to reflect the new database, user id and password for the new host.</li><li>I changed the DNS settings on my domain name provider to reflect my new host details.</li></ul><p>All went really well, in fact it was the best migration to date and the new DNS settings switched in within an hour which was great.</p><p>However, when I checked that all the plugins etc. were functioning correctly I got the following error message on all my admin pages</p><p>“<strong>Error Warning: Your backup folder MIGHT be visible to the public</strong>”</p><p>The suggested fix from the plugin stated as follows</p><p>“<strong>To correct this issue, move the .htaccess file from wp-content/plugins/wp-dbmanager to /home/xxxxxxx/public_html/wp-content/backup-db</strong>”</p><p>Well, I’d seen this message many times before and the move as requested had always worked before so thought I must have dropped the “.htaccess” file in the move. Remember that the original file is &#8220;<strong>htaccess.txt</strong>&#8221; so you also have to change it to &#8220;<strong>.htaccess</strong>&#8221; when doing the move (or copy).</p><p>No, it was still there so I went back to my original host, zipped up the whole “<strong>public_html/wp-content/backup-db</strong>” directory and replaced the new host &#8220;backup-db&#8221; directory with it just in case something was corrupted in the migration .</p><p>No, the error message was still there so I realised I had to dig somewhat deeper.</p><p>Permissions on the directory? No all ok</p><p>I then looked at the actual setup of the plugin using the “<strong>DB Options</strong>” which you rarely visit once the plugin is configured.</p><p>That’s when I realised that there was an area that was still configured with data for the old host &#8211; my account name reflected as a directory. This is to be found in the  “<strong>Path To Backup</strong>:” setting.</p><p>Mine was set with the old path for my previous host<br
/> “<strong><span
style="color: #ff0000;">/home/domain/public_html</span></strong>/wp-content/backup-db”</p><p>I changed it to reflect my new host settings like this<br
/> “<strong><span
style="color: #ff0000;">/web/docroot/1111/domain.com/htdocs/</span></strong>wp-content/backup-db”</p><p>After the change and reseting the page, the message disappeared.</p><p>I tested full functionally of the plugin without any problems and I would add that this plugin from <a
title="Visit author homepage" href="http://lesterchan.net/portfolio/programming/php/#wp-dbmanager">Lester &#8216;GaMerZ&#8217; Chan</a>  is still great, I have been using it now for many years, thank you Lester.</p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2011/09/wp-dbmanager-error/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Yoast WordPress SEO export settings problem</title><link>http://www.seoexploration.com/2011/08/yoast-wordpress-seo-export-settings-problem/</link> <comments>http://www.seoexploration.com/2011/08/yoast-wordpress-seo-export-settings-problem/#comments</comments> <pubDate>Thu, 11 Aug 2011 20:13:52 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Website Optimization]]></category> <category><![CDATA[WordPress]]></category> <category><![CDATA[Joost de Valk]]></category> <category><![CDATA[WordPress SEO]]></category> <category><![CDATA[wp]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=235</guid> <description><![CDATA["wordpress seo" plugin failure when exporting settings - with error pointing to a problem in “wordpress-seo/inc/wpseo-non-ajax-functions.php”]]></description> <content:encoded><![CDATA[<p>I have found that one of the best SEO plugins for Word Press is  <a
title="WordPress SEO" href="http://yoast.com/wordpress/seo/" target="_blank"><strong>WordPress SEO</strong></a> which is yet another of  <a
title="Visit author homepage" href="http://yoast.com/">Joost de Valk&#8217;s</a> many good WP plugins.</p><p>I started to use it some months ago and apart from the learning curve that always has to be passed through I found it quite intuitive and documentation enough to do the job. All on all one of the best &#8220;<strong>free</strong>&#8221; SEO  packages around.</p><p>Today I was faced with opening two new WP sites and I&#8217;m designing the themes for each so I just wanted a few plugins to get me going. I loaded WordPress SEO and started to configure the standard setting which are pretty much the same for all my sites and as I was tidying up thought I may as well use the settings export facility so I can import for the second website.<br
/> Unfortunately when you try to export it comes up with an error</p><p><span
style="color: #0000ff;"><em>Warning: chdir() [function.chdir]: No such file or directory (errno 2) in /home/</em>xxxxxxx<em>/public_html/www.</em>yyyyyyyyyyyy<em>.com/wp-content/plugins/<strong>wordpress-seo/inc/wpseo-non-ajax-functions.php on line 90</strong></em></span></p><p>This is when I remembered that I&#8217;d tried this some while ago with the same result &#8211; what a bummer. This time I resolved to try and find a fix and not being a PHP expert this meant searching the internet.</p><p>This time I struck gold after about half an hour searching.</p><p>I take no credit for the work but I did what the patch suggested and it works a treat but remember his warning <span
style="color: #000000;"><strong>&#8220;Try out at your own risk&#8221;</strong>.</span>&#8230;</p><p>The patch applies to the file located in the plugin directory <strong> &#8220;wordpress-seo/inc/wpseo-non-ajax-functions.php&#8221;</strong></p><p>This is the fix verbatim:-</p><div><div><p
style="padding-left: 60px;"><span
style="color: #800000;">There is a subtitle difference in that the dir must be an OS path when creating the file and a url when returning the file for download.</span><br
/> <span
style="color: #800000;"> There should also be a leading / on settings.ini and settings.zip</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">Here is my workaround. Try out at your own risk.</span><br
/> <span
style="color: #800000;"> NOTE: I have not tested the resulting import yet.</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">Additions market with &gt; starting from line 80. Mods marked with |</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">&gt; $upload_dir = wp_upload_dir();</span><br
/> <span
style="color: #800000;"> &gt; $wpseo_upload_path = $upload_dir['path'];</span><br
/> <span
style="color: #800000;"> &gt; $wpseo_upload_url = $upload_dir['url'];</span><br
/> <span
style="color: #800000;"> | if ( !$handle = fopen( $wpseo_upload_path.&#8217;/settings.ini&#8217;, &#8216;w&#8217; ) )</span><br
/> <span
style="color: #800000;"> die();</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">if ( !fwrite($handle, $content) )</span><br
/> <span
style="color: #800000;"> die();</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">fclose($handle);</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">require_once (ABSPATH . &#8216;wp-admin/includes/class-pclzip.php&#8217;);</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">| chdir($wpseo_upload_path);</span><br
/> <span
style="color: #800000;"> $zip = new PclZip(&#8216;./settings.zip&#8217;);</span><br
/> <span
style="color: #800000;"> if ($zip-&gt;create(&#8216;./settings.ini&#8217;) == 0)</span><br
/> <span
style="color: #800000;"> return false;</span></p><p
style="padding-left: 60px;"><span
style="color: #800000;">| return $wpseo_upload_url.&#8217;/settings.zip&#8217;;</span></p></div></div><p>And the guy we should all thank for it is known as <a
title="SETUPTIPS" href="http://wordpress.org/support/profile/setuptips" target="_blank"><strong>setuptips</strong></a>  and a member of the WordPress.org Forums.</p><p>&nbsp;</p><p>&nbsp;</p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2011/08/yoast-wordpress-seo-export-settings-problem/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>7 Steps to Building the Right Social Media Connections</title><link>http://www.seoexploration.com/2011/01/building-the-right-social-media-connections/</link> <comments>http://www.seoexploration.com/2011/01/building-the-right-social-media-connections/#comments</comments> <pubDate>Mon, 17 Jan 2011 10:11:47 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Social SEO]]></category> <category><![CDATA[facebook]]></category> <category><![CDATA[networking events]]></category> <category><![CDATA[professional organizations]]></category> <category><![CDATA[social networking sites]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=231</guid> <description><![CDATA[By Angelique L. Rewers (c) 2011 Once upon a time, it seemed as though the number of &#8220;followers&#8221; or &#8220;connections&#8221; a person had on social networking sites like Twitter, Facebook, and LinkedIn was akin to the number of votes they had for homecoming king or queen. It was the adult version of a high school [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: justify;"><strong><em>By Angelique L. Rewers (c) 2011</em></strong></p><p>Once upon a time, it seemed as though the number of &#8220;followers&#8221; or &#8220;connections&#8221; a person had on social networking sites like Twitter, Facebook, and LinkedIn was akin to the number of votes they had for homecoming king or queen. It was the adult version of a high school popularity contest.</p><p>However, as these websites have now matured &#8211; and as entrepreneurs and business owners have figured out how and how not to use them &#8211; most everyone has come to realize that it&#8217;s not about the number of connections you have, but the number of right connections.</p><p>Just like in the real world, you want to make sure you&#8217;re making the most of your networking time by connecting with those people that have similar or complementary interests or expertise and, therefore, create a mutually beneficial relationship &#8211; particularly when sites like Facebook limit your number of friends to only 5,000. In fact, many people who have large followings of the wrong people are taking the drastic step of deleting their connections and starting over from scratch.</p><p>Whether you&#8217;re just getting started building your social media network or you&#8217;re a seasoned pro, who&#8217;s thinking about doing a major overhaul, here are seven steps you can take to help you build the right connections.</p><p>1.) Start With the People You Know. If you&#8217;re still not using social media and are hesitant to get started, the best way to get your feet wet is by connecting with those you know personally: your friends, your family, your neighbors, and your co-workers. But don&#8217;t stop there; your network is likely a lot bigger than you might think. Don&#8217;t forget about your former co-workers, your connections through professional organizations to which you belong, your clients or customers, members of your mastermind communities and even vendors with whom you&#8217;ve done business.</p><p>2.) Add the New People You Meet. Not so long ago (unless you were in sales), the majority of the business cards you collected at networking events, conferences, trade shows and other professional development opportunities probably went in the garbage can the next day. Today, however, there&#8217;s no excuse for not taking a few minutes to extend the life of those connections by sending social media invites the very next day. Be sure to remind the person who you are by referencing something from your conversation or by providing a piece of follow-up information that you promised.</p><p>3.) Follow Your Followers&#8217; Followers. Check out the connections and followers of your colleagues, peers, friends, etc. On Twitter you can easily see who your friends are following, as well as who is following them. Facebook automatically provides suggestions of people you might want to add because you have a lot of shared connections. In LinkedIn you may need to ask your connection to make an introduction. In any case, if you have things in common with your networkers, it stands to reason that a good portion of their followers is also worth following. Just be sure not to &#8220;spam&#8221; your connections&#8217; lists.</p><p>4.) Broaden Your Reach. Extend invitations to people in groups to which you belong in both the real and online worlds, such as professional organizations. On LinkedIn you can connect with the folks you &#8220;meet&#8221; through LinkedIn Groups. And on Facebook you can make connections when you&#8217;re invited to attend an event or when you join someone&#8217;s fan page.</p><p>5.) Follow the Experts. We&#8217;re constantly learning from experts in our respective industries. Why not reach out to these folks in the social media world? Maybe you&#8217;ve just read a great book. See what the author has to say on Twitter. Or maybe you&#8217;ve received a brochure for an upcoming conference that you&#8217;d love to attend but can&#8217;t. Before you throw the brochure in the trash, search for the speakers&#8217; names on social networking sites and send them an invitation to connect. Let them know that you saw their session description for the conference and you&#8217;re disappointed you&#8217;re going to miss it, but would love to keep track of where else they might be speaking.</p><p>6.) Do Some Digging. Don&#8217;t forget to take the time to search for people who share similar interests as you or who would be an ideal customer for your business. Granted, this is the most time consuming of all the methods. But it will give you the chance to unearth new sources, experts and connections that will add value to your business and who you might not otherwise have ever &#8220;met.&#8221; Be on the lookout for bloggers, reporters, and analysts who cover your company or industry.</p><p>7.) Invite Others to Follow You. To truly create an online &#8220;relationship&#8221; it needs to be a two-way street. One of the best ways to encourage others to follow you is by showing that you will provide value to them. In other words, be worthy of their time. Start by ensuring your online profiles are professional (i.e. no avatar photos) and accurately describe who you are, what you do, and what topics you&#8217;re interested in. Provide content and commentary that matches that profile, is timely and doesn&#8217;t spam. Promoting is fine so long as it&#8217;s balanced with valuable content. Link to blog posts, videos and articles your followers would find interesting. Ask questions<br
/> and provide insightful comments on other people&#8217;s posts. Make it easy for others to follow you by providing &#8220;follow me&#8221; widgets on your website, blog posts, article archives, and podcasts.</p><p>Remember: It&#8217;s not about the number of connections you have on these sites &#8211; it&#8217;s about the quality of those connections. Today, people are looking for authenticity. They want to meet real people with real things to say who will add value to their personal and professional lives.</p><p>Are you doing something interesting to find valuable contacts on social media sites? Leave us a comment and let us know what strategies are working for you!</p><p
style="text-align: justify;"><strong><em>By Angelique Rewers, ABC, APR &#8211; Richer. Smarter. Happier. </em></strong><br
/> The Queen of Clarity &#8211; Angelique Rewers, ABC, APR, harnesses her extensive experience working with Fortune 500 companies to help solopreneurs clarify their marketing focus so they can build a business that makes them happy and makes them money. If you&#8217;re looking for simple, low-cost ways to boost your sales, get Free marketing *Brilliance!* now at: <a
href="http://www.richersmarterhappier.com/brilliance_ezine.htm">http://www.richersmarterhappier.com/brilliance_ezine.htm</a></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2011/01/building-the-right-social-media-connections/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Caching Tutorial</title><link>http://www.seoexploration.com/2010/05/caching-tutorial/</link> <comments>http://www.seoexploration.com/2010/05/caching-tutorial/#comments</comments> <pubDate>Fri, 28 May 2010 21:51:36 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Website Optimization]]></category> <category><![CDATA[browser caches]]></category> <category><![CDATA[cache control]]></category> <category><![CDATA[freshness]]></category> <category><![CDATA[meta tags]]></category> <category><![CDATA[proxy caches]]></category> <category><![CDATA[web cache]]></category> <category><![CDATA[web caches]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=170</guid> <description><![CDATA[I came across this tutorial which I found extremely useful and my thanks and appreciation go to the author Mark Nottingham &#60;mnot@pobox.com&#62;. Copied from mnot.net for Web Authors and Webmasters This is an informational document. Although technical in nature, it attempts to make the concepts involved understandable and applicable in real-world situations. Because of this, some [...]]]></description> <content:encoded><![CDATA[<p
style="text-align: center;"><strong><em>I came across this tutorial which I found extremely useful</em><em><br
/> and my thanks and appreciation go to the author</em><em><br
/> Mark Nottingham &lt;<a
href="mailto:mnot@pobox.com">mnot@pobox.com</a>&gt;.<strong><em><br
/> Copied from <a
title="Caching  Tutorial" href="http://www.mnot.net/cache_docs/" target="_blank">mnot.net</a> <a
title="Caching  Tutorial" href="http://www.mnot.net/cache_docs/" target="_blank"><br
/> </a></em></strong></em></strong></p><h3>for Web Authors and Webmasters</h3><p
style="text-align: justify;">This is an informational document. Although technical in nature, it attempts to make the concepts involved understandable and applicable in real-world situations. Because of this, some aspects of the material are simplified or omitted, for the sake of clarity. If you are interested in the minutia of the subject, please explore the <a
href="#REF">References and Further Information</a> at the end.<br
/> <a
id="TOC"></a></p><ol
class="TOC"><li
class="TOC"><a
href="#DEFINITION">What’s a Web Cache? Why do people use them?</a></li><li
class="TOC"><a
href="#KINDS">Kinds of Web Caches</a><ol
class="SUBTOC"><li
class="SUBTOC"><a
href="#BROWSER">Browser Caches</a></li><li
class="SUBTOC"><a
href="#PROXY">Proxy Caches</a></li></ol></li><li
class="TOC"><a
href="#WHY">Aren’t Web Caches bad for me? Why should I help them?</a></li><li
class="TOC"><a
href="#WORK">How Web Caches Work</a></li><li
class="TOC"><a
href="#CONTROL">How (and how not) to Control Caches</a><ol
class="SUBTOC"><li
class="SUBTOC"><a
href="#META">HTML Meta Tags vs. HTTP Headers</a></li><li
class="SUBTOC"><a
href="#PRAGMA">Pragma HTTP Headers (and why they don’t work)</a></li><li
class="SUBTOC"><a
href="#EXPIRES">Controlling Freshness with the Expires HTTP Header</a></li><li
class="SUBTOC"><a
href="#CACHE-CONTROL">Cache-Control HTTP Headers</a></li><li
class="SUBTOC"><a
href="#VALIDATE">Validators and Validation</a></li></ol></li><li
class="TOC"><a
href="#TIPS">Tips for Building a Cache-Aware Site</a></li><li
class="TOC"><a
href="#SCRIPT">Writing Cache-Aware Scripts</a></li><li
class="TOC"><a
href="#FAQ">Frequently Asked Questions</a></li><li
class="TOC"><a
href="#IMP-SERVER">Implementation Notes — Web Servers</a></li><li
class="TOC"><a
href="#IMP-SCRIPT">Implementation Notes — Server-Side Scripting</a></li><li
class="TOC"><a
href="#REF">References and Further Information</a></li><li
class="TOC"><a
href="#ABOUT">About This Document</a></li></ol><h2><a
id="DEFINITION">What’s a Web Cache? Why do people use them?</a></h2><p
style="text-align: justify;">A <em>Web cache</em> sits between one or more Web servers (also known as <em>origin servers</em>) and a client or many clients, and watches requests come by, saving copies of the responses — like HTML pages, images and files (collectively known as <em>representations</em>) — for itself. Then, if there is another request for the same URL, it can use the response that it has,instead of asking the origin server for it again.</p><p
style="text-align: justify;">There are two main reasons that Web caches are used:</p><ul
style="text-align: justify;"><li>To <strong>reduce latency</strong> — Because the request is satisfied from the cache (which is closer to the client) instead of the origin server, it takes less time for it to get the representation and display it. This makes the Web seem more responsive.</li><li>To <strong>reduce network traffic</strong> — Because representations are reused, it reduces the amount of bandwidth used by a client. This saves money if the client is paying for traffic, and keeps their bandwidth requirements lower and more manageable.</li></ul><h2 style="text-align: justify;"><a
id="KINDS">Kinds of Web Caches</a></h2><h3 style="text-align: justify;"><a
id="BROWSER">Browser Caches</a></h3><p
style="text-align: justify;">If you examine the preferences dialog of any modern Web browser (like Internet Explorer, Safari or Mozilla), you’ll probably notice a “cache” setting. This lets you set aside a section of your computer’s hard disk to store representations that you’ve seen, just for you. The browser cache works according to fairly simple rules. It will check to make sure that the representations are fresh, usually once a session (that is, the once in the current invocation of the browser).</p><p
style="text-align: justify;">This cache is especially useful when users hit the “back” button or click a link to see a page they’ve just looked at. Also, if you use the same navigation images throughout your site, they’ll be served from browsers’ caches almost instantaneously.</p><h3 style="text-align: justify;"><a
id="PROXY">Proxy Caches</a></h3><p
style="text-align: justify;">Web proxy caches work on the same principle, but a much larger scale. Proxies serve hundreds or thousands of users in the same way; large corporations and ISPs often set them up on their firewalls, or as standalone devices (also known as <em>intermediaries</em>).</p><p
style="text-align: justify;">Because proxy caches aren’t part of the client or the origin server, but instead are out on the network, requests have to be routed to them somehow. One way to do this is to use your browser’s proxy setting to manually tell it<br
/> what proxy to use; another is using interception. <em>Interception proxies</em> have Web requests redirected to them by the underlying network itself, so that clients don’t need to be configured for them, or even know about them.</p><p
style="text-align: justify;">Proxy caches are a type of <em>shared cache</em>; rather than just having one person using them, they usually have a large number of users, and because of this they are very good at reducing latency and network traffic. That’s because popular representations are reused a number of times.</p><h3 style="text-align: justify;"><a
id="GATEWAY">Gateway Caches</a></h3><p
style="text-align: justify;">Also known as “reverse proxy caches” or “surrogate caches,” gateway caches are also intermediaries, but instead of being deployed by network administrators to save bandwidth, they’re typically deployed by Webmasters themselves, to make their sites more scalable, reliable and better performing.</p><p
style="text-align: justify;">Requests can be routed to gateway caches by a number of methods, but typically some form of load balancer is used to make one or more of them look like the origin server to clients.</p><p
style="text-align: justify;"><em>Content delivery networks</em> (CDNs) distribute gateway caches throughout the Internet (or a part of it) and sell caching to interested Web sites. <a
class="offsite" href="http://www.speedera.com/">Speedera</a> and <a
class="offsite" href="http://www.akamai.com/">Akamai</a> are examples of CDNs.</p><p
style="text-align: justify;">This tutorial focuses mostly on browser and proxy caches, although some of the information is suitable for those interested in gateway caches as well.</p><h2 style="text-align: justify;"><a
id="WHY">Aren’t Web Caches bad for me? Why should I help them?</a></h2><p
style="text-align: justify;">Web caching is one of the most misunderstood technologies on the Internet. Webmasters in particular fear losing control of their site, because a proxy cache can “hide” their users from them, making it difficult to see who’s using the site.</p><p
style="text-align: justify;">Unfortunately for them, even if Web caches didn’t exist, there are too many variables on the Internet to assure that they’ll be able to get an accurate picture of how users see their site. If this is a big concern for you, this tutorial will teach you how to get the statistics you need without making your site cache-unfriendly.</p><p
style="text-align: justify;">Another concern is that caches can serve content that is out of date, or<em> stale</em>. However, this tutorial can show you how to configure your server to control how your content is cached.</p><p
class="callout right" style="text-align: justify;"><abbr
title="Content Delivery Networks">CDNs</abbr><br
/> are an interesting development, because unlike many proxy caches, their gateway caches are aligned with the interests of the Web site being cached, so that these problems aren’t seen. However, even when you use a CDN, you still have to consider that there will be proxy and browser caches downstream.</p><p
style="text-align: justify;">On the other hand, if you plan your site well, caches can help your Web site load faster, and save load on your server and Internet link. The difference can be dramatic; a site that is difficult to cache may take several seconds to load, while one that takes advantage of caching can seem instantaneous in comparison. Users will appreciate a fast-loading site, and will visit more often.</p><p
style="text-align: justify;">Think of it this way; many large Internet companies are spending millions of dollars setting up farms of servers around the world to replicate their content, in order to make it as fast to access as possible for their users. Caches do the same for you, and they’re even closer to the end user. Best of all, you don’t have to pay for them.</p><p
style="text-align: justify;">The fact is that proxy and browser caches will be used whether you like it or not. If you don’t configure your site to be cached correctly, it will be cached using whatever defaults the cache’s administrator decides upon.</p><h2 style="text-align: justify;"><a
id="WORK">How Web Caches Work</a></h2><p
style="text-align: justify;">All caches have a set of rules that they use to determine when to serve a representation from the cache, if it’s available. Some of these rules are set in the protocols (HTTP 1.0 and 1.1), and some are set by the administrator of the cache (either the user of the browser cache, or the proxy administrator).</p><p
style="text-align: justify;">Generally speaking, these are the most common rules that are followed (don’t worry if you don’t understand the details, it will be explained below):</p><div
class="ol" style="text-align: justify;"><ol><li>If the response’s headers tell the cache not to keep it, it won’t.</li><li>If the request is authenticated or secure (i.e., HTTPS), it won’t be cached.</li><li>A cached representation is considered <em>fresh</em> (that is, able to be sent to a client without checking with the origin server) if:<ul><li>It has an expiry time or other age-controlling header set, and is still within the fresh period, or</li><li>If the cache has seen the representation recently, and it was modified relatively long ago.</li></ul><p>Fresh representations are served directly from the cache, without checking with the origin server.</li><li>If an representation is stale, the origin server will be asked to<em> validate</em> it, or tell the cache whether the copy that it has is still good.</li><li>Under certain circumstances — for example, when it’s disconnected from a network — a cache can serve stale responses without checking with the origin server.</li></ol><p>If no validator (an <code>ETag</code> or <code>Last-Modified</code> header) is present on a response, <em>and</em> it doesn&#8217;t have any explicit freshness information, it will usually — but not always — be considered uncacheable.</p></div><p
style="text-align: justify;">Together, <em>freshness</em> and <em>validation</em> are the most important ways that a cache works with content. A fresh representation will be available instantly from the cache, while a validated representation will avoid sending the entire representation over again if it hasn’t changed.</p><h2 style="text-align: justify;"><a
id="CONTROL">How (and how not) to Control Caches</a></h2><p
style="text-align: justify;">There are several tools that Web designers and Webmasters can use to fine-tune how caches will treat their sites. It may require getting your hands a little dirty with your server’s configuration, but the results are worth it.<br
/> For details on how to use these tools with your server, see the <a
href="#IMP-SERVER">Implementation</a> sections below.</p><h3 style="text-align: justify;"><a
id="META">HTML Meta Tags and HTTP Headers</a></h3><p
style="text-align: justify;">HTML authors can put tags in a document’s &lt;HEAD&gt; section that describe its attributes. These <em>meta tags</em> are often used in the belief that they can mark a document as uncacheable, or expire it at a certain time.</p><p
style="text-align: justify;">Meta tags are easy to use, but aren’t very effective. That’s because they’re only honored by a few browser caches (which actually read the HTML), not proxy caches (which almost never read the HTML in the document). While it may be tempting to put a Pragma: no-cache meta tag into a Web page, it won’t necessarily cause it to be kept fresh.</p><p
class="callout right" style="text-align: justify;">If your site is hosted at an ISP or hosting farm and they don’t give you the ability to set arbitrary HTTP headers (like <code>Expires</code> and<code> Cache-Control</code>), complain loudly; these are tools necessary for doing your job.</p><p
style="text-align: justify;">On the other hand, true <em>HTTP headers</em> give you a lot of control over how both browser caches and proxies handle your representations. They can’t be seen in the HTML, and are usually automatically generated by the Web<br
/> server. However, you can control them to some degree, depending on the server you use. In the following sections, you’ll see what HTTP headers are interesting, and how to apply them to your site.</p><p
style="text-align: justify;">HTTP headers are sent by the server before the HTML, and only seen by the browser and any intermediate caches. Typical HTTP 1.1 response headers might look like this:</p><pre class="example" style="padding-left: 30px; text-align: justify;">HTTP/1.1 200 OK
Date: Fri, 30 Oct 1998 13:19:41 GMT
Server: Apache/1.3.3 (Unix)
Cache-Control: max-age=3600, must-revalidate
Expires: Fri, 30 Oct 1998 14:19:41 GMT
Last-Modified: Mon, 29 Jun 1998 02:28:12 GMT
ETag: "3e86-410-3596fbbc"
Content-Length: 1040
Content-Type: text/html</pre><p
style="text-align: justify;">The HTML would follow these headers, separated by a blank line. See the <a
href="#IMP-SERVER">Implementation</a> sections for information about how to set HTTP headers.</p><h3 style="text-align: justify;"><a
id="PRAGMA">Pragma HTTP Headers (and why they don’t work)</a></h3><p
style="text-align: justify;">Many people believe that assigning a <code>Pragma: no-cache</code> HTTP header to a representation will make it uncacheable. This is not necessarily true; the HTTP specification does not set any guidelines for Pragma response headers; instead, Pragma request headers (the headers that a browser sends to a server) are discussed. Although a few caches may honor this header, the majority won’t, and it won’t have any effect. Use the headers below instead.</p><h3 style="text-align: justify;"><a
id="EXPIRES">Controlling Freshness with the Expires HTTP Header</a></h3><p
style="text-align: justify;">The <code>Expires</code> HTTP header is a basic means of controlling caches; it tells all caches how long the associated representation is fresh for. After that time, caches will always check back with the origin server to see if a document is changed. <code>Expires</code> headers are supported by practically every cache.</p><p
style="text-align: justify;">Most Web servers allow you to set <code>Expires</code> response headers in a number of ways. Commonly, they will allow setting an absolute time to expire, a time based on the last time that the client retrieved the representation (last <em>access time</em>), or a time based on the last time the document changed on your server (last <em>modification time</em>).</p><p
style="text-align: justify;"><code>Expires</code> headers are especially good for making static images (like navigation bars and buttons) cacheable. Because they don’t change much, you can set extremely long expiry time on them, making your site appear much more responsive to your users. They’re also useful for controlling caching of a page that is regularly changed. For instance, if you update a news page once a day at 6am, you can set the representation to expire at that time, so caches will know when to get a fresh copy, without users having to hit ‘reload’.</p><p
style="text-align: justify;">The <strong>only</strong> value valid in an <code>Expires</code> header is a HTTP date; anything else will most likely be interpreted as ‘in the past’, so that the representation is uncacheable. Also, remember that the time in a HTTP date is Greenwich Mean Time (GMT), not local time.</p><p
style="text-align: justify;">For example:</p><pre style="padding-left: 30px; text-align: justify;"><span class="example">Expires: Fri, 30 Oct 1998 14:19:41 GMT</span></pre><p
class="callout right" style="text-align: justify;">It’s important to make sure that your Web server’s clock is accurate if you use the <code>Expires</code> header. One way to do this is using the <a
class="offsite" href="http://www.ntp.org/">Network Time Protocol</a> (NTP); talk to your local system administrator to find out more.</p><p
style="text-align: justify;">Although the <code>Expires</code> header is useful, it has some limitations. First, because there’s a date involved, the clocks on the Web server and the cache must be synchronised; if they have a different idea of the time, the intended<br
/> results won’t be achieved, and caches might wrongly consider stale content as fresh.</p><p
style="text-align: justify;">Another problem with <code>Expires</code> is that it’s easy to forget that you’ve set some content to expire at a particular time. If you don’t update an <code>Expires</code> time before it passes, each and every request will go back to your Web server, increasing load and latency.</p><h3 style="text-align: justify;"><a
id="CACHE-CONTROL">Cache-Control HTTP Headers</a></h3><p
style="text-align: justify;">HTTP 1.1 introduced a new class of headers, <code>Cache-Control</code> response headers, to give Web publishers more control over their content, and to address the limitations of <code>Expires</code>.</p><p
style="text-align: justify;">Useful <code>Cache-Control</code> response headers include:</p><ul
style="text-align: justify;"><li><strong><code>max-age=</code></strong>[seconds] — specifies the maximum amount of time that an representation will be considered fresh. Similar to <code>Expires</code>, this directive is relative to the time of the request, rather than absolute. [seconds] is the number of seconds from the time of the request you wish the representation to be fresh for.</li><li><strong><code>s-maxage=</code></strong>[seconds] — similar to <code>max-age</code>, except that it only applies to shared (e.g., proxy) caches.</li><li><strong><code>public</code></strong> — marks authenticated responses as cacheable; normally, if HTTP authentication is required, responses are automatically private.</li><li><strong><code>private</code></strong> — allows caches that are specific to one user (e.g., in a browser) to store the response; shared caches (e.g., in a proxy) may not.</li><li><strong><code>no-cache</code></strong> — forces caches to submit the request to the origin server for validation before releasing a cached copy, every time. This is useful to assure that authentication is respected (in combination with public), or to maintain rigid freshness, without sacrificing all of the benefits of caching.</li><li><strong><code>no-store</code></strong> — instructs caches not to keep a copy of the representation under any conditions.</li><li><strong><code>must-revalidate</code></strong> — tells caches that they must obey any freshness information you give them about a representation. HTTP allows caches to serve stale representations under special conditions; by specifying this header, you’re telling the cache that you want it to strictly follow your rules.</li><li><strong><code>proxy-revalidate</code></strong> — similar to <code>must-revalidate</code>, except that it only applies to proxy caches.</li></ul><p
style="text-align: justify;">For example:</p><pre style="padding-left: 30px; text-align: justify;"><span class="example">Cache-Control: max-age=3600, must-revalidate</span></pre><p
style="text-align: justify;">If you plan to use the <code>Cache-Control</code> headers, you should have a look at the excellent documentation in HTTP 1.1; see <a
href="#REF">References and Further Information</a>.</p><h3 style="text-align: justify;"><a
id="VALIDATE">Validators and Validation</a></h3><p
style="text-align: justify;">In <a
href="#WORK">How Web Caches Work</a>, we said that validation is used by servers and caches to communicate when an representation has changed. By using it, caches avoid having to download the entire representation when they already have a copy locally, but they’re not sure if it’s still fresh.</p><p
style="text-align: justify;">Validators are very important; if one isn’t present, and there isn’t any freshness information (<code>Expires</code> or <code>Cache-Control</code>) available, caches will not store a representation at all.</p><p
style="text-align: justify;">The most common validator is the time that the document last changed, as communicated in <code>Last-Modified</code> header. When a cache has an representation stored that includes a <code>Last-Modified</code> header, it can use it to ask the server if the representation has changed since the last time it was seen, with an <code>If-Modified-Since</code> request.</p><p
style="text-align: justify;">HTTP 1.1 introduced a new kind of validator called the <em>ETag</em>. ETags are unique identifiers that are generated by the server and changed every time the representation does. Because the server controls how the ETag is generated, caches can be surer that if the ETag matches when they make a<code> If-None-Match</code> request, the representation really is the same.</p><p
style="text-align: justify;">Almost all caches use Last-Modified times in determining if an representation is fresh; ETag validation is also becoming prevalent.</p><p
style="text-align: justify;">Most modern Web servers will generate both <code>ETag</code> and <code>Last-Modified</code> headers to use as validators for static content (i.e., files) automatically; you won’t have to do anything. However, they don’t know enough about dynamic content (like CGI, ASP or database sites) to generate them; see <a
href="#SCRIPT">Writing Cache-Aware Scripts</a>.</p><h2 style="text-align: justify;"><a
id="TIPS">Tips for Building a Cache-Aware Site</a></h2><p
style="text-align: justify;">Besides using freshness information and validation, there are a number of other things you can do to make your site more cache-friendly.</p><ul
style="text-align: justify;"><li><strong>Use URLs consistently</strong> — this is the golden rule of caching. If you serve the same content on different pages, to different users, or from different sites, it should use the same URL.<br
/> This is the easiest and most effective way to make your site cache-friendly. For example, if you use “/index.html” in your HTML as a reference once, always use it that way.</li><li><strong>Use a common library of images</strong> and other elements and refer back to them from different places.</li><li><strong>Make caches store images and pages that don’t change often</strong> by using a <code>Cache-Control: max-age</code> header with a large value.</li><li><strong>Make caches recognise regularly updated pages</strong> by specifying an appropriate max-age or expiration time.</li><li><strong>If a resource (especially a downloadable file) changes, change its name.</strong> That way, you can make it expire far in the future, and still guarantee that the correct version is served; the page that links to it is the only one that will need a short expiry time.</li><li><strong>Don’t change files unnecessarily.</strong> If you do, everything will have a falsely young <code>Last-Modified</code> date. For instance, when updating your site, don’t copy over the entire site; just move the files that you’ve changed.</li><li><strong>Use cookies only where necessary</strong> — cookies are difficult to cache, and aren’t needed in most situations. If you must use a cookie, limit its use to dynamic pages.</li><li><strong>Minimize use of SSL</strong> — because encrypted pages are not stored by shared caches, use them only when you have to, and use images on SSL pages sparingly.</li><li><strong>Check your pages with <a
href="http://redbot.org/">REDbot</a></strong> — it can help you apply many of the concepts in this tutorial.</li></ul><h2 style="text-align: justify;"><a
id="SCRIPT">Writing Cache-Aware Scripts</a></h2><p
style="text-align: justify;">By default, most scripts won’t return a validator (a <code>Last-Modified</code> or <code>ETag</code> response header) or freshness information (<code>Expires</code> or <code>Cache-Control</code>). While some scripts really are dynamic (meaning that they return a different response for every request), many (like search engines and database-driven sites) can benefit from being cache-friendly.</p><p
style="text-align: justify;">Generally speaking, if a script produces output that is reproducible with the same request at a later time (whether it be minutes or days later), it should be cacheable. If the content of the script changes only depending on what’s in the URL, it is cacheble; if the output depends on a cookie, authentication information or other external criteria, it probably isn’t.</p><ul
style="text-align: justify;"><li>The best way to make a script cache-friendly (as well as perform better) is to dump its content to a plain file whenever it changes. The Web server can then treat it like any other Web page, generating and using validators, which makes your life easier. Remember to only write files that have changed, so the <code>Last-Modified</code> times are preserved.</li><li>Another way to make a script cacheable in a limited fashion is to set an age-related header for as far in the future as practical. Although this can be done with <code>Expires</code>, it’s probably easiest to do so with<code> Cache-Control: max-age</code>, which will make the request fresh for an amount of time after the request.</li><li>If you can’t do that, you’ll need to make the script generate a validator, and then respond to <code>If-Modified-Since</code> and/or <code>If-None-Match</code> requests. This can be done by parsing the HTTP headers, and then responding with <code>304 Not Modified</code> when appropriate. Unfortunately, this is not a trival task.</li></ul><p
style="text-align: justify;">Some other tips;</p><ul
style="text-align: justify;"><li><strong>Don’t use POST</strong> unless it’s appropriate. Responses to the POST method aren’t kept by most caches; if you send information in the path or query (via GET), caches can store that information for the future.</li><li><strong>Don’t embed user-specific information in the URL</strong> unless the content generated is completely unique to that user.</li><li><strong>Don’t count on all requests from a user coming from the same host</strong>, because caches often work together.</li><li><strong>Generate <code>Content-Length</code> response headers.</strong> It’s easy to do, and it will allow the response of your script to be used in a<em> persistent connection</em>. This allows clients to request multiple representations on one TCP/IP connection, instead of setting up a connection for every request. It makes your site seem much faster.</li></ul><p
style="text-align: justify;">See the <a
href="#IMP-SCRIPT">Implementation Notes</a> for more specific<br
/> information.</p><h2><a
id="FAQ">Frequently Asked Questions</a></h2><h3>What are the most important things to make cacheable?</h3><p>A good strategy is to identify the most popular, largest representations<br
/> (especially images) and work with them first.</p><h3>How can I make my pages as fast as possible with caches?</h3><p>The most cacheable representation is one with a long freshness time set.<br
/> Validation does help reduce the time that it takes to see a representation,<br
/> but the cache still has to contact the origin server to see if it’s fresh. If<br
/> the cache already knows it’s fresh, it will be served directly.</p><h3>I understand that caching is good, but I need to keep statistics on how<br
/> many people visit my page!</h3><p>If you must know every time a page is accessed, select ONE small item on<br
/> a page (or the page itself), and make it uncacheable, by giving it a suitable<br
/> headers. For example, you could refer to a 1&#215;1 transparent uncacheable image<br
/> from each page. The <code>Referer</code> header will contain information about what page<br
/> called it.</p><p>Be aware that even this will not give truly accurate statistics about your<br
/> users, and is unfriendly to the Internet and your users; it generates<br
/> unnecessary traffic, and forces people to wait for that uncached item to be<br
/> downloaded. For more information about this, see On Interpreting Access<br
/> Statistics in the <a
href="#REF">references</a>.</p><h3>How can I see a representation’s HTTP headers?</h3><p>Many Web browsers let you see the <code>Expires</code> and <code>Last-Modified</code> headers are in<br
/> a “page info” or similar interface. If available, this will give you a menu of<br
/> the page and any representations (like images) associated with it, along with<br
/> their details.</p><p>To see the full headers of a representation, you can manually connect to<br
/> the Web server using a Telnet client.</p><p>To do so, you may need to type the port (be default, 80) into a separate<br
/> field, or you may need to connect to <code>www.example.com:80</code> or <code>www.example.com 80</code><br
/> (note the space). Consult your Telnet client’s documentation.</p><p>Once you’ve opened a connection to the site, type a request for the<br
/> representation. For instance, if you want to see the headers for<br
/> <code>http://www.example.com/foo.html</code>, connect to <code>www.example.com</code>, port <code>80</code>, and<br
/> type:</p><pre class="example">GET /foo.html HTTP/1.1 [return]
Host: www.example.com [return][return]</pre><p>Press the Return key every time you see <code>[return]</code>; make sure to press it<br
/> twice at the end. This will print the headers, and then the full<br
/> representation. To see the headers only, substitute HEAD for GET.</p><h3>My pages are password-protected; how do proxy caches deal with them?</h3><p>By default, pages protected with HTTP authentication are considered private;<br
/> they will not be kept by shared caches. However, you can make authenticated<br
/> pages public with a Cache-Control: public header; HTTP 1.1-compliant caches will then<br
/> allow them to be cached.</p><p>If you’d like such pages to be cacheable, but still authenticated for every<br
/> user, combine the <code>Cache-Control: public</code> and <code>no-cache</code> headers. This tells the<br
/> cache that it must submit the new client’s authentication information to the<br
/> origin server before releasing the representation from the cache. This would look like:</p><pre><span class="example">Cache-Control: public, no-cache</span></pre><p>Whether or not this is done, it’s best to minimize use of authentication;<br
/> for example, if your images are not sensitive, put them in a separate<br
/> directory and configure your server not to force authentication for it. That<br
/> way, those images will be naturally cacheable.</p><h3>Should I worry about security if people access my site through a<br
/> cache?</h3><p>SSL pages are not cached (or decrypted) by proxy caches, so you don’t have<br
/> to worry about that. However, because caches store non-SSL requests and URLs<br
/> fetched through them, you should be conscious about unsecured sites; an<br
/> unscrupulous administrator could conceivably gather information about their<br
/> users, especially in the URL.</p><p>In fact, any administrator on the network between your server and your<br
/> clients could gather this type of information. One particular problem is when<br
/> CGI scripts put usernames and passwords in the URL itself; this makes it<br
/> trivial for others to find and user their login.</p><p>If you’re aware of the issues surrounding Web security in general, you<br
/> shouldn’t have any surprises from proxy caches.</p><h3>I’m looking for an integrated Web publishing solution. Which ones are<br
/> cache-aware?</h3><p>It varies. Generally speaking, the more complex a solution is, the more<br
/> difficult it is to cache. The worst are ones which dynamically generate all<br
/> content and don’t provide validators; they may not be cacheable at all. Speak<br
/> with your vendor’s technical staff for more information, and see the<br
/> Implementation notes below.</p><h3>My images expire a month from now, but I need to change them in the<br
/> caches now!</h3><p>The Expires header can’t be circumvented; unless the cache (either browser<br
/> or proxy) runs out of room and has to delete the representations, the cached<br
/> copy will be used until then.</p><p>The most effective solution is to change any links to them; that way,<br
/> completely new representations will be loaded fresh from the origin server.<br
/> Remember that the page that refers to an representation will be cached as<br
/> well. Because of this, it’s best to make static images and similar<br
/> representations very cacheable, while keeping the HTML pages that refer to<br
/> them on a tight leash.</p><p>If you want to reload an representation from a specific cache, you can<br
/> either force a reload (in Firefox, holding down shift while pressing ‘reload’<br
/> will do this by issuing a <code>Pragma: no-cache</code> request header) while using the<br
/> cache. Or, you can have the cache administrator delete the representation<br
/> through their interface.</p><h3>I run a Web Hosting service. How can I let my users publish<br
/> cache-friendly pages?</h3><p>If you’re using Apache, consider allowing them to use .htaccess files and<br
/> providing appropriate documentation.</p><p>Otherwise, you can establish predetermined areas for various caching<br
/> attributes in each virtual server. For instance, you could specify a<br
/> directory /cache-1m that will be cached for one month after access, and a<br
/> /no-cache area that will be served with headers instructing caches not to<br
/> store representations from it.</p><p>Whatever you are able to do, it is best to work with your largest<br
/> customers first on caching. Most of the savings (in bandwidth and in load on<br
/> your servers) will be realized from high-volume sites.</p><h3>I’ve marked my pages as cacheable, but my browser keeps requesting them<br
/> on every request. How do I force the cache to keep representations of them?</h3><p>Caches aren’t required to keep a representation and reuse it; they’re only<br
/> required to <strong>not</strong> keep or use them under some conditions. All<br
/> caches make decisions about which representations to keep based upon their<br
/> size, type (e.g., image vs. html), or by how much space they have left to keep<br
/> local copies. Yours may not be considered worth keeping around, compared to<br
/> more popular or larger representations.</p><p>Some caches do allow their administrators to prioritize what kinds of<br
/> representations are kept, and some allow representations to be “pinned” in<br
/> cache, so that they’re always available.</p><h2><a
id="IMP-SERVER">Implementation Notes — Web<br
/> Servers</a></h2><p>Generally speaking, it’s best to use the latest version of whatever Web<br
/> server you’ve chosen to deploy. Not only will they likely contain more<br
/> cache-friendly features, new versions also usually have important security<br
/> and performance improvements.</p><h3>Apache HTTP Server</h3><p><a
class="offsite" href="http://www.apache.org/">Apache</a> uses<br
/> optional modules to include headers, including both Expires and<br
/> Cache-Control. Both modules are available in the 1.2 or greater<br
/> distribution.</p><p>The modules need to be built into Apache; although they are included in<br
/> the distribution, they are not turned on by default. To find out if the<br
/> modules are enabled in your server, find the httpd binary and run <code>httpd<br
/> -l</code>; this should print a list of the available modules (note that this only<br
/> lists compiled-in modules; on later versions of Apache, use <code>httpd -M</code><br
/> to include dynamically loaded modules as well). The modules we’re<br
/> looking for are mod_expires and mod_headers.</p><ul><li>If they aren’t available, and you have administrative access, you can<br
/> recompile Apache to include them. This can be done either by uncommenting<br
/> the appropriate lines in the Configuration file, or using the<br
/> <code>-enable-module=expires</code> and <code>-enable-module=headers</code></p><p>arguments to configure (1.3 or greater). Consult the INSTALL file found<br
/> with the Apache distribution.</li></ul><p>Once you have an Apache with the appropriate modules, you can use<br
/> mod_expires to specify when representations should expire, either in .htaccess<br
/> files or in the server’s access.conf file. You can specify expiry from either<br
/> access or modification time, and apply it to a file type or as a default. See<br
/> the <a
class="offsite" href="http://www.apache.org/docs/mod/mod_expires.html">module<br
/> documentation</a> for more information, and speak with your local Apache guru<br
/> if you have trouble.</p><p>To apply <code>Cache-Control</code> headers, you’ll need to use the mod_headers module,<br
/> which allows you to specify arbitrary HTTP headers for a resource. See <a
class="offsite" href="http://www.apache.org/docs/mod/mod_headers.html">the<br
/> mod_headers documentation</a>.</p><p>Here’s an example .htaccess file that demonstrates the use of some<br
/> headers.</p><ul><li>.htaccess files allow web publishers to use commands normally only<br
/> found in configuration files. They affect the content of the directory<br
/> they’re in and their subdirectories. Talk to your server administrator to<br
/> find out if they’re enabled.</li></ul><pre class="example">### activate mod_expires
ExpiresActive On
### Expire .gif's 1 month from when they're accessed
ExpiresByType image/gif A2592000
### Expire everything else 1 day from when it's last modified
### (this uses the Alternative syntax)
ExpiresDefault "modification plus 1 day"
### Apply a Cache-Control header to index.html
&lt;Files index.html&gt;
Header append Cache-Control "public, must-revalidate"
&lt;/Files&gt;</pre><ul><li>Note that mod_expires automatically calculates and inserts a<br
/> <code>Cache-Control:max-age</code> header as appropriate.</li></ul><p>Apache 2’s configuration is very similar to that of 1.3; see the 2.2 <a
class="offsite" href="http://httpd.apache.org/docs/2.2/mod/mod_expires.html">mod_expires</a> and<br
/> <a
class="offsite" href="http://httpd.apache.org/docs/2.2/mod/mod_headers.html">mod_headers</a><br
/> documentation for more information.</p><h3>Microsoft IIS</h3><p><a
class="offsite" href="http://www.microsoft.com/">Microsoft</a>’s<br
/> Internet Information Server makes it very easy to set headers in a somewhat<br
/> flexible way. Note that this is only possible in version 4 of the server,<br
/> which will run only on NT Server.</p><p>To specify headers for an area of a site, select it in the<br
/> <code>Administration Tools</code> interface, and bring up its properties. After<br
/> selecting the <code>HTTP Headers</code> tab, you should see two interesting<br
/> areas; <code>Enable Content Expiration</code> and <code>Custom HTTP headers</code>.<br
/> The first should be self-explanatory, and the second can be used to apply<br
/> Cache-Control headers.</p><p>See the ASP section below for information about setting headers in Active<br
/> Server Pages. It is also possible to set headers from ISAPI modules; refer to<br
/> MSDN for details.</p><h3>Netscape/iPlanet Enterprise Server</h3><p>As of version 3.6, Enterprise Server does not provide any obvious way to<br
/> set Expires headers. However, it has supported HTTP 1.1 features since version<br
/> 3.0. This means that HTTP 1.1 caches (proxy and browser) will be able to take<br
/> advantage of Cache-Control settings you make.</p><p>To use Cache-Control headers, choose <code>Content Management | Cache Control<br
/> Directives</code> in the administration server. Then, using the Resource Picker,<br
/> choose the directory where you want to set the headers. After setting the<br
/> headers, click ‘OK’. For more information, see the <a
class="offsite" href="http://www.redhat.com/docs/manuals/ent-server/">NES manual</a>.</p><h2><a
id="IMP-SCRIPT">Implementation Notes — Server-Side<br
/> Scripting</a></h2><p
class="callout right">One thing to keep in mind is that it may be easier to set<br
/> HTTP headers with your Web server rather than in the scripting language. Try<br
/> both.</p><p>Because the emphasis in server-side scripting is on dynamic content, it<br
/> doesn’t make for very cacheable pages, even when the content could be cached.<br
/> If your content changes often, but not on every page hit, consider setting a<br
/> Cache-Control: max-age header; most users access pages again in a relatively<br
/> short period of time. For instance, when users hit the ‘back’ button, if there<br
/> isn’t any validator or freshness information available, they’ll have to wait<br
/> until the page is re-downloaded from the server to see it.</p><h3>CGI</h3><p>CGI scripts are one of the most popular ways to generate content. You can<br
/> easily append HTTP response headers by adding them before you send the body;<br
/> Most CGI implementations already require you to do this for the<br
/> <code>Content-Type</code> header. For instance, in Perl;</p><pre class="example">#!/usr/bin/perl
print "Content-type: text/html\n";
print "Expires: Thu, 29 Oct 1998 17:04:19 GMT\n";
print "\n";
### the content body follows...</pre><p>Since it’s all text, you can easily generate <code>Expires</code> and other<br
/> date-related headers with in-built functions. It’s even easier if you use</p><p><code>Cache-Control: max-age</code>;</p><pre><span class="example">print "Cache-Control: max-age=600\n";</span></pre><p>This will make the script cacheable for 10 minutes after the request, so<br
/> that if the user hits the ‘back’ button, they won’t be resubmitting the<br
/> request.</p><p>The CGI specification also makes request headers that the client sends<br
/> available in the environment of the script; each header has ‘HTTP_’ prepended<br
/> to its name. So, if a client makes an <code>If-Modified-Since</code> request, it will show<br
/> up as <code>HTTP_IF_MODIFIED_SINCE</code>.</p><p>See also the <a
href="http://www.mnot.net/cgi_buffer/">cgi_buffer</a><br
/> library, which automatically handles ETag generation and validation,<br
/> <code>Content-Length</code> generation and gzip content-coding for Perl and Python CGI<br
/> scripts with a one-line include. The Python version can also be used to wrap<br
/> arbitrary CGI scripts with.</p><h3>Server Side Includes</h3><p>SSI (often used with the extension .shtml) is one of the first ways that<br
/> Web publishers were able to get dynamic content into pages. By using special<br
/> tags in the pages, a limited form of in-HTML scripting was available.</p><p>Most implementations of SSI do not set validators, and as such are not<br
/> cacheable. However, Apache’s implementation does allow users to specify which<br
/> SSI files can be cached, by setting the group execute permissions on the<br
/> appropriate files, combined with the <code>XbitHack full</code> directive. For more<br
/> information, see the <a
class="offsite" href="http://www.apache.org/docs/mod/mod_include.html">mod_include<br
/> documentation</a>.</p><h3>PHP</h3><p><a
class="offsite" href="http://www.php.net/">PHP</a> is a<br
/> server-side scripting language that, when built into the server, can be used<br
/> to embed scripts inside a page’s HTML, much like SSI, but with a far larger<br
/> number of options. PHP can be used as a CGI script on any Web server (Unix or<br
/> Windows), or as an Apache module.</p><p>By default, representations processed by PHP are not assigned validators,<br
/> and are therefore uncacheable. However, developers can set HTTP headers by<br
/> using the <code>Header()</code> function.</p><p>For example, this will create a Cache-Control header, as well as an<br
/> Expires header three days in the future:</p><pre class="example">&lt;?php
 Header("Cache-Control: must-revalidate");

 $offset = 60 * 60 * 24 * 3;
 $ExpStr = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
 Header($ExpStr);
?&gt;</pre><p>Remember that the <code>Header()</code> function MUST come before any other output.</p><p>As you can see, you’ll have to create the HTTP date for an <code>Expires</code> header<br
/> by hand; PHP doesn’t provide a function to do it for you (although recent<br
/> versions have made it easier; see the <a
class="offsite" href="http://php.net/date">PHP&#8217;s date documentation</a>). Of course, it’s<br
/> easy to set a <code>Cache-Control: max-age header</code>, which is just as good for most<br
/> situations.</p><p>For more information, see the <a
class="offsite" href="http://www.php.net/manual/function.header.php3">manual entry for<br
/> header</a>.</p><p>See also the <a
class="offsite" href="http://www.mnot.net/cgi_buffer/">cgi_buffer</a> library, which<br
/> automatically handles <code>ETag</code> generation and validation, <code>Content-Length</code><br
/> generation and gzip content-coding for PHP scripts with a one-line<br
/> include.</p><h3>Cold Fusion</h3><p><a
class="offsite" href="http://www.macromedia.com/software/coldfusion/">Cold Fusion</a>, by <a
class="offsite" href="http://www.macromedia.com/">Macromedia</a> is a commercial server-side<br
/> scripting engine, with support for several Web servers on Windows, Linux and<br
/> several flavors of Unix.</p><p>Cold Fusion makes setting arbitrary HTTP headers relatively easy, with the<br
/> <code><a
class="offsite" href="http://livedocs.macromedia.com/coldfusion/7/htmldocs/00000270.htm">CFHEADER</a></code><br
/> tag. Unfortunately, their example for setting an <code>Expires</code> header, as below, is a bit misleading.</p><pre><span class="example">&lt;CFHEADER NAME="Expires" VALUE="#Now()#"&gt;</span></pre><p>It doesn’t work like you might think, because the time (in this case, when the request is made)<br
/> doesn’t get converted to a HTTP-valid date; instead, it just gets printed as<br
/> a representation of Cold Fusion’s Date/Time object. Most clients will either<br
/> ignore such a value, or convert it to a default, like January 1, 1970.</p><p>However, Cold Fusion does provide a date formatting function that will do the job;<br
/> <code><a
class="offsite" href="http://livedocs.macromedia.com/coldfusion/7/htmldocs/00000483.htm">GetHttpTimeString</a></code>. In combination with <code><br
/> <a
class="offsite" href="http://livedocs.macromedia.com/coldfusion/7/htmldocs/00000437.htm">DateAdd</a></code>, it’s easy to set Expires dates;<br
/> here, we set a header to declare that representations of the page expire in one month;</p><pre class="example">&lt;cfheader name="Expires"
  value="#GetHttpTimeString(DateAdd('m', 1, Now()))#"&gt;</pre><p>You can also use the <code>CFHEADER</code> tag to set <code>Cache-Control: max-age</code> and other headers.</p><p>Remember that Web server headers are passed through in some deployments of Cold Fusion<br
/> (such as CGI); check yours to determine whether you can use<br
/> this to your advantage, by setting headers on the server instead of in Cold<br
/> Fusion.</p><h3>ASP and ASP.NET</h3><p
class="callout right">When setting HTTP headers from ASPs, make sure you either<br
/> place the Response method calls before any HTML generation, or use<br
/> <code>Response.Buffer</code> to buffer the output. Also, note that some versions of IIS set<br
/> a <code>Cache-Control: private</code> header on ASPs by default, and must be declared public<br
/> to be cacheable by shared caches.</p><p>Active Server Pages, built into IIS and also available for other Web<br
/> servers, also allows you to set HTTP headers. For instance, to set an expiry<br
/> time, you can use the properties of the <code>Response</code> object;</p><pre><span class="example">&lt;% Response.Expires=1440 %&gt;</span></pre><p>specifying the number of minutes from the request to expire the<br
/> representation. <code>Cache-Control</code> headers can be added like this:</p><pre><span class="example">&lt;% Response.CacheControl="public" %&gt;</span></pre><p>In ASP.NET, <code>Response.Expires</code> is deprecated; the proper way to set cache-related<br
/> headers is with <code>Response.Cache</code>;</p><pre class="example">Response.Cache.SetExpires ( DateTime.Now.AddMinutes ( 60 ) ) ;
Response.Cache.SetCacheability ( HttpCacheability.Public ) ;</pre><p>See the <a
class="offsite" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspoutputcache.asp">MSDN documentation</a> for more<br
/> information.</p><h2><a
id="REF">References and Further Information</a></h2><h3><a
class="offsite" href="http://www.ietf.org/rfc/rfc2616.txt">HTTP 1.1 Specification</a></h3><p>The HTTP 1.1 spec has many extensions for making pages cacheable,<br
/> and is the authoritative guide to implementing the protocol. See sections 13,<br
/> 14.9, 14.21, and 14.25.</p><h3><a
class="offsite" href="http://www.web-caching.com/">Web-Caching.com</a></h3><p>An excellent introduction to caching concepts, with links to other online<br
/> resources.</p><h3><a
class="offsite" href="http://www.goldmark.org/netrants/webstats/">On Interpreting<br
/> Access Statistics</a></h3><p>Jeff Goldberg’s informative rant on why you shouldn’t rely on access<br
/> statistics and hit counters.</p><h3><a
href="http://redbot.org/">REDbot</a></h3><p>Examines HTTP resources to determine how they will interact with Web caches, and generally how well they use the protocol.</p><h3><a
href="http://www.mnot.net/cgi_buffer/">cgi_buffer Library</a></h3><p>One-line include in Perl CGI, Python CGI and PHP scripts automatically<br
/> handles ETag generation and validation, Content-Length generation and gzip<br
/> Content-Encoding — correctly. The Python version can also be used as a<br
/> wrapper around arbitrary CGI scripts.</p><h2><a
id="ABOUT">About This Document</a></h2><p>This document is Copyright © 1998-2010 Mark Nottingham &lt;<a
href="mailto:mnot@pobox.com">mnot@pobox.com</a>&gt;.</p><p></p><p>This <span>work</span> is licensed under a <a
rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License</a>.</p><p>All trademarks within are property of their respective holders.</p><p>Although the author believes the contents to be accurate at the time of<br
/> publication, no liability is assumed for them, their application or any<br
/> consequences thereof. If any misrepresentations, errors or other need for<br
/> clarification is found, please contact the author immediately.</p><p>The latest revision of this document can always be obtained from <a
href="http://www.mnot.net/cache_docs/">http://www.mnot.net/cache_docs/</a></p><p>Translations are available in:<br
/> <a
title="面向站长和网站管理员的Web缓存加速指南" hreflang="zh" href="http://www.chedong.com/tech/cache_docs.html">Chinese</a>,<br
/> <a
title="Kešovací návod pro autory webu a webmastery" hreflang="cs" href="http://www.jakpsatweb.cz/clanky/caching-tutorial-czech-translation.html">Czech</a>,<br
/> <a
title="Caching-Tutorial für Webautoren und Webmaster" hreflang="de" href="http://thomas-huehn.de/web/caching-tutorial">German</a>, and<br
/> <a
title="Un tutoriel de la mise en cache" hreflang="fr" href="index.fr.html">French</a>.</p><p>April 9, 2010</p><p><a
href="http://creativecommons.org/licenses/by-nc-nd/3.0/"><img
class="alignright size-full wp-image-211" title="Creative Commons Licence" src="http://www.seoexploration.com/wp-content/uploads/2010/05/Licence.jpg" alt="Creative Commons Licence" width="93" height="39" /></a></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2010/05/caching-tutorial/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Social Bookmarking Strategies</title><link>http://www.seoexploration.com/2009/12/social-bookmarking/</link> <comments>http://www.seoexploration.com/2009/12/social-bookmarking/#comments</comments> <pubDate>Fri, 11 Dec 2009 09:32:34 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Social SEO]]></category> <category><![CDATA[gaining traffic]]></category> <category><![CDATA[SEO]]></category> <category><![CDATA[seo benefits]]></category> <category><![CDATA[social bookmark]]></category> <category><![CDATA[social bookmarking]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=163</guid> <description><![CDATA[This is a good video about the SEO benefits of Social Bookmarking &#8211; a great way of gaining traffic. Thanks to http://videos.sitepronews.com/]]></description> <content:encoded><![CDATA[<p>This is a good video about the SEO benefits of Social Bookmarking &#8211; a great way of gaining traffic.<object
id="main" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="452" height="361" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param
name="name" value="main" /><param
name="bgcolor" value="#000000" /><param
name="src" value="http://videos.sitepronews.com/player/vPlayer.swf?f=http://videos.sitepronews.com/player/vConfig_embed.php?vkey=95eeef66c225f7883bdc" /><param
name="allowfullscreen" value="true" /><param
name="quality" value="high" /><embed
id="main" type="application/x-shockwave-flash" width="452" height="361" src="http://videos.sitepronews.com/player/vPlayer.swf?f=http://videos.sitepronews.com/player/vConfig_embed.php?vkey=95eeef66c225f7883bdc" quality="high" allowfullscreen="true" bgcolor="#000000" name="main"></embed></object></p><p>Thanks to <a
title="site pro news" href="http://videos.sitepronews.com/" target="_blank">http://videos.sitepronews.com/</a></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/12/social-bookmarking/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Google Page Speed and Yslow 2.0</title><link>http://www.seoexploration.com/2009/12/google-page-speed-and-yslow-2-0/</link> <comments>http://www.seoexploration.com/2009/12/google-page-speed-and-yslow-2-0/#comments</comments> <pubDate>Wed, 09 Dec 2009 12:53:06 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Website Optimization]]></category> <category><![CDATA[activity monitor]]></category> <category><![CDATA[analytics]]></category> <category><![CDATA[archive]]></category> <category><![CDATA[archived]]></category> <category><![CDATA[archives]]></category> <category><![CDATA[external css]]></category> <category><![CDATA[firebug]]></category> <category><![CDATA[google]]></category> <category><![CDATA[performance rules]]></category> <category><![CDATA[web pages]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=153</guid> <description><![CDATA[Posted By Mike Hopley On June 15, 2009 @ 12:52 pm Hot on the heels of Yahoo’s Yslow [1], Google have published Page Speed [2], a tool they have been using to optimize their own web pages. Now you can use it too. Page Speed is similar to Yslow in several respects: it’s an add-on [...]]]></description> <content:encoded><![CDATA[<p
id="BlogDate">Posted By <a
href="http://www.badmintonbible.com/" target="_blank"><span
style="text-decoration: underline;">Mike Hopley</span></a> On June 15, 2009 @ 12:52 pm</p><div
id="BlogContent"><p>Hot on the heels of Yahoo’s <a
rel="external" href="http://developer.yahoo.com/yslow/">Yslow</a> <sup>[1]</sup>, Google have published <a
rel="external" href="http://code.google.com/speed/page-speed/">Page Speed</a> <sup>[2]</sup>, a tool they have been using to optimize their own web pages. Now you can use it too.</p><p>Page Speed is similar to Yslow in several respects: it’s an add-on to Firebug; it analyses your pages according to a set of performance rules; it draws attention to rules that you score badly on; and it also provides a page activity monitor.<br
/> <img
title="Google Page Speed and Yslow 2.0" src="http://www.thewebsqueeze.com/wp-content/uploads/2009/06/page-speed.jpg" alt="Google Page Speed" width="468" height="246" /><br
/> For each rule, Page Speed gives you a general indication of how well you’re doing, in the form of a green tick (good), red circle (bad), or amber triangle (indifferent). You can also hover over a rule to see your percentage score. Page Speed does not provide an overall percentage score, but it does arrange the results in order of importance.</p><p>Since my previous <a
rel="external" href="http://www.thewebsqueeze.com/web-design-articles/yslow-going-from-f-to-a.html">article about Yslow 1.0</a> <sup>[3]</sup>, Yslow 2.0 has been released; this includes a further 9 rules. Let’s now take a look at all these rules—both Page Speed and Yslow.</p><h3>Page Speed rules shared with Yslow 1.0</h3><p>These rules are the same as those I previously discussed, although their organisation is different. I’m not going to cover these rules again, but you may still find some of <a
rel="external" href="http://code.google.com/speed/page-speed/docs/using.html">Page Speed’s documentation</a> <sup>[4]</sup> details interesting.</p><ul><li> Avoid CSS expressions</li><li>Combine external CSS</li><li>Combine external javascript</li><li>Enable gzip compression</li><li>Leverage browser caching</li><li>Minify javascript</li><li>Minimize DNS lookups</li><li>Minimize redirects</li><li>Parallelize downloads across multiple hostnames</li><li>Put CSS in the document head</li></ul><p>Page Speed may sometimes advise you to do stupid things. For example, under the “Leverage browser caching” rule, Page Speed suggested that I make <code>__utm.gif</code> cacheable. This tiny gif is used by Google Analytics to help compile your statistics; if you make it cacheable, Analytics will fail to track visitors who retrieved it from a cache. Leave it alone!</p><h3>Page Speed rules shared with Yslow 2.0</h3><p>I haven’t yet discussed these rules, so let’s look at them now:</p><ul><li>Minimize cookie size</li><li>Serve static content from a cookie-less domain</li><li>Specify image dimensions</li></ul><h4>Minimize cookie size</h4><p>Google’s advice here is more specific than Yslow’s: keep the average cookie size below 400 bytes. I get perfect marks on this from both tools, so I haven’t investigated further.</p><h4>Serve static content from a cookie-less domain</h4><p>I score badly on this one, and I expect many other sites will too. Surprisingly, requests for components such as images also include cookies, and these are generally just useless network traffic. The best way to fix this is to use a CDN; obviously, this will also cause you to score well on Yslow’s “Use a CDN” rule.</p><p>And yes, this means I’ve changed my mind about CDN’s. Some good, cheap CDN’s are now available, such as SimpleCDN or Amazon Cloudfront. I use SimpleCDN, and have found them to be okay; but I’m not happy with their changing their service offering at short notice, and their Lightning service is currently not working for me—hence my poor score on this rule!</p><h4>Specify image dimensions</h4><p>Lazy designers often take a large image and use HTML to squash it down; consequently, the file size can be much larger than is necessary.</p><p>Don’t use HTML to resize images; use a graphics program. The width and height attributes in your HTML &lt;img&gt; tag should exactly match the size of the image. Doing so will also give the best appearance, as the browser does not need to scale the image.</p><p>I get a perfect score on this, and there’s no excuse for anything less.</p><h3>Rules unique to Page Speed</h3><p>In some cases, Yslow’s guidelines may include these topics, but not in the form of an automated check on your web page.</p><ul><li>Defer loading of javascript</li><li>Optimize images</li><li>Optimize the order of styles and scripts</li><li>Remove unused CSS</li><li>Serve resources from a consistent URL</li><li>Leverage proxy caching</li><li>Use efficient CSS selectors</li></ul><h4>Defer loading of javascript</h4><p>Before you can test your website against this rule, you must enable “Profile Deferrable Javascript” in the options. You may want to disable it again when you’re done, as it can slow down Firefox. Moreover, this profiling is only accurate on your first visit: to get an accurate result, you must start a new browser session and run Page Speed directly you load your website (before loading a second page).</p><p>The idea behind this rule is that javascript slows down your pages even when it’s not actually being used. Even if the script is cached, the browser must load it from disk and execute it. Some javascript functions need to be available before the onLoad event; others don’t. This rule proposes that you split off these latter functions into a separate file. You can then use some trickery to “lazy-load” this javascript after the document has finished loading.</p><p>It’s unclear to me whether this lazy-loading is better than simply putting your script at the bottom of the page. If your script is at the bottom, then it will still need to be downloaded and evaluated before the onLoad event is fired (I think), and lazy-loading will bypass this limitation; but what if you’re using a framework such as jQuery, which has the more sophisticated onDomReady event? To be honest, I don’t yet know enough about this issue to make simple recommendations. I suspect, however, that lazy-loading is even faster than simply putting javascript at the bottom of the page.</p><p>The good news is that Google Page Speed will identify these uncalled functions for you. Ironically, although I had plenty of uncalled functions, they all came from Google’s own ga.js; I’m not sure I want to mess with that, as it may screw up my Google Analytics stats.</p><h4>Optimise images</h4><p>Page Speed automatically creates optimised versions of your images, and offers a link to them. This is similar to running your images through Smush.it.</p><h4>Optimise the order of styles and scripts</h4><p>Ideally, you wouldn’t include any javascript in the &lt;head&gt;, as this violates Yslow’s rule, “Put javascript at the bottom.” If you need to include scripts in the &lt;head&gt;, however, try to get the order right. External scripts should come after all the external stylesheets, and inline scripts should come last of all.</p><p>Why does the order matter? Because javascript blocks subsequent downloads. While your javascript is downloading and being evaluated, the stylesheet that comes after it can’t be downloaded. Check out the documentation for more details.</p><h4>Remove unused CSS</h4><p>I score 100% on this one, which is surprising given that my CSS is an overgrown, tangled thicket of complexity that desperately needs pruning.</p><p>Every CSS rule adds bytes to be downloaded, and also requires parsing by the browser. Obviously it’s good to remove dusty old rules that you never use, but even after doing so you may still have a single monolithic CSS file that styles a diverse range of pages. As a result, every page gets a large amount of CSS that’s not needed; if your site is like this, it may be more efficient to split your CSS across multiple modules (although this increases HTTP requests).</p><p>Clearly a trade-off is necessary here. I recommend keeping a consistent style as much as possible; apart from the speed benefits, consistency helps visitors and generally looks more professional than constantly changing styles. For large sites with many different types of pages (such as Yahoo), however, it’s often better to split CSS into modules.</p><p>Even if your site only needs one stylesheet, it’s a good idea to start thinking in terms of object-oriented CSS, because this makes your CSS simpler, shorter, and more flexible; for an expert explanation of the topic, <a
rel="external" href="http://developer.yahoo.net/blogs/theater/archives/2009/03/website_and_webapp_performance.html">see Nicole Sullivan’s presentation</a> <sup>[5]</sup>.</p><h4>Serve resources from a consistent URL</h4><p>This one is fairly obvious. To benefit from caching, we need to keep the URL consistent. For example, if on different pages you serve the same image, but from two different domains, then it will get downloaded twice instead of being read from cache.</p><p>For most people this shouldn’t be issue; it’s most likely to apply if you’re doing something fancy and automated to split your content across multiple hostnames.</p><h4>Leverage proxy caching</h4><p>Now this one is clever. When people visit your website, its resources can be cached not only by them but also by their ISP. Then when another visitor comes via the same ISP, he can download a copy from the ISP’s cache—which will be faster, because it’s closer to him than your server. Page Speed’s documentation recommends that, with a few exceptions, you set a Cache-control: public header for static resources (such as images).</p><p>Be careful not to do this for resources that have cookies attached, as you may end up allowing proxies to cache information that should be kept private to a visitor; the best solution is to serve these resources from a cookie-less domain. Also be careful with gzipping: some proxies will send gzipped content to browsers that can’t read it.</p><p>I’m not sure how this rule interacts with the use of CDN. Again, this is one I don’t understand well, and I’d welcome discussion on it.</p><h4>Use efficient CSS selectors</h4><p>This rule is controversial. The idea is that some CSS selectors are much harder for the browser to parse than others; the most efficient are ID and Class selectors, because these do not require the browser to look higher up the document tree to determine a match.</p><p>With this rule, Google is recommending a radical change in the way we write CSS. Specifically, they are suggesting that we add otherwise unnecessary ID’s and classes to the markup, in return for a speed advantage. As an example, they consider the situation where you want different colours on ordered and unordered list items:</p><pre>ul li {color: blue;}
ol li {color: red;}</pre><p>That would be the usual way to do it; instead, Google recommends adding a class to each &lt;li&gt;, so that you can use class selectors:</p><pre>.unordered-list-item {color: blue;}
.ordered-list-item {color: red;}</pre><p>No doubt this is faster, but it also takes longer to write and imposes a maintainance burden in your markup. If there were tools that would automatically generate such optimised CSS and the accompanying markup, then it might be worth doing. I suppose you could use server-side coding to generate the markup—for example, using the HTML helper from CakePHP—but this seems a heavy-handed approach.</p><p>My scepticism over this rule was initially quashed by the towering authority of Google, but then I looked around to see whether there was any research on the subject. The most respectable tests I could find came from Steve Souders himself, in his post about the <a
rel="external" href="http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/">performance impact of CSS selectors</a> <sup>[6]</sup>. Steve found that, in real-world conditions, the maximum possible benefit of optimising CSS is 50 ms; and for 70% of users (i.e. those running IE7 or FF3), it’s only 20 ms. These numbers were obtained with 6000 DOM elements and 2000 extremely inefficient CSS rules. This is pretty much a worst-case scenario; most sites, even complex ones, will have far fewer DOM elements and CSS rules, and their CSS will also be much simpler.</p><p>Steve concludes that the potential performance benefits are small, and not worth the cost. I’m inclined to agree, but I’d welcome more information.</p><p>Nevertheless, there’s no harm in getting into good habits: some of Google’s recommendations for CSS selectors are quite reasonable, such as not over-qualifying ID and class selectors with an antecedent tag selector (so .errorMessage is better than p.errorMessage). Such coding habits also sit harmoniously with object-oriented CSS.</p><p>If you read Steve’s post, be sure to check out Nicole Sullivan’s comment: “Micro-optimization of selectors is going a bit off track in a performance analysis of CSS. The focus should be on scalable CSS.” To me, this seems a much more sensible and maintainable approach than the monomaniacal one recommended by Google.</p><p>I do extremely badly on this rule (0%). Although I consider the recommendations to be unrealistic, my terrible score does reflect the excessive complexity and lack of modularity within my CSS.</p><h3>Rules unique to Yslow 2.0</h3><p>In some cases, Page Speed’s guidelines may include these topics, but not in the form of an automated check on your web page.</p><p>Note that Yahoo’s documentation includes other recommendations that are not checked by Yslow (because they haven’t discovered a sensible way to automate the test). Yslow has 22 rules, but Yahoo lists <a
rel="external" href="http://developer.yahoo.com/performance/rules.html">34 best practices</a> <sup>[7]</sup> in total.</p><ul><li>Reduce the number of DOM elements</li><li>Make favicon small and cacheable</li><li>Avoid HTTP 404 (Not Found) errors</li><li>Avoid AlphaImageLoader filter</li><li>Make AJAX cacheable</li><li>Use GET for AJAX requests</li></ul><h4>Reduce the number of DOM elements</h4><p>The more DOM elements you have, the longer it takes to download your page, to render it, and to play with the DOM via javascript.</p><p>Essentially, this rule asks you to avoid large amounts of unnecessary markup, including markup added by javascript. As an example, yahoo.com has about 700 DOM nodes, despite being a busy page. My home page has 267 DOM nodes, and that could be reduced a lot. You can check how many nodes your page has, by entering the following into Firebug’s console:</p><pre>document.getElementsByTagName('*').length</pre><p>Blindly applying this rule can be dangerous (and that’s true of many performance rules). Don’t cut off your nose to spite your face! Markup purists will take this rule as a vindication for using the absolute minimum of markup, and in particular for avoiding the use of container &lt;div&gt;s whenever possible. This will leave them with hideously convoluted CSS and problems maintaining their code.</p><p>By all means remove extraneous markup, and also try to limit the complexity of DOM access in your javascript (for example, <a
rel="external" href="http://developer.yahoo.com/performance/rules.html#dom_access">avoid using javascript to fix layout issues</a> <sup>[8]</sup>—here I have sinned). But never be afraid to throw in an extra container &lt;div&gt; when you can see it will make life easier.</p><h4>Make favicon.ico small and cacheable</h4><p>You might think that a favicon is not even worth the HTTP request, but you don’t get a say in the matter: the browser is going to request it anyway. Make one, make it small, and put it in the root directory of your website (where the browser will look for it).</p><p>Because you can’t change the name of this file—it must be called favicon.ico, or it won’t work—you should be moderate in setting its expiry date. It’s hardly essential that your visitors immediately get your latest favicon, but equally you wouldn’t want it to be cached for 10 years! I give mine a two-month shelf-life.</p><h4>Avoid HTTP 404 (Not Found) errors</h4><p>This one is obvious. If your document has broken links, fix them.</p><h4>Avoid AlphaImageLoader filter</h4><p>Ah, good old alpha-transparent PNG’s; how we love them! What web designer hasn’t flirted with multi-layer scrolling transparencies at some point? And who has not felt a sense of satisfied mastery, upon forcing IE6 to eat them via a clever hack?</p><p>The sobering reality is that, although you can make alpha-transparency work in IE6, you pay a heavy price for doing so. All the hacks rely on Microsoft’s AlphaImageLoader filter. Not only does this filter block rendering and freeze the browser while it’s being calculated, but it also increases memory consumption. To make matters worse, the performance penalty is incurred for each element, not for each image. For example, let’s say you have a fancy alpha-transparent bullet point image for your unordered list items; on a page with 20 bullets, you get the penalty 20 times over.</p><p>Use PNG-8 transparency instead, if you can. Incidentally, creating a web page from multiple layers of transparency is probably a bad idea anyway: even in good browsers, these kinds of pages are sluggish to scroll; find a better medium for expressing latent op art.</p><h4>Make AJAX cacheable, and use GET for AJAX requests</h4><p>I can’t pretend to understand these rules properly, having never used AJAX. Nevertheless, the ideas are straightforward.</p><p>If a resource has not changed since it was fetched, we want to read it from cache rather than getting a new copy; this applies just as much to something requested via AJAX. Steve summarises it thus:</p><blockquote><p>Even though your Ajax responses are created dynamically, and might only be applicable to a single user, they can still be cached. Doing so will make your Web 2.0 apps faster.</p></blockquote><p>Apparently, GET is more efficient than POST, because it can send data in a single packet, whereas POST takes two steps: first send the headers, then send the data. Providing your data is less than 2 kB (a limit on the URL length in IE), you should be able to use GET for AJAX requests.</p><h3>Conclusions</h3><p>Google Page Speed is a useful new tool for optimising your websites’ performance. However, some of its advice can be misleading—in particular, CSS selector efficiency is a red herring that distracts you from the more useful goal of building object-oriented CSS.</p><p>Yslow is the more mature tool, and I recommend you give it priority. After you’ve finished with Yslow, you may be interested in what Page Speed has to say.</p></div><hr
style="text-align: center;" />Article printed from The Web Squeeze: <strong
dir="ltr">http://www.thewebsqueeze.com</strong></p><p>URL to article: <strong
dir="ltr">http://www.thewebsqueeze.com/web-design-articles/google-page-speed-and-yslow-2-0.html</strong></p><p>URLs in this post:</p><p
style="margin: 2px 0pt;">[1] Yslow: <strong><span
dir="ltr">http://developer.yahoo.com/yslow/</span></strong></p><p
style="margin: 2px 0pt;">[2] Page Speed: <strong><span
dir="ltr">http://code.google.com/speed/page-speed/</span></strong></p><p
style="margin: 2px 0pt;">[3] article about Yslow 1.0: <strong><span
dir="ltr">http://www.thewebsqueeze.com/web-design-articles/yslow-going-from-f-to-a.html</span></strong></p><p
style="margin: 2px 0pt;">[4] Page Speed’s documentation: <strong><span
dir="ltr">http://code.google.com/speed/page-speed/docs/using.html</span></strong></p><p
style="margin: 2px 0pt;">[5] see Nicole Sullivan’s presentation: <strong><span
dir="ltr">http://developer.yahoo.net/blogs/theater/archives/2009/03/website_and_webapp_performance.html</span></strong></p><p
style="margin: 2px 0pt;">[6] performance impact of CSS selectors: <strong><span
dir="ltr">http://www.stevesouders.com/blog/2009/03/10/performance-impact-of-css-selectors/</span></strong></p><p
style="margin: 2px 0pt;">[7] 34 best practices: <strong><span
dir="ltr">http://developer.yahoo.com/performance/rules.html</span></strong></p><p
style="margin: 2px 0pt;">[8] avoid using javascript to fix layout issues: <strong><span
dir="ltr">http://developer.yahoo.com/performance/rules.html#dom_access</span></strong></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/12/google-page-speed-and-yslow-2-0/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>301 redirect to the &#8220;www&#8221; site</title><link>http://www.seoexploration.com/2009/09/301-redirect/</link> <comments>http://www.seoexploration.com/2009/09/301-redirect/#comments</comments> <pubDate>Sun, 06 Sep 2009 11:24:23 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[HTML]]></category> <category><![CDATA[301 redirect]]></category> <category><![CDATA[browser shortcuts]]></category> <category><![CDATA[cache problems]]></category> <category><![CDATA[fred morgan]]></category> <category><![CDATA[htaccess file]]></category> <category><![CDATA[public html directory]]></category> <category><![CDATA[redirect url]]></category> <category><![CDATA[url redirect]]></category> <category><![CDATA[url www]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=125</guid> <description><![CDATA[Fred Morgan &#8211; seoexploration.com With the modern style of losing the &#8220;www&#8221; at the beginning of the website URL you may encounter problems &#8211; especially with statistical analysis programs. I&#8217;m not really concerned with the semantics of whether one should or should not use the starting &#8220;www&#8221; but being of the old school I still [...]]]></description> <content:encoded><![CDATA[<p>Fred Morgan &#8211; <a
title="SeoExploration" href="http://www.seoexploration.com" target="_blank">seoexploration.com</a></p><p>With the modern style of losing the &#8220;www&#8221; at the beginning of the website URL you may encounter problems &#8211; especially with statistical analysis programs.</p><p>I&#8217;m not really concerned with the semantics of whether one should or should not use the starting &#8220;www&#8221; but being of the old school I still tend towards using it.  These days most hosting facilities utilise the dual base directories of &#8220;public_html&#8221; and &#8220;www&#8221; where &#8220;www&#8221;  is the automatic clone of the &#8220;public_html&#8221; directory so, under normal circumstances, either URL will work fine.<br
/> However, I have seen browser cache problems give display problems identifying a difference between them  &#8211; i.e. missing favicon images and intermittent flash errors etc.  It took me a long time before I identified where the problem actually lay. Everyone always identifies the<strong> standard cache reload fix</strong> but not that you may be varying the actual URL (www) search which can happen when using previous saved browser shortcuts or bookmarks.</p><h3>.htaccess</h3><p>I always now use a <a
title="301 redirect" href="http://www.seoexploration.com/2009/09/301-redirect/" target="_blank">301 redirect</a> with the following script in my .htaccess file which redirects my incoming URLs to www however this step should only be taken by those who understand that problems could follow if incorrect editing is done. Firstly<span
style="text-decoration: underline;"><strong> create a backup copy of your original .htaccess file</strong></span> just in case things get messed up. Now add the following  3 lines of 301 redirection code<span
style="color: #ff0000;"><em><span
style="color: #3366ff;"><br
/> (<span
style="color: #000000;">note :</span> </span><strong>aaaaaaaa.bbb</strong><span
style="color: #3366ff;"> <span
style="color: #000000;">is tobe replaced by your website URL i.e.  <strong> <span
style="color: #ff0000;">okikoki.com</span></strong>)</span></span></em></span></p><p><span
style="color: #ff0000;"><em><span
style="color: #3366ff;"> </span><span
style="color: #3366ff;"><br
/> </span></em></span></p><p><strong>RewriteEngine On </strong><span
style="color: #3366ff;"><em><br
/> </em></span></p><p><strong>RewriteCond %{HTTP_HOST} ^<span
style="color: #ff0000;">aaaaaaaa.bbb</span><br
/> RewriteRule (.*) http://www.</strong><span
style="color: #ff0000;"><strong>aaaaaaaa.bbb</strong></span><strong>/$1 [R=301,L]</strong></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/09/301-redirect/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Track SEO rankings and Sitelinks with Google Analytics II</title><link>http://www.seoexploration.com/2009/09/track-seo-rankings-and-sitelinks-with-google-analytics-ii/</link> <comments>http://www.seoexploration.com/2009/09/track-seo-rankings-and-sitelinks-with-google-analytics-ii/#comments</comments> <pubDate>Sat, 05 Sep 2009 16:31:50 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Google-Analytics]]></category> <category><![CDATA[analytics]]></category> <category><![CDATA[google]]></category><guid
isPermaLink="false">http://www.seoexploration.com/?p=116</guid> <description><![CDATA[2 September, 2009 André Scholten Earlier this year I did a guest post on this site to show you how to track your SEO rankings with Google Analytics. It was quite some news for a lot of people, just take a look at the 300+ comments. And now it&#8217;s time for the follow-up. Google&#8217;s new [...]]]></description> <content:encoded><![CDATA[<h2><span>2 September, 2009</span> <span><a
href="http://yoast.com/track-seo-rankings-and-sitelinks-with-google-analytics-ii/#author">André Scholten</a></span> <span> </span></h2><div><p>Earlier this year I did a guest post on this site to show you how to track your <a
href="http://yoast.com/track-seo-rankings-google-analytics/">SEO rankings with Google Analytics</a>. It was quite some news for a lot of people, just take a look at the 300+ comments. And now it&#8217;s time for the follow-up.</p><h2>Google&#8217;s new technology</h2><p>Since a while Google is testing a new <a
onclick="javascript:pageTracker._trackPageview('/outbound/article/smackdown.blogsblogsblogs.com');" href="http://smackdown.blogsblogsblogs.com/2009/01/30/google-web-search-goes-completely-ajax/">AJAX version</a> of their search engine. I&#8217;m not sure who&#8217;s seeing the AJAX version and who isn&#8217;t, but in Holland most of the Firefox users do see it. You can see if you&#8217;re one the new one by looking at the url of a result page:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/examplefirefox.gif" alt="examplefirefox" width="533" height="35" /></p><p><span
id="more-1582"> </span></p><p>The great thing about this new version is that it makes Google Analytics capable of tracking the clicked <strong>position</strong>. Yes you heard what I say: the position. Where the &#8216;old&#8217; Google only allowed us to track the page a keyword was on, the new Google allows us to track the exact position.</p><h2>The new filters</h2><p>You can use the first 2 filters mentioned in the old article, be before you do that: create a new profile where you can apply these filters to (tip: watch <a
href="http://yoast.com/rankings-filter-analytics-video/">the video</a> where Joost explains this all):</p><pre>Filter name: "Ranking 1"
Filter type: "Custom filter - Include"
Filter field: "Campaign Medium"
Filter pattern: "organic"</pre><pre>Filter name: "Ranking 2"
Filter type: "Custom filter - Include"
Filter field: "Campaign Source"
Filter pattern: "google"</pre><p>And this is the new filter that is capable of tracking positions:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/ranking3.gif" alt="ranking3" width="411" height="439" /></p><p>And the copy/paste version:</p><pre>Filter name: "Ranking 3"
Filter type: "Custom filter - Advanced"
Field A -&gt; Extract A: "Campaign term", "(.*)"
Field B -&gt; Extract B: "Referral", "(\?|&amp;)cd=([^&amp;]*)"
Output To -&gt; User Defined: "$A2 (position: $B2)"</pre><p>And a bonus filter to add an &#8220;unknown position&#8221; message when the position of the searched keyword is not passed through:</p><pre>Filter name: "Ranking 4"
Filter type: "Custom filter - Search and Replace"
Filter field: "User Defined"
Search String: "\(position: \)"
Replace String: "(position unknown)"</pre><h2>The new reports</h2><p>If you have implemented everything correct you should see this in the &#8220;Visitors -&gt; User Defined&#8221; report:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/userdefinedkeywords.gif" alt="userdefinedkeywords" width="240" height="177" /></p><p>A list of keywords with the position the keyword was on when a visitor clicked it. Now you&#8217;re able to see the exact positions, more precise than any ranking tool that is out there. There&#8217;s 1 minor drawback: business listings next to the little maps are counted as a position also:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/mapsresult.gif" alt="mapsresult" width="450" height="285" /></p><p>The blue result is counted as the 11th result, and not as the first organic result. But when you&#8217;re analyzing your positions you can easily separate the geo-related keywords from the rest.</p><h2>Sitelinks</h2><p>Very interesting: the sitelinks positions are also tracked, and in a more intelligent way than the maps results. If you click on a sitelink, the actual position of that sitelink is passed on. For example, this sitelink has position 4:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/sitelinksranking.gif" alt="sitelinksranking" width="400" height="125" /></p><p>If you want to get better insights about your sitelinks you should create an extra profile with the first 3 filters mentioned above. Then add this extra filter to only track those keywords where people clicked on the (full or oneline) sitelinks:</p><pre>Filter name: "Ranking 5"
Filter type: "Custom filter - Include"
Filter field: "Referral"
Filter pattern: "oi=(oneline_sitelinks|smap)"</pre><p>The positions you will see are pure sitelinks positions, and you will get an idea about which sitelink is popular and which isn&#8217;t.</p><h2>Extra tip</h2><p>While we are dissecting the referring url from the Google Search engine we could take a look at the &#8220;meta&#8221; parameter (<a
onclick="javascript:pageTracker._trackPageview('/outbound/article/andrescholten.nl');" href="http://andrescholten.nl/zoekt-men-in-google-op-het-internet-of-in-het-nederland/">my dutch blogpost about this</a>). It&#8217;s used when people use one of these options:</p><p><img
src="http://netdna.yoast.com/uploads/2009/09/googleopties.gif" alt="googleopties" width="485" height="102" /></p><p>The selected country or language is in the &#8220;meta&#8221; parameter (not applicable for Google.com) and can be made visible with the following filter:</p><pre>Filter name: "Language / Country"
Filter type: "Custom filter - Advanced"
Field A -&gt; Extract A: "Referral", "(\?|&amp;)meta=([^&amp;]*)"
Output To -&gt; User Defined: "$A2"</pre><p>And remember: do this on a new profile so you don&#8217;t mess up existing profiles. The selected language(s) or country is visible in the &#8220;Visitors -&gt; User Defined&#8221; report.</p><p>I had this filter for quite a while on a lot of Dutch sites and saw that the three options where used like this:</p><ol><li>The internet: 96,69%</li><li>Pages in Dutch: 3,28%</li><li>Pages from Holland: 0,03%</li></ol><p>Well, that was the update, hope you liked it.</p></div><div
id="author"><img
src="http://www.gravatar.com/avatar/91df1020caec70125240f061d5f80c19?s=60&amp;d=http%3A%2F%2Fwww.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D60&amp;r=G" alt="" width="60" height="60" /></p><h3>This post was written by: André Scholten</h3><p><a
href="http://en.traffic4u.nl/web-analytics-consultancy#utm_campaign=yoast&amp;utm_medium=referral&amp;utm_source=andre">Web Analytics Consultant</a> and <a
href="http://en.traffic4u.nl/seo#utm_campaign=yoast&amp;utm_medium=referral&amp;utm_source=andre">SEO specialist</a> at Traffic4u. For more info check my <a
href="http://andrescholten.nl/">Web Analytics and SEO blog</a>.</p><p>See all posts by: <a
title="Posts by André Scholten" href="http://yoast.com/author/andre/">André Scholten</a>.</div> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/09/track-seo-rankings-and-sitelinks-with-google-analytics-ii/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>How to Position Text and Images Exactly within a Web Page</title><link>http://www.seoexploration.com/2009/08/how-to-position-text-and-images-exactly-within-a-web-page/</link> <comments>http://www.seoexploration.com/2009/08/how-to-position-text-and-images-exactly-within-a-web-page/#comments</comments> <pubDate>Wed, 19 Aug 2009 16:36:42 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[HTML]]></category> <category><![CDATA[div style]]></category> <category><![CDATA[div tag]]></category> <category><![CDATA[exact position]]></category><guid
isPermaLink="false">http://www.seoexploration.com/2009/08/how-to-position-text-and-images-exactly-within-a-web-page/</guid> <description><![CDATA[By William Bontrager Although I&#8217;ve written several articles that included examples of positioning, such as &#8220;Instant Info&#8221; and the &#8220;No-Kill Pop Box&#8221; series, it occurred to me that I&#8217;ve never written an article about how to do the positioning itself. This is it. Basically, it&#8217;s three steps: 1. Create a DIV tag. 2. Put content [...]]]></description> <content:encoded><![CDATA[<h3><span
style="font-family: verdana,helvetica,arial; font-size: x-small;">By<span
style="color: #0000ff;"> <a
href="http://www.web-source.net/cgi-bin/web/jump.cgi?ID=762" target="blank">William Bontrager</a></span></span></h3><p>Although I&#8217;ve written several articles that included examples of positioning, such as &#8220;<a
href="http://willmaster.com/possibilities/archives/wmp20021224001.shtml" target="blank">Instant Info</a>&#8221; and the  &#8220;<a
href="http://willmaster.com/possibilities/archives/wmp20030617001.shtml" target="blank">No-Kill Pop Box</a>&#8221; series, it occurred to me that I&#8217;ve never written an article about how to do the positioning itself.</p><p>This is it.</p><p>Basically, it&#8217;s three steps:</p><p>1. Create a DIV tag.</p><p>2. Put content within the DIV.</p><p>3. Tell the browser where to put the DIV.</p><p>What you&#8217;re doing is making a layer. I&#8217;ll explain those three steps in a 		      moment.</p><p>Without the above, text and images can move, and probably will, depending 		      on which browser is displaying your page and the size preferences the user 		      has specified.</p><p>That&#8217;s not necessarily bad. But if you must have something in an exact position, 		      making a layer and positioning it is a way to do it.</p><p>You might want a photograph overlapping another. Or, you might want to place 		      some text so it overlaps an image. Or, perhaps, your logo must be in the 		      exact same place on every web page.</p><p>A demonstration page has been prepared consisting of four layers.</p><p>The first layer is a photograph of the Old Faithful geyser at Yellowstone 		      National Park. The other layers are layered over the first and are composed 		      of text, the word &#8220;Old,&#8221; the word &#8220;Faithful,&#8221; and a copyright line (this 		      latter being bordered).</p><p>The demonstration page is at<br
/> <a
href="http://willmaster.com/a/21t/pl.pl?art215" target="blank">http://willmaster.com/a/21t/pl.pl?art215</a></p><p>Here&#8217;s how to do it.</p><p>1. Create a DIV tag</p><p>Creating a DIV tag creates a layer.</p><p>The DIV tag contains a style attribute with positioning information. It might 		      also have border and size information, if appropriate.</p><p>Here is the basic DIV tag required for exact positioning:</p><pre>&lt;div
   style="
      top: 99;
      left: 99;
      position: absolute;
      z-index: 1;
      visibility: show;"&gt;
&lt;!-- content will go here --&gt;
&lt;/div&gt;</pre><p><span
style="font-family: Verdana,Helvetica; font-size: x-small;"> The above creates a layer.</span></p><p>You&#8217;ll notice that the style attribute has five different labels. They all 		      relate to positioning the layer and will be addresses in section 3, &#8220;Tell 		      the browser where to put the DIV,&#8221; below.</p><p>2. Put content within the DIV</p><p>Putting content between the &lt;div&#8230;&gt; and &lt;/div&gt; tags is providing 		      content for the layer.</p><p>The layer might contain an image tag, a word, paragraphs of text, or combination 		      text and images. The layer can contain anything web pages can contain, including 		      forms.</p><p>3. Tell the browser where to put the DIV</p><p>Telling the browser where to put the DIV tag is actually telling it where 		      to put the layer and its content.</p><p>The &#8220;top&#8221; and &#8220;left&#8221; labels &#8211;</p><p>The 2-dimension positioning is done with the &#8220;top&#8221; and &#8220;left&#8221; labels in the 		      style attribute. The number is in pixels. In the example DIV tag in section 		      1, &#8220;Create a DIV tag,&#8221; the layer is put 99 pixels from the top edge and 99 		      pixels from the left edge.</p><p>The &#8220;position&#8221; label &#8211;</p><p>The top edge of what? The left edge of what?</p><p>The &#8220;position&#8221; label gives the browser the answers to those questions.</p><p>If the position label&#8217;s value is &#8220;absolute,&#8221; then the number of pixels is 		      measured from the top of the browser window and from the left of the browser 		      window.</p><p>If the label&#8217;s value is &#8220;relative&#8221; however, the position is measured from 		      the position relative to the place in the HTML source code that you have 		      placed the DIV tag. If you&#8217;ve placed the DIV tag at the end of a paragraph, 		      the position will be calculated relative to the end of that paragraph. Using 		      the &#8220;relative&#8221; value does not position elements according to purpose of this 		      article, but it does have its uses in other situations.</p><p>The &#8220;z-index&#8221; label &#8211;</p><p>This label determines the third dimension of positioning when several layers 		      occupy the same pixel of the user&#8217;s screen. The value of the &#8220;z-index&#8221; label 		      determines which layer will be placed over the other. If two layers vie for 		      the same spot, one has a &#8220;z-index&#8221; value of &#8220;1&#8243; and the other a &#8220;z-index&#8221; 		      value of &#8220;2,&#8221; then the &#8220;2&#8243; value layer will be placed over the &#8220;1&#8243; value 		      layer.</p><p>The &#8220;z-index&#8221; label was used to place text over an image on the demonstration 		      page. The image was given a &#8220;z-layer&#8221; of 1 and the text a &#8220;z-layer&#8221; of &#8220;2.&#8221; 		      The demonstration page is at <a
href="http://willmaster.com/a/21t/pl.pl?art215" target="blank">http://willmaster.com/a/21t/pl.pl?art215</a></p><p>The &#8220;visibility&#8221; label &#8211;</p><p>Give the &#8220;visibility&#8221; label a value of &#8220;show&#8221; so it will be visible. For 		      other purposes, a layer might want to be hidden for a time, in which case 		      the value &#8220;hide&#8221; or &#8220;hidden&#8221; would be used.</p><p>Special Effects</p><p>Supposing the content of the layer is the word &#8220;hello,&#8221; the above would give 		      us a layer like this:</p><pre>&lt;div
   style="
      top: 99;
      left: 99;
      position: absolute;
      z-index: 1;
      visibility: show;"&gt;
hello
&lt;/div&gt;</pre><p><span
style="font-family: Verdana,Helvetica; font-size: x-small;"> If you want to give the layer a 		      background color or a border, you&#8217;ll also need to specify the size of the 		      layer. It&#8217;s done with these labels:</span></p><p>width: 266px;<br
/> height: 17px;</p><p>(The &#8220;px&#8221; represents pixels, although other units of measurements may be 		      specified.)</p><p>To give the layer a background color of yellow, use this label and value:</p><p>background: yellow;</p><p>To put a 1-pixel solid black border around the layer, specify these labels 		      and values:</p><p>border-color: #000000;<br
/> border-style: solid;<br
/> border-top-width: 1px;<br
/> border-bottom-width: 1px;<br
/> border-left-width: 1px;<br
/> border-right-width: 1px;</p><p>The &#8220;border-color&#8221; label can have a color name or hexadecimal color value.</p><p>The &#8220;border-style&#8221; label can have other values, such as &#8220;dotted&#8221; and &#8220;dashed,&#8221; 		      but some browsers print a solid line nevertheless.</p><p>The width of the border can be different for each side.</p><p>The copyright line layered over the image on the demonstration page is a 		      demonstration of giving a layer a border. The demonstration page is at <a
href="http://willmaster.com/a/21t/pl.pl?art215" target="blank">http://willmaster.com/a/21t/pl.pl?art215</a></p><p>Note: If you wish to apply other style elements within the layer, such as 		      font size or color, use a SPAN, P, or other tag instead of the DIV tag. A 		      DIV tag within a layer (somewhat like a DIV tag nested within a DIV tag) 		      can confuse some browsers.</p><p>When you need to position something on a web page exactly, so it stays in 		      that position regardless of what browser is used to view it, what the browser&#8217;s 		      preferences are, or the size of the browser window, you now know how to do 		      it.</p><p>The visitor&#8217;s browser must be able to render layers, of course, in order 		      to position your content. Most recent browser releases do.</p><p>Netscape 4.#, while it does render layers, doesn&#8217;t do a good job with more 		      than two layers over each other. If this is a high priority for you, you 		      might develop with Netscape 4.# and then verify your pages render correctly 		      in the later browsers.</p><p>Those browsers that don&#8217;t render layers will probably place the content in 		      the order it exists in your source code. That may be a consideration when 		      you decide where in the source code to put layer DIV tags.</p><p>Will Bontrager</p><p><strong>About the Author:</strong></p><p>Copyright 2003 Bontrager Connection, LLC<br
/> <a
href="http://www.web-source.net/cgi-bin/web/jump.cgi?ID=762" target="blank">William 		      Bontrager</a> Programmer/Publisher, &#8220;WillMaster Possibilities&#8221; <a
href="http://willmaster.com/possibilities/" target="blank">ezine</a> <a
href="mailto:possibilities@willmaster.com">mailto:possibilities@willmaster.com</a></p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/08/how-to-position-text-and-images-exactly-within-a-web-page/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Google Analytics Tutorial Part 2</title><link>http://www.seoexploration.com/2009/07/google-analytics-tutorial-part-2/</link> <comments>http://www.seoexploration.com/2009/07/google-analytics-tutorial-part-2/#comments</comments> <pubDate>Mon, 27 Jul 2009 15:23:00 +0000</pubDate> <dc:creator>anon</dc:creator> <category><![CDATA[Google-Analytics]]></category> <category><![CDATA[analytics]]></category> <category><![CDATA[flash code]]></category> <category><![CDATA[flash events]]></category> <category><![CDATA[google]]></category> <category><![CDATA[javascript events]]></category> <category><![CDATA[link position]]></category><guid
isPermaLink="false">http://www.seoexploration.com/2009/07/google-analytics-tutorial-part-2/</guid> <description><![CDATA[by Patrick Altoft on June 12, 2007 The Advanced Google Analytics Tutorial raised more questions than it answered so I have spent this afternoon going through everybody’s comments and trying to answer them. If you have any more questions please feel free to ask in the comments at the end of this post. Google has [...]]]></description> <content:encoded><![CDATA[<p><em>by</em> <a
title="google-analytics-tutorial" href="http://www.blogstorm.co.uk/google-analytics-tutorial/" target="_blank"><span>Patrick Altoft</span></a> <em>on</em> <abbr
title="2007-06-12">June 12, 2007</abbr></p><p>The Advanced Google Analytics Tutorial raised more questions than it answered so I have spent this afternoon going through everybody’s comments and trying to answer them.</p><p>If you have any more questions please feel free to ask in the comments at the end of this post.</p><p>Google has just announced a few new features including the ability (finally) to click on referring url’s and be taken to the referring page.</p><p>Michael asked:</p><blockquote><p>Is there a way to see stats based on a specific day? I’d love to be able to see which pages are more popular as I’ve changed my site over time. I might change link position or something for a week and it’d be nice to see stats for that time period only to be able to compare them.</p></blockquote><p>Click on <em>Content &gt; Top Content</em> and then scroll right down to the form that says Find url and type the page you want to view the stats for. In this case I wanted to view stats for users clicking on my outgoing (affiliate) links.</p><p><img
title="Find url" src="http://www.blogstorm.co.uk/images/ga2.gif" alt="Find url" /></p><p>From the chart below we can see that the link outgoing/top (named because it was at the top of the page) has had 1060 clicks in the time period selected.</p><p><img
title="The outgoing/top link had 1060 clicks" src="http://www.blogstorm.co.uk/images/ga-q1.jpg" alt="The outgoing/top link had 1060 clicks" /></p><p>If you look to the top right of the screen you should see a drop down box containing a data range.</p><p><img
title="Drop down data range box" src="http://www.blogstorm.co.uk/images/ga-q4.jpg" alt="Drop down data range box" /></p><p>Click on the box and enter your desired date ranges in the boxes (hint: click on the box and then the name of the month at the top of the calendar to highlight the whole month) and then click the “Apply Range” button.</p><p><img
title="Drop down date range box" src="http://www.blogstorm.co.uk/images/ga-q2.jpg" alt="Drop down date range box" /></p><p>The result should be a graph comparing data from the two date ranges, one range has a blue line and one is shown with a green line.</p><p><img
title="Date range box" src="http://www.blogstorm.co.uk/images/ga-q3.jpg" alt="Date range box" /></p><p>Hunter asked:</p><blockquote><p>How do we track flash movie plays with google analytics?</p></blockquote><p>Tracking Flash events is the same as tracking JavaScript events, just call the urchinTracker function:</p><p><code>javascript:urchinTracker('/homepage/flashbuttons/button1');</code></p><p><strong>Example Flash Code</strong></p><p><code>on (release) {</code></p><p>// Track with no action</p><p>getURL(&#8220;javascript:urchinTracker(&#8216;/folder/file&#8217;);&#8221;);</p><p>}</p><p>on (release) _</p><p>//Track with action</p><p>getURL(”javascript:urchinTracker(’/folder/file’);”);</p><p>_root.gotoAndPlay(3);</p><p>myVar = “Flash Track Test”</p><p>}<br
/> onClipEvent (enterFrame) {</p><p>getURL(”javascript:urchinTracker(’/folder/file’);”);</p><p>}</p><p><a
href="http://www.google.com/support/googleanalytics/bin/answer.py?answer=55520&amp;topic=11006">More details</a></p><p>LGR asked:</p><blockquote><p>Is there anyway to attach the onclick event handler on a link I want to track without editing the html, perhaps at the bottom of the page? Just wondering if it is possible to separate the HTML from the javascript so it is easier to maintain.</p></blockquote><p>Motorcycle Guy asked :</p><blockquote><p>Surely there is javascript to add that javascript to every external link? it seems dumb to have to rewrite your whole application.</p></blockquote><p>I don’t think there is an easy way to do this. The best way would be to make your site database driven and append some automatic variables to the events you want to track.</p><p>Another solution would be to give each of your links an id parameter and then to track clicks on each id and register the event that way.</p><p>If anybody has any better suggestions please post in the comments.</p><p>f4rrest commented:</p><blockquote><p>There are some things still only available in the old UI though, such as graphing country-specific visitors.</p></blockquote><p>Clicking on <em>Visitors &gt; Map Overlay</em> and then the Country detail level and finally selecting the graph view I was able to create the chart below. Is this what you were looking for? I suspect you wanted to see how traffic from a certain country changed over time but this isn’t possible unfortunately.</p><p><img
title="Traffic by country" src="http://www.blogstorm.co.uk/images/ga-q5.jpg" alt="Traffic by country" /></p><p>Slides asked:</p><blockquote><p>Can GA be used to track registered users and their activity on site?</p></blockquote><p>I don’t think GA is the right solution to track individual user sessions and activity on a website. Depending on the data you want to track it sounds like a php application would be best.</p><p>darnit commented:</p><blockquote><p>I would love to know how to view the pages sending traffic in the referring information statistics. Not just the domain but a link to the actual page sending traffic.</p></blockquote><p>Clicking on <em>Traffic Sources &gt; Referring Sites</em> and then clicking on del.icio.us (or any of the other sites on the list) you can see a list of the referring pages as well as build a pie chart to visualise the data. Click the “Views” icons to view the pie chart.</p><p><img
title="Referring pages" src="http://www.blogstorm.co.uk/images/ga-q6.jpg" alt="Referring pages" /></p><p>This method falls down on sites where the referring page is site.com/page.php?id=12345 as Google strips the id parameter off. It works fine for most blogs as they tend to use a folder structure rather than dynamic urls.</p><p>Any more questions feel free to ask</p> ]]></content:encoded> <wfw:commentRss>http://www.seoexploration.com/2009/07/google-analytics-tutorial-part-2/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>
<!-- Served from: www.seoexploration.com @ 2012-02-05 11:41:42 by W3 Total Cache -->
