<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>W-Shadow.com</title>
	
	<link>http://w-shadow.com</link>
	<description>A blog about web development, software business, and WordPress</description>
	<lastBuildDate>Wed, 16 May 2012 14:55:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/wshadowcom" /><feedburner:info uri="wshadowcom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>wshadowcom</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Adding A Notification Bubble To An Admin Menu Item</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/ZzMmp-S4X8U/</link>
		<comments>http://w-shadow.com/blog/2012/05/03/adding-a-notification-bubble-to-an-admin-menu-item/#comments</comments>
		<pubDate>Thu, 03 May 2012 09:09:51 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[WordPress Development]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2727</guid>
		<description><![CDATA[You&#8217;ve probably seen the small notification bubble that shows up in the Dashboard menu when a new update is available. Here&#8217;s how you can add a menu bubble to your own custom menu: The resulting menu will look like this: Copyright &#169; 2012 W-Shadow.com. This Feed is for personal non-commercial use only. If you are [...]]]></description>
			<content:encoded><![CDATA[<p>You&#8217;ve probably seen the small notification bubble that shows up in the Dashboard menu when a new update is available. Here&#8217;s how you can add a menu bubble to your own custom menu:</p>
<pre class="brush: php; title: ; notranslate">
function add_menu_with_notification_bubble() {
	$bubble = sprintf(
		' &lt;span class=&quot;update-plugins&quot;&gt;&lt;span class=&quot;update-count&quot;&gt;%d&lt;/span&gt;&lt;/span&gt;',
		42 //bubble contents
	);
	add_dashboard_page(
		'Example Menu',
		'Example Menu' . $bubble,
		'read',
		'example-menu-item'
	);
}
add_action('admin_menu', 'add_menu_with_notification_bubble');
</pre>
<p>The resulting menu will look like this:</p>
<p><img class="alignnone" title="Notification bubbles in the WordPress menu" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/notification-bubble-example2.png" alt="" width="170" height="152" /></p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A1--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ZzMmp-S4X8U:Ns0aXpQkaPI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=ZzMmp-S4X8U:Ns0aXpQkaPI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ZzMmp-S4X8U:Ns0aXpQkaPI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=ZzMmp-S4X8U:Ns0aXpQkaPI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/ZzMmp-S4X8U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2012/05/03/adding-a-notification-bubble-to-an-admin-menu-item/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2012/05/03/adding-a-notification-bubble-to-an-admin-menu-item/</feedburner:origLink></item>
		<item>
		<title>Security Tip: Block Direct Access To Plugin PHP Files</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/GGG8xBFqNcA/</link>
		<comments>http://w-shadow.com/blog/2012/04/27/block-access-to-plugin-php-files/#comments</comments>
		<pubDate>Fri, 27 Apr 2012 09:00:50 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[htaccess file]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[WordPress security]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2720</guid>
		<description><![CDATA[Plugins are usually loaded and executed along with the rest of WordPress. However, since each plugin is physically just set of .php, .css and .js files, it is also possible for someone to bypass the normal load order and execute the plugin files directly.  They just need to type the right URL in the address [...]]]></description>
			<content:encoded><![CDATA[<p>Plugins are usually loaded and executed along with the rest of WordPress. However, since each plugin is physically just set of .php, .css and .js files, it is also possible for someone to bypass the normal load order and execute the plugin files directly.  They just need to type the right URL in the address bar.</p>
<p>Security-wise, this is dangerous for two reasons:</p>
<ul>
<li>Most plugins are not designed to be accessed in this way and will simply crash. The error message, if any, can disclose sensitive information about your site.</li>
<li>Most plugin developers don&#8217;t expect anyone to access the plugin .php files directly. Doing so may trigger a dangerous bug or vulnerability that they haven&#8217;t tested for.</li>
</ul>
<p>While the chances of either happening are admittedly fairly slim, it doesn&#8217;t hurt to safe-guard your site from this type of attack. Luckily, disabling direct browser access plugin .php files is very easy. Just create a text file named &#8220;.htaccess&#8221; in your <code>/wp-content/plugins</code> directory and place this code in the file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;FilesMatch &quot;\.php$&quot;&gt;
	Order deny,allow
	Deny from all
&lt;/FilesMatch&gt;
</pre>
<p>Now anyone who tries to load a plugin PHP file in their browser will now get a &#8220;Forbidden&#8221; error.</p>
<p><strong>A word of warning</strong></p>
<p><strong></strong>This <em>will</em> break some plugins. While most plugins only need their CSS, JS and image files to be accessible via the web browser, a handful also rely on .php files being directly accessible (e.g. for AJAX or dynamically generated CSS).</p>
<p>If you find out that one of your plugins doesn&#8217;t work, create a .htaccess file in that plugin&#8217;s directory and place the following code in the file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;FilesMatch &quot;\.php$&quot;&gt;
	Order deny,allow
	Allow from all
&lt;/FilesMatch&gt;
</pre>
<p>This will re-enable browser access to .php files for just that directory.</p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A1--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GGG8xBFqNcA:hP07-Y-WV0Q:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=GGG8xBFqNcA:hP07-Y-WV0Q:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GGG8xBFqNcA:hP07-Y-WV0Q:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GGG8xBFqNcA:hP07-Y-WV0Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/GGG8xBFqNcA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2012/04/27/block-access-to-plugin-php-files/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2012/04/27/block-access-to-plugin-php-files/</feedburner:origLink></item>
		<item>
		<title>Cleaning Up Stale Transients</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/rQe1hlT0qaI/</link>
		<comments>http://w-shadow.com/blog/2012/04/17/delete-stale-transients/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 13:00:25 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[Transients API]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2734</guid>
		<description><![CDATA[WordPress transients are very similar to DB options but they also support expiration times. The Transients API documentation states: Our transient will die naturally of old age once $expiration seconds have passed since we last ran set_transient() What you might not know if you haven&#8217;t explored the source code of the transients API is that [...]]]></description>
			<content:encoded><![CDATA[<p>WordPress transients are very similar to DB options but they also support expiration times. The <a href="http://codex.wordpress.org/Transients_API">Transients API documentation</a> states:</p>
<blockquote><p>Our transient will die naturally of old age once $expiration seconds have passed since we last ran set_transient()</p></blockquote>
<p>What you might not know if you haven&#8217;t explored the source code of the transients API is that transients stored in the database* will not actually &#8220;die of old age&#8221;. Instead, a stale transient will stick around until someone tries to access it. Only then will WordPress notice that the transient has expired and delete it. If no-one ever attempts to read a stale transient &#8211; e.g. because the plugin that created it has been uninstalled &#8211; it will stay in your database forever.</p>
<p><em>* If you have a suitable caching plugin installed, transients can be stored in a fast in-memory cache like APC or Memcached instead of the database.</em></p>
<p>Fortunately, since the expiration time of each transient is also stored in the database, we can easily clean up stale transients with a little bit of SQL magic. Run the two queries below to delete all stale transients. You can use either phpMyAdmin or a plugin like <a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> to execute SQL queries.</p>
<pre class="brush: sql; title: ; notranslate">
DELETE a, b
FROM
	wp_options a, wp_options b

WHERE
 a.option_name LIKE &quot;_transient_%&quot; AND
 a.option_name NOT LIKE &quot;_transient_timeout_%&quot; AND
 b.option_name = CONCAT(
		&quot;_transient_timeout_&quot;,
		SUBSTRING(
			a.option_name,
			CHAR_LENGTH(&quot;_transient_&quot;) + 1
		)
	)
 AND b.option_value &lt; UNIX_TIMESTAMP()
</pre>
<p>&nbsp;</p>
<pre class="brush: sql; title: ; notranslate">
DELETE a, b
FROM
	wp_options a, wp_options b

WHERE
 a.option_name LIKE &quot;_site_transient_%&quot; AND
 a.option_name NOT LIKE &quot;_site_transient_timeout_%&quot; AND
 b.option_name = CONCAT(
		&quot;_site_transient_timeout_&quot;,
		SUBSTRING(
			a.option_name,
			CHAR_LENGTH(&quot;_site_transient_&quot;) + 1
		)
	)
 AND b.option_value &lt; UNIX_TIMESTAMP()
</pre>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A3--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rQe1hlT0qaI:tQ2VKGWgqN0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=rQe1hlT0qaI:tQ2VKGWgqN0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rQe1hlT0qaI:tQ2VKGWgqN0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rQe1hlT0qaI:tQ2VKGWgqN0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/rQe1hlT0qaI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2012/04/17/delete-stale-transients/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2012/04/17/delete-stale-transients/</feedburner:origLink></item>
		<item>
		<title>WordPress Spring Cleaning – The Master List For Cleaning Up Your Blog</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/TA1V9eRS-aE/</link>
		<comments>http://w-shadow.com/blog/2012/04/10/wordpress-spring-cleaning-the-master-list-for-cleaning-up-your-blog/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 13:00:08 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2696</guid>
		<description><![CDATA[Now that spring has arrived (at least in the Northern Hemisphere), it is an excellent time to clean up and decruft your WordPress site. In this post I will show you a number of plugins and techniques that you can use to do just that. Note: Back up your database before running any of the [...]]]></description>
			<content:encoded><![CDATA[<p>Now that spring has arrived (at least in the Northern Hemisphere), it is an excellent time to clean up and decruft your WordPress site. In this post I will show you a number of plugins and techniques that you can use to do just that.</p>
<p><em>Note:</em> Back up your database before running any of the plugins or queries presented below.</p>
<h3>Delete inactive plugins and themes</h3>
<p>Not only do inactive plugins and themes waste disk space, they also clutter your database with unused settings and other metadata. Remember: most plugins won&#8217;t delete their DB options and tables until you completely uninstall them. You will also continue to receive update notifications, which can be a distraction. Remove any plugins and themes you&#8217;re not using any more.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2711" title="Delete inactive plugins" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/delete-inactive-plugins.png" alt="" width="504" height="234" /></p>
<h3>Delete orphaned DB options</h3>
<p>As mentioned above, plugins should automatically clean up their database entries when you uninstall them. Unfortunately, not all of them do, which leads to some entries becoming &#8220;orphaned&#8221;. Use the <a href="http://wordpress.org/extend/plugins/clean-options/">Clean Options</a> plugin to delete DB options left behind by those untidy plugins.</p>
<p><a href="http://wordpress.org/extend/plugins/clean-options/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2716" title="Clean Options screenshot" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/find-orphaned-options.png" alt="" width="485" height="248" /></a></p>
<h3>Delete orphaned database tables</h3>
<p>First, use <a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> to get a list of all tables in your database. Compare it to <a href="http://codex.wordpress.org/Database_Description#Table_Overview">the list of WordPress core tables</a>. Any table <em>not</em> on that list is part of a plugin. If you spot any tables that have been orphaned by uninstalled plugins, use the &#8220;drop&#8221; command to delete them.</p>
<p><a href="http://wordpress.org/extend/plugins/wp-dbmanager/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2701" title="WP-DBManager screenshot" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/wp-dbmanager-screenshot.png" alt="" width="473" height="213" /></a></p>
<h3>Delete post revisions</h3>
<p>The post revision feature can be useful, but it also tends to fill up your database pretty quickly since WordPress creates a new revision each time you edit a post. There are several ways to fix this problem.</p>
<p><strong>Delete all post revisions</strong></p>
<p>You can use <a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP-Cleanfix</a> or <a href="http://wordpress.org/extend/plugins/wp-optimize/">WP-Optimize</a> to get rid of any and all post revisions.</p>
<p><a href="http://wordpress.org/extend/plugins/wp-cleanfix/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2704" title="WP-CleanFix screenshot" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/wp-cleanfix-post-screenshot.png" alt="" width="587" height="246" /></a></p>
<p><strong>Delete only old post revisions</strong></p>
<p>In some cases you may want to clean out old revisions while leaving the most recent &#8211; and thus most likely to be useful &#8211; revisions intact. This SQL query will delete only post revisions created before March 1st, 2012:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE a, b, c
FROM wp_posts a
LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
WHERE
	a.post_type = 'revision' AND
	a.post_date &lt; '2012-03-1'
</pre>
<p>Use <a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> or a similar plugin to run this query.</p>
<p><strong>Limit the number of revisions per post</strong></p>
<p>Add this line to your <code>wp-config.php</code> file to limit the number of revisions to 5 per post:</p>
<pre class="brush: php; title: ; notranslate">
define('WP_POST_REVISIONS', 5);
</pre>
<p><strong>Disable revisions</strong></p>
<p>Add this line to your wp-config.php to completely disable post revisions:</p>
<pre class="brush: php; title: ; notranslate">
define('WP_POST_REVISIONS', 0);
</pre>
<p>Note that this does not remove existing revisions. Use one of the other techniques discussed above to do that.</p>
<h3>Delete spam comments</h3>
<p>Even small blogs can receive thousands of spam comments per month. If left unchecked, all the spam will gradually accumulate in your database, potentially slowing down comment queries and hurting your site&#8217;s performance. Make sure to regularly clean out the spam by clicking the &#8220;Empty Spam&#8221; button in <em>Comments -&gt; Spam</em>.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2712" title="Delete spam comments" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/empty-spam.png" alt="" width="525" height="254" /></p>
<p><strong>Bonus tip:</strong> I strongy recommend the <a href="http://wordpress.org/extend/plugins/nospamnx/">NoSpamNX</a> plugin to anyone receiving large amounts of spam. It&#8217;s a great &#8220;first line of defence&#8221; and can be configured to discard spam comments immediately instead of storing them in the database.</p>
<h3>Delete pingbacks</h3>
<p>If your comments table still takes up a lot of space even after you&#8217;ve deleted all spam comments, consider removing some or all the received pingbacks. While pingbacks can be useful as a way to be notified when someone mentions your content, old pingbacks lose their relevance quickly. Pingbacks are also frequently abused by spammers.</p>
<p>This query will delete all pingbacks received before March 1st, 2012:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_comments
WHERE
   comment_type = 'pingback' AND
   comment_date &lt; '2012-03-01';
</pre>
<h3>Scan your site for malware</h3>
<p>Check that your blog is free from malware and suspicious code by <a href="http://sucuri.net/">scanning it with Sucuri.net</a>.</p>
<p><a href="http://sucuri.net/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2702" title="Sucuri scan results" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/sucuri-scan-screenshot.png" alt="" width="496" height="327" /></a></p>
<h3>Find and fix broken links</h3>
<p>Use <a href="http://wordpress.org/extend/plugins/broken-link-checker/">Broken Link Checker</a> to check your site for broken links, missing images, removed YouTube videos and similar issues.</p>
<p style="text-align: center;"><a href="http://wordpress.org/extend/plugins/broken-link-checker/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2703" title="Broken Link Checker screenshot" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/broken-link-checker-screenshot.png" alt="" width="490" height="302" /></a></p>
<h3>Delete unused post and comment meta</h3>
<p>Unused post meta keys are another kind of database cruft that can be left behind by long-since-uninstalled plugins and themes. You can use the <a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP CleanFix</a> plugin I mentioned before or <a href="http://wordpress.org/extend/plugins/wp-cleanup/">WP-Cleanup</a> to remove them.</p>
<p>Alternatively, if you would prefer to do it without a plugin, the following SQL query will also remove all instances of the specified post meta key:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_postmeta WHERE meta_key = 'unused meta-key-name';
</pre>
<p>And this query will do the same for the comment meta table:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_commentmeta WHERE meta_key = 'unused-meta-key-name';
</pre>
<p>Finally, if you have a lot of registered users, you might also want to check for and remove unused user meta keys. Here&#8217;s a query to delete an unused piece of user metadata:</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_usermeta WHERE meta_key = 'unused-meta-key-name';
</pre>
<p>Also, see <a href="http://www.shoutmeloud.com/how-to-delete-custom-field-value-from-wordpress-database.html">this tutorial</a> for a more in-depth explanation of how to find and remove unused custom fields with phpMyAdmin.</p>
<h3>Remove unused tags and categories</h3>
<p>If you have a lot of unused tags or categories on your site, clean them up to reduce the database size and gain a little bit of performance. Both <a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP CleanFix</a> and <a href="http://wordpress.org/extend/plugins/wp-cleanup/">WP-Cleanup</a> can help you get rid of unused tags.</p>
<p><a href="http://wordpress.org/extend/plugins/wp-cleanfix/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2705" title="WP CleaFix - remove unused tags and categories" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/wp-cleanfix-categories-screenshot.png" alt="" width="498" height="221" /></a></p>
<p>Alternatively, this set of SQL queries will accomplish the same task (props to <a href="http://4rapiddev.com/tips-and-tricks/wordpress-delete-unused-post-tags-by-sql-command/">4 Rapid Development</a>):</p>
<pre class="brush: sql; title: ; notranslate">
DELETE FROM wp_terms WHERE term_id IN (SELECT term_id FROM wp_term_taxonomy WHERE COUNT = 0 );
DELETE FROM wp_term_taxonomy WHERE term_id NOT IN (SELECT term_id FROM wp_terms);
DELETE FROM wp_term_relationships WHERE term_taxonomy_id NOT IN (SELECT term_taxonomy_id FROM wp_term_taxonomy);
</pre>
<h3>Remove unused shortcodes</h3>
<p>If you&#8217;ve been blogging for a while, you&#8217;ve probably run into this problem: you uninstall a plugin or switch to a different theme, and now your site is full of shortcodes that no longer work. Obviously, going back and editing each post one-by-one is not going to work. You need a way to automatically remove the unused shortcodes.</p>
<p>Well, <a href="http://wordpress.org/extend/plugins/search-and-replace/">Search and Replace</a> is just the ticket. It lets you search your posts for a piece of text and replace it something else.</p>
<p style="text-align: center;"><a href="http://wordpress.org/extend/plugins/search-and-replace/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2708" title="Search and Replace screenshot" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/search-and-replace-screenshot.png" alt="" width="537" height="293" /></a></p>
<p>Alternatively, here&#8217;s a query that will remove all instances of the specified [shortcode] from your posts (props to <a href="http://www.wprecipes.com/wordpress-tip-get-rid-of-unused-shortcodes">WPRecipes</a>):</p>
<pre class="brush: sql; title: ; notranslate">
UPDATE wp_post SET post_content = replace(post_content, '[shortcode]', '' ) ;
</pre>
<p>Note that the above only works with self-closing shortcodes. For self-closing shortcodes like &#8220;[shortcode] content [/shortcode]&#8221; you&#8217;ll need to use <a href="http://wordpress.org/extend/plugins/search-regex/">regular expression search</a>.</p>
<h3>Delete commenter&#8217;s user agent</h3>
<p>For each comment your blog receives, WordPress also stores the comment author&#8217;s user agent (basically, the web browser fingerprint) along with the rest of the comment. This can be handy for advanced users, but most bloggers will never need this information. You can shrink your database a bit by removing the user agent records.</p>
<p>Run this query to remove the user agent information from your database (props to <a href="http://www.rsatechnologies.in/best-sql-queries-for-wordpress-administrator.html">RSA Blog</a>):</p>
<pre class="brush: sql; title: ; notranslate">
UPDATE wp_comments SET comment_agent = '';
</pre>
<h3>Delete unused images</h3>
<p>Free up some disk space by deleting images not attached to any post or page. Go to <em>Media -&gt; Library -&gt; Unattached</em>, select all items, choose &#8220;Delete Permanently&#8221; from the &#8220;Bulk Action&#8221; drop-down and click &#8220;Apply&#8221;.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2713" title="Delete unused attachments" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/delete-unused-attachments.png" alt="" width="438" height="233" /></p>
<p>Another option is to use <a href="http://wordpress.org/extend/plugins/upload-janitor/">Upload Janitor</a> or <a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP CleanFix</a> to automate the process.</p>
<h3>Optimize database tables</h3>
<p>It&#8217;s good practice to optimize your tables regularly. Database optimization helps keep site performance steady and is especially useful after you&#8217;ve just made large change to the DB (like cleaning up all post revisions and unused meta keys). You can use <a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> to schedule automatic DB optimization. <a href="http://wordpress.org/extend/plugins/wp-optimize/">WP-Optimize</a> also includes the database optimization feature, but does not support scheduling.</p>
<p><a href="http://wordpress.org/extend/plugins/wp-dbmanager/"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2706" title="WP-DBManager database optimization scheduling" src="http://1.shadowcdn.com/wp-content/uploads/2012/04/wp-dbmanager-database-optimization.png" alt="" width="694" height="186" /></a></p>
<h3>Resources</h3>
<p>For reference, here&#8217;s a list of all plugins mentioned in this post (in alphabetical order):</p>
<ul>
<li><a href="http://wordpress.org/extend/plugins/broken-link-checker/">Broken Link Checker</a> &#8211; scan your site for broken links.</li>
<li><a href="http://wordpress.org/extend/plugins/clean-options/">Clean Options</a> &#8211; detect and remove orphaned DB options.</li>
<li><a href="http://wordpress.org/extend/plugins/nospamnx/">NoSpamNX</a> &#8211; block spam comments.</li>
<li><a href="http://wordpress.org/extend/plugins/search-and-replace/">Search and Replace </a>- find &amp; replace text in your posts, comments, etc.</li>
<li><a href="http://wordpress.org/extend/plugins/search-regex/">Search Regex</a> &#8211; find &amp; replace with regular expression support.</li>
<li><a href="http://wordpress.org/extend/plugins/upload-janitor/">Upload Janitor</a> &#8211; find and delete unused images.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP CleanFix</a> &#8211; delete post revisions, unused meta, and much more.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-cleanup/">WP-Cleanup</a> &#8211; delete revisions, unused tags, post meta, etc.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-dbmanager/">WP-DBManager</a> &#8211; manage and optimize your database.</li>
<li><a href="http://wordpress.org/extend/plugins/wp-optimize/">WP-Optimize</a> &#8211; remove revisions, auto-draft posts, optimize tables, etc.</li>
</ul>
<p>Final note: As you may have noticed, many of the &#8220;clean up&#8221; plugins &#8211; WP-Cleanup, WP-CleanFix, and so on &#8211; have a very similar feature set. So which should you use? Overall, <a href="http://wordpress.org/extend/plugins/wp-cleanfix/">WP CleanFix</a> seems to be the most comprehensive solution, so I would recommend that one.</p>
<p>a href=&#8221;http://wordpress.org/extend/plugins/broken-link-checker/&#8221;</p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A43--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=TA1V9eRS-aE:efTm0yv2zPU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=TA1V9eRS-aE:efTm0yv2zPU:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=TA1V9eRS-aE:efTm0yv2zPU:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=TA1V9eRS-aE:efTm0yv2zPU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/TA1V9eRS-aE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2012/04/10/wordpress-spring-cleaning-the-master-list-for-cleaning-up-your-blog/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2012/04/10/wordpress-spring-cleaning-the-master-list-for-cleaning-up-your-blog/</feedburner:origLink></item>
		<item>
		<title>Automatic Updates For Private And Commercial Themes</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/GyIMZSp8DXo/</link>
		<comments>http://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 10:53:37 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[WordPress Tools]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[update notifications]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wordpress theme]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2331</guid>
		<description><![CDATA[This is a PHP library that lets you add automatic update notifications and single-click updates to any WordPress theme. It&#8217;s purpose is to be easy to integrate for developers and to provide a familiar experience to theme users. From the users&#8217; point of view, update notifications generated by this library will look and function just [...]]]></description>
			<content:encoded><![CDATA[<p>This is a PHP library that lets you add automatic update notifications and single-click updates to any WordPress theme. It&#8217;s purpose is to be easy to integrate for developers and to provide a familiar experience to theme users. From the users&#8217; point of view, update notifications generated by this library will look and function just like those displayed by WP itself.</p>
<div id="attachment_2340" class="wp-caption aligncenter" style="width: 500px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; display: block; margin-right: auto; margin-left: auto;"><a href="http://1.shadowcdn.com/wp-content/uploads/2011/06/theme-updater-screenshot.png"><img class="size-large wp-image-2340" title="An update notification for a private theme" src="http://1.shadowcdn.com/wp-content/uploads/2011/06/theme-updater-screenshot-490x139.png" alt="Dashboard screenshot" width="490" height="139" /></a><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">An update notification for a theme not hosted on wordpress.org</p></div>
<h3>Download</h3>
<ul>
<li><strong><a href="http://1.shadowcdn.com/files/theme-updates.zip">Client library</a></strong> (requires PHP 5 and WP 3.0 or later)</li>
<li><strong><a href="http://1.shadowcdn.com/files/example-theme-1.0.zip">Example theme</a></strong></li>
<li><strong><a href="http://1.shadowcdn.com/files/example-theme-updates/info.json">Example metadata file</a></strong></li>
</ul>
<h3>License</h3>
<form style="float: right; margin-top: 1em;" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" />
<input type="hidden" name="hosted_button_id" value="CYSRQ7QASECVJ" />
<input type="image" name="submit" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="PayPal - The safer, easier way to pay online!" /> <img src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" alt="" width="1" height="1" border="0" /></form>
<p>This library is licensed under the <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>and is distributed free of charge. If you find it useful, consider making a donation. Commercial licensing (e.g. for projects that can&#8217;t use an open-source license) is available upon request.</p>
<h3>Quick-Start Guide</h3>
<p>There are two things you will need to do:</p>
<ol>
<li>Create a publicly accessible &#8220;metadata file&#8221; that describes the latest version of your theme.</li>
<li>Add the update checker to your theme and tell it where to find that file.</li>
</ol>
<p>First, the metadata file. Open your favourite text editor and copy the following <a href="http://www.json.org/">JSON</a> code into a new file:</p>
<pre class="brush: jscript; title: ; notranslate">
{
  &quot;version&quot; : &quot;2.0&quot;,
  &quot;details_url&quot; : &quot;http://example.com/example-theme/details.html&quot;,
  &quot;download_url&quot; : &quot;http://examle.com/example-theme/example-theme.zip&quot;
}
</pre>
<p>Replace the placeholder values with your own data. As you can probably guess, <code>version</code> is the version number of your theme. <code>details_url</code> specifies the page that the user will see if they click the &#8220;View version 1.2.3 details&#8221; link in an update notification. Set this field to your &#8220;What&#8217;s New In Version 1.2.3&#8243; page or the theme homepage. Finally, <code>download_url</code> is the URL where the latest version of the theme can be downloaded. This field is optional. If you leave it out, the user will still get an update notification when a new version comes out, but there will be no &#8220;update automatically&#8221; link. They&#8217;ll have to download and install the update manually. </p>
<p>Upload the metadata file to your website. You can use any directory and file name you like; just remember that the file URL should be accessible from wherever someone might install your theme. </p>
<p>Next, lets add the update checker library to you theme. Copy the &#8220;theme-updates&#8221; directory from the <a href="http://1.shadowcdn.com/files/theme-updates.zip">client library</a> to your theme. Then add the following to your <code>functions.php</code>:</p>
<pre class="brush: php; title: ; notranslate">
//Initialize the update checker.
require 'theme-updates/theme-update-checker.php';
$example_update_checker = new ThemeUpdateChecker(
    'example-theme',
    'http://example.com/example-theme/info.json'
);
</pre>
<p>Again, replace the placeholders with your own settings. The first argument should be the name of your theme&#8217;s directory. For example, if your theme lives in /wp-content/themes/my-theme/, use &#8220;my-theme&#8221; here. The second argument should be the URL of the metadata file you just created. </p>
<p>Congratulations, your theme now supports automatic updates :) The update checker will automatically query the metadata file every 12 hours, checking to see if a new version is available. If it finds one, it will display a standard theme update notification on the Dashboard. Your users will be able to install the new version with a single click.</p>
<h3>The ThemeUpdateChecker class</h3>
<p><strong>Class constructor</strong>The library is configured by passing a number of arguments to the ThemeUpdateChecker constructor. They are, in order :</p>
<ul>
<li><code>$theme</code> &#8211;  The theme directory name, sometimes called the &#8220;slug&#8221;.</li>
<li><code>$metadataUrl</code> &#8211; The URL of the theme metadata file.</li>
<li><code>$enableAutomaticChecking</code> &#8211; Enable/disable automatic update checking. If set to FALSE, you&#8217;ll need to explicitly call the checkForUpdates method to, err, check for updates. Defaults to TRUE.</li>
</ul>
<p><strong>checkForUpdates()</strong><br />
Manually trigger an update check. This is useful if you want to do update checks on your own schedule. checkForUpdates has no parameters and does not return anything. If you want to actually <em>retrieve</em> the latest update, use requestUpdate instead. </p>
<p><strong>requestUpdate()</strong><br />
Retrieve update information from the configured metadata URL. Returns either an instance of ThemeUpdate, or NULL if there is no newer version available or if there&#8217;s an error. </p>
<p><strong>deleteStoredData()</strong><br />
The update checker stores various update-related bookkeeping data in a DB option. Call this method to delete that data. This is can be useful is your theme provides some kind of &#8220;uninstall&#8221; feature. </p>
<p><strong>addQueryArgFilter($callback)</strong><br />
Register a callback for filtering query arguments. Whenever the update checker needs to retrieve the metadata file, it will first run each filter callback and attach the query arguments that they return to the metadata URL. This lets you pass arbitrary data to the server hosting the metadata. For example, commercial themes could use it to implement some kind of authorization scheme where only paying users get automatic updates. </p>
<p>The callback function will be passed an associative array of query arguments and should return a modified array. By default, the update checker will append the following query arguments to the URL:</p>
<ul>
<li>installed_version &#8211; the currently installed version of the theme.</li>
</ul>
<p>This method takes one parameter – the callback function. </p>
<p><strong>addHttpRequestArgFilter($callback)</strong><br />
Register a callback for filtering arguments passed to <a href="http://codex.wordpress.org/HTTP_API#Helper_Functions">wp_remote_get</a>. The callback function should take one argument – an associative array of arguments – and return a modified array or arguments. See the WP documentation for details about what arguments are available and how they work. This method takes one parameter – the callback function. </p>
<p><strong>addResultFilter($callback)</strong><br />
Register a callback for filtering theme info retrieved from the metadata URL. The callback function should take two arguments. If a theme update was retrieved successfully, the first argument will be an instance of ThemeUpdate. Otherwise, it will be NULL. The second argument will be the corresponding return value of wp_remote_get (see WP docs for details). The callback function should return an instance of ThemeUpdate, or NULL. This method takes one parameter – the callback function.</p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A9--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GyIMZSp8DXo:ejHG36w_qx8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=GyIMZSp8DXo:ejHG36w_qx8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GyIMZSp8DXo:ejHG36w_qx8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=GyIMZSp8DXo:ejHG36w_qx8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/GyIMZSp8DXo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/06/02/automatic-updates-for-commercial-themes/</feedburner:origLink></item>
		<item>
		<title>FindBroken Beta</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/gLdP9G0Pt4Y/</link>
		<comments>http://w-shadow.com/blog/2011/03/07/findbroken-beta/#comments</comments>
		<pubDate>Mon, 07 Mar 2011 09:48:38 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Web Apps]]></category>
		<category><![CDATA[broken link checker]]></category>
		<category><![CDATA[crawler]]></category>
		<category><![CDATA[find broken]]></category>
		<category><![CDATA[find broken links]]></category>
		<category><![CDATA[news]]></category>
		<category><![CDATA[saas]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2299</guid>
		<description><![CDATA[Here&#8217;s something I&#8217;ve been working on for the last month or so: FindBroken.com. It&#8217;s an automated link checker that periodically scans your site for broken links and alerts you by email if any are found. Basically, it&#8217;s like a hosted version of the Broken Link Checker plugin, only simpler and not WordPress-specific. The site is [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s something I&#8217;ve been working on for the last month or so: <a title="FindBroken" href="http://findbroken.com/">FindBroken.com</a>. It&#8217;s an automated link checker that periodically scans your site for broken links and alerts you by email if any are found. Basically, it&#8217;s like a hosted version of the <a href="http://w-shadow.com/blog/2007/08/05/broken-link-checker-for-wordpress/">Broken Link Checker plugin</a>, only simpler and not WordPress-specific.</p>
<p>The site is still in early beta, so some features may a little rough around the edges or just plain missing. Nevertheless, I encourage you to <a href="http://findbroken.com/">go check it out</a> and let me know what you think. All feedback is welcome.</p>
<h3>What already works</h3>
<ul>
<li>Add/remove sites.</li>
<li>Monitor multiple sites with one account.</li>
<li>Automatic daily scans.</li>
<li>Email notifications.</li>
</ul>
<h3>What doesn&#8217;t quite work</h3>
<ul>
<li>The crawler that I use is slow to get going. Sometimes it can take ~30 minutes before any progress is visible.</li>
<li>Redirects are currently not followed.</li>
<li>There&#8217;s a fair amount of false positives. Luckily, most of them are temporary and don&#8217;t show up when using the &#8220;persistent&#8221; filter.</li>
<li>The site could use some UX love.</li>
</ul>
<h3>Screenshots</h3>
<p style="text-align: center;"><a href="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-add-site.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2305" title="Adding a site" src="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-add-site-thumb.png" alt="" width="480" height="187" /></a></p>
<p style="text-align: center;"><a href="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-site-list.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2307" title="Site list" src="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-site-list-thumb.png" alt="" width="480" height="145" /></a></p>
<p style="text-align: center;"><a href="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-alerts.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2306" title="Alerts" src="http://1.shadowcdn.com/wp-content/uploads/2011/03/findbroken-alerts-thumb.png" alt="" width="480" height="348" /></a></p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A7--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=gLdP9G0Pt4Y:96y3-slBKGQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=gLdP9G0Pt4Y:96y3-slBKGQ:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=gLdP9G0Pt4Y:96y3-slBKGQ:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=gLdP9G0Pt4Y:96y3-slBKGQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/gLdP9G0Pt4Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/03/07/findbroken-beta/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/03/07/findbroken-beta/</feedburner:origLink></item>
		<item>
		<title>How To Convert Your WordPress Blog To A Static Site</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/Fh7tbOlVgp8/</link>
		<comments>http://w-shadow.com/blog/2011/02/02/how-to-convert-your-wordpress-blog-to-a-static-site/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 09:09:42 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[static html]]></category>
		<category><![CDATA[static html files]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2290</guid>
		<description><![CDATA[Recently, I found this old question on WordPress StackExchange: I am starting a new WordPress blog, and no longer updating an old one. [...] How can I lock the installation of WordPress down so I don&#8217;t need to maintain it? I have seen someone suggest making a static version, which sounds like a lot of [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I found <a href="http://wordpress.stackexchange.com/questions/6109/how-can-i-lock-down-an-old-wordpress-install-i-dont-intend-to-update">this old question</a> on WordPress StackExchange:</p>
<blockquote><p>I am starting a new WordPress blog, and no longer updating an old one. [...] How can I lock the installation of WordPress down so I don&#8217;t need to maintain it? I have seen someone suggest making a static version, which sounds like a lot of work.</p></blockquote>
<p>The <a href="http://wordpress.stackexchange.com/questions/6109/how-can-i-lock-down-an-old-wordpress-install-i-dont-intend-to-update/6117#6117">top-rated answer</a> is very good, but overly complicated. It involves custom code and .htaccess modification. I think I can offer a simpler solution. Here&#8217;s how you can turn your blog into a static site:</p>
<ol>
<li>Make a backup. Just in case.</li>
<li>Disable comments and any other dynamic features your blog may have, e.g. contact forms.</li>
<li>Install <a href="http://ocaoimh.ie/wp-super-cache/">WP-SuperCache</a> and set the cache expiry time to 604800 seconds (= one week).</li>
<li>Fire up <a href="http://home.snafu.de/tilman/xenulink.html">Xenu&#8217;s Link Sleuth</a> and tell it to crawl your entire site. This will make WP-SuperCache generate static HTML files for all of your pages.</li>
<li>Delete all .php files and drop the WordPress database.</li>
</ol>
<p>With all PHP scripts deleted, &#8220;expired&#8221; cache entries will never be removed, so the server will keep serving the same cached pages forever. Congratulations, your site now static :)  <em></em></p>
<p><em>Alas, the aforementioned SE thread is rather old, so if I posted my answer there, no-one would probably ever see it.</em></p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A5--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Fh7tbOlVgp8:zt0nfO_69x8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=Fh7tbOlVgp8:zt0nfO_69x8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Fh7tbOlVgp8:zt0nfO_69x8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=Fh7tbOlVgp8:zt0nfO_69x8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/Fh7tbOlVgp8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/02/02/how-to-convert-your-wordpress-blog-to-a-static-site/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/02/02/how-to-convert-your-wordpress-blog-to-a-static-site/</feedburner:origLink></item>
		<item>
		<title>Page Load Time vs SEO: My Experience</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/rmU49lCM9X8/</link>
		<comments>http://w-shadow.com/blog/2011/02/01/page-load-time-vs-seo-my-experience/#comments</comments>
		<pubDate>Tue, 01 Feb 2011 18:50:24 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Google Search]]></category>
		<category><![CDATA[load time]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2279</guid>
		<description><![CDATA[It is hardly news that the average load time is one of the many factors that Google uses to determine how well your site will rank. But how much does it matter, really? If my recent experience is anything to go by, the answer is &#8220;very little&#8221;. Over the last two months, I optimized this [...]]]></description>
			<content:encoded><![CDATA[<p>It is hardly news that the average load time is one of the many factors that Google uses to determine how well your site will rank. But how much does it matter, really? If my recent experience is anything to go by, the answer is &#8220;very little&#8221;.</p>
<p>Over the last two months, I<a href="http://w-shadow.com/blog/2011/01/18/the-quest-for-speed/"> optimized this site</a> to load <strong>almost 2x faster</strong>. After the optimization was complete, the amount of Google search traffic that it receives increased by <strong>a whopping 5 percent</strong>. Here are the specific numbers:</p>
<p><strong>November 2010</strong></p>
<ul>
<li>4.5 seconds.</li>
<li>58 832 visits.</li>
</ul>
<p><strong>January 2011</strong></p>
<ul>
<li>2.2 seconds (-105%).</li>
<li>61 751 visits (+5%).</li>
</ul>
<p>If I wasn&#8217;t deliberately looking for changes in my organic search traffic, I probably wouldn&#8217;t even had noticed! The upswing is so tiny it might as well be a random statistical aberration. In fact, there&#8217;s a good change that is all it is.</p>
<p>Either way, there is some value in this exercise &#8211; it provides an upper bound. If you speed up your site by 100%, you probably won&#8217;t see more than a 5% improvement in your search traffic. Underwhelming, that.</p>
<p>And a couple of charts for you:</p>
<p><em>Site performance history from Google Webmaster Tools</em><br />
<a href="http://1.shadowcdn.com/wp-content/uploads/2011/02/site-performance.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2286" title="Site performance graph from Google Webmaster Tools" src="http://1.shadowcdn.com/wp-content/uploads/2011/02/site-performance-thumb.png" alt="" width="490" height="106" /></a></p>
<p><em>Google Search traffic</em><br />
<a href="http://1.shadowcdn.com/wp-content/uploads/2011/02/google-search-traffic.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2284" title="Google Search visitors (weekly)" src="http://1.shadowcdn.com/wp-content/uploads/2011/02/google-search-traffic-thumb.png" alt="" width="490" height="156" /></a></p>
<p><em>Both charts overlaid</em><br />
<a href="http://1.shadowcdn.com/wp-content/uploads/2011/02/google-search-traffic.png"></a><a href="http://1.shadowcdn.com/wp-content/uploads/2011/02/combo-chart.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2282" title="Site performance vs Google Search visitors" src="http://1.shadowcdn.com/wp-content/uploads/2011/02/combo-chart-thumb.png" alt="" width="490" height="107" /></a></p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A6--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rmU49lCM9X8:aqY3tHOvL5Q:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=rmU49lCM9X8:aqY3tHOvL5Q:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rmU49lCM9X8:aqY3tHOvL5Q:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=rmU49lCM9X8:aqY3tHOvL5Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/rmU49lCM9X8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/02/01/page-load-time-vs-seo-my-experience/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/02/01/page-load-time-vs-seo-my-experience/</feedburner:origLink></item>
		<item>
		<title>Lazy-Load Avatars</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/BJzj_fhdU8Q/</link>
		<comments>http://w-shadow.com/blog/2011/01/31/lazy-load-avatars/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 14:04:24 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[WordPress Plugins]]></category>
		<category><![CDATA[Gravatar]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[WordPress plugins]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2274</guid>
		<description><![CDATA[In my previous post, The Quest For Speed, I mentioned that lazy-loading avatars is a good way to improve your site performance: The overwhelming majority of visitors never leave a comment. Chances are, most don&#8217;t even scroll down to the comments section. So why waste their time and bandwidth by loading avatars that they&#8217;ll never [...]]]></description>
			<content:encoded><![CDATA[<p>In my previous post, <a href="http://w-shadow.com/blog/2011/01/18/the-quest-for-speed/">The Quest For Speed</a>, I mentioned that lazy-loading avatars is a good way to improve your site performance:</p>
<blockquote><p>The overwhelming majority of visitors never leave a comment. Chances are, most don&#8217;t even scroll down to the comments section. So why waste their time and bandwidth by loading avatars that they&#8217;ll never see? A better option is to delay the loading of avatars until the user has scrolled far enough to actually see them.</p></blockquote>
<p>I also promised to post the plugin that would allow you to implement this feature on your own WordPress site. So here it is.</p>
<h3>Download</h3>
<p><a href="http://1.shadowcdn.com/files/lazy-avatars.zip"><strong>lazy-avatars.zip</strong></a> (3 KB)</p>
<h3>Usage</h3>
<ol>
<li>Install and activate the plugin.</li>
<li>Open your comments.php find a line that looks like this:
<pre class="brush: php; title: ; notranslate">&lt;?php wp_list_comments(); ?&gt;</pre>
</li>
<li>Add this line <em>above</em> the wp_list_comments call:
<pre class="brush: php; title: ; notranslate">&lt;?php do_action('enable_lazy_avatars', true); ?&gt;</pre>
</li>
</ol>
<p>This will enable the lazy-load feature for the avatar images in your comments section. If you want to use it <em>everywhere</em> on your site &#8211; e.g. in the sidebar or the admin panel &#8211; you can instead add the line from step #3  to your functions.php file.</p>
<p>The way it works is that the plugin replaces all avatar images with place-holder &lt;div&gt;&#8217;s.  Then it monitors the scrollbar position. When one of the place-holders comes into view, the plugin creates a new &lt;img&gt; tag inside the place-holder &lt;div&gt; and sets its &#8220;src&#8221; attribute to the original avatar URL.</p>
<p>With regards to styling, each place-holder has any CSS classes that the original avatar image had, plus two  more &#8211; &#8220;lazy-avatar&#8221; and &#8220;pending&#8221;. The &#8220;pending&#8221; class is removed once the avatar has been loaded. You can use this to apply a custom style to avatars that haven&#8217;t been loaded yet, e.g. a by adding a spinning &#8220;loading&#8230;&#8221; icon as the background image.</p>
<h3>Compatibility</h3>
<p>The plugin has been tested in the following environments:</p>
<ul>
<li>WordPress 3.0.4 and 3.1-RC2.</li>
<li>Firefox 3.6, Opera 11,  Chrome 9 and Internet Explorer 9.</li>
</ul>
<p>It will probably work fine in older versions of Firefox, Opera, Chrome and possibly Safari (not tested). However, it will <strong>not</strong> work in any version of Internet Explorer older than IE9. This is because old versions of IE don&#8217;t support the <a href="https://developer.mozilla.org/en/DOM/element.addEventListener">addEventListener method</a> and the <a href="https://developer.mozilla.org/en/DOM/window.scrollY">pageYOffset property</a>.</p>
<p>If you&#8217;d like to write your own image lazy-loading script that is fully cross-browser compatible, take a look at jQuery&#8217;s <a href="http://api.jquery.com/scroll/">scroll</a> and <a href="http://api.jquery.com/scrollTop/">scrollTop</a> methods. There&#8217;s also an <a href="http://remysharp.com/2009/01/26/element-in-view-event-plugin/">inView jQuery plugin</a> that could simplify the task even further.</p>
<p>The plugin also uses custom data- attributes to store avatar image URLs. This is, strictly speaking, not a standards-compliant thing to do (<a href="http://ejohn.org/blog/html-5-data-attributes/">except in HTML5</a>), but I&#8217;ve found that it works well enough in practice.</p>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A9--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=BJzj_fhdU8Q:F0MB7e7bRZk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=BJzj_fhdU8Q:F0MB7e7bRZk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=BJzj_fhdU8Q:F0MB7e7bRZk:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=BJzj_fhdU8Q:F0MB7e7bRZk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/BJzj_fhdU8Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/01/31/lazy-load-avatars/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/01/31/lazy-load-avatars/</feedburner:origLink></item>
		<item>
		<title>The Quest For Speed</title>
		<link>http://feedproxy.google.com/~r/wshadowcom/~3/tSUQXJeJ9Eo/</link>
		<comments>http://w-shadow.com/blog/2011/01/18/the-quest-for-speed/#comments</comments>
		<pubDate>Tue, 18 Jan 2011 13:40:31 +0000</pubDate>
		<dc:creator>Jānis Elsts</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WordPress Development]]></category>
		<category><![CDATA[css sprites]]></category>
		<category><![CDATA[lists]]></category>
		<category><![CDATA[page load time]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://w-shadow.com/?p=2252</guid>
		<description><![CDATA[A little more than a month ago, I logged into my Google Webmaster Tools account and to check if Google had detected any crawl errors or any other problems with my site. Finding everything in good order, I was just about to close the browser tab when I noticed a sidebar link that had somehow [...]]]></description>
			<content:encoded><![CDATA[<p>A little more than a month ago, I logged into my Google Webmaster Tools account and to check if Google had detected any crawl errors or any other problems with my site. Finding everything in good order, I was just about to close the browser tab when I noticed a sidebar link that had somehow escaped my attention in the past &#8211; <em>Site performance</em> (it&#8217;s under <em>Labs</em>). I clicked it and was appalled to discover that my site was &#8220;slower than 68% of sites&#8221;.</p>
<p>Naturally, I couldn&#8217;t leave it that way. Optimization problems are among my favourites. So I set out to speed up my site as much as possible, and after a month of off-and-on optimization efforts I managed to get the average load time down from 4.6 seconds to 1.5 seconds. In this post I&#8217;ll summarize all the performance tricks and techniques I used to achieve that. They are loosely ordered from most widely applicable to most narrow/esoteric.</p>
<p>Here&#8217;s how my site performance graph looks now (click to enlarge):</p>
<p><a href="http://1.shadowcdn.com/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph.png"></a><a href="http://1.shadowcdn.com/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph.png"><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2262" title="Site performance graph from Google Webmaster Tools" src="http://1.shadowcdn.com/wp-content/uploads/2011/01/webmaster-tools-site-performance-graph-small.png" alt="Site performance graph from Google Webmaster Tools" width="480" height="229" /></a></p>
<p><em>You will undoubtedly notice that after reaching 1.5 seconds it gradually returns to 2.3. This was a calculated decision on my part, and I&#8217;ll discuss it after at the end of this post.</em></p>
<h3>Combine and compress CSS files</h3>
<p>Technically there is a number of ways to do this automatically. However, I was too lazy to do it &#8220;right&#8221;. Instead, I combined the files by hand and edited my theme&#8217;s header.php to include the combined CSS file instead of the default style sheet.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://aciddrop.com/2009/02/02/php-speedy-wp-052-bug-fix/">PHP Speedy WP</a> &#8211; automatically combine and compress CSS and JS. Warning: doesn&#8217;t play nice with CDNs.</li>
<li><a href="http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/">WP Minify plugin</a> &#8211; like PHP Speedy WP, but more actively maintained and up-to-date.</li>
<li><a href="http://www.halmatferello.com/lab/wp-css/">WP CSS plugin</a> &#8211; gzip and minify CSS, automatically combine @import&#8217;ed files.</li>
<li><a href="http://www.csscompressor.com/">CSS Compressor</a></li>
<li><a href="http://refresh-sf.com/yui/">YUI Compressor</a></li>
<li><a href="http://w-shadow.com/blog/2010/12/14/where-did-that-js-css-come-from/">Where did that CSS/JS come from?</a></li>
</ul>
<h3>Remove unused JavaScript</h3>
<p>There was this one JS file that didn&#8217;t seem to actually <em>do</em> anything. After some investigation, I discovered that WP was including it because I had comment threading turned on. Since my theme doesn&#8217;t actually support comment threading, I simply disabled it in Settings -&gt; Discussion. This got rid of the .js file.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://w-shadow.com/blog/2010/12/14/where-did-that-js-css-come-from/">Where did that CSS/JS come from?</a></li>
<li><a href="http://stackoverflow.com/questions/4136738/find-dead-javascript-code">How to find dead JavaScript code</a></li>
</ul>
<h3>Remove unused selectors</h3>
<p>Small CSS = &nbsp;faster downloads.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://www.sitepoint.com/dustmeselectors/">Dust-Me Selectors</a> &#8211; Firefox Add-on</li>
<li><a href="https://github.com/aanand/deadweight">Deadweight</a> &#8211; Ruby gem.</li>
<li><a href="http://code.google.com/p/css-redundancy-checker/">CSS Redundancy Checker</a></li>
</ul>
<h3>Set far expires headers for static content</h3>
<p>Far-future &#8220;Expires&#8221; headers allow browsers keep static content &#8211; e.g. CSS, JS and images &#8211; in their cache and avoid re-downloading the same files unnecessarily. It&#8217;s as simple as adding a couple of lines to your .htaccess:<br />
# Far-future &quot;Expires&quot; header for static files<br />
&lt;FilesMatch &quot;\.(ico|jpg|jpeg|png|gif|js|css|swf)$&quot;&gt;<br />
ExpiresActive On<br />
ExpiresDefault &quot;access plus 8 weeks&quot;<br />
&lt;/FilesMatch&gt;</p>
<h3>Disable ETags</h3>
<p>Again, just add this to your .htaccess:<br />
# Disable ETags<br />
FileETag none</p>
<h3>Minify the HTML</h3>
<p>Smaller page = faster page. I used the WPSCMin plugin for WP Super Cache to strip redundant whitespace from my pages and re-organize tags for better compressibility.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://lyncd.com/wpscmin/">WPSCMin</a></li>
<li><a href="http://ocaoimh.ie/wp-super-cache/">WP Super Cache</a></li>
<li><a href="http://omninoggin.com/wordpress-plugins/wp-minify-wordpress-plugin/">WP Minify</a></li>
</ul>
<h3>Use CloudFront CDN with origin pull</h3>
<p>On the one hand, using a Content Delivery Network is a huge overkill for a small(ish) site like mine. On the other, it does improve performance for many visitors, and it helps with Reddit-proofing one&#8217;s site. It&#8217;s also ridiculously cheap &#8211; my CloudFront bill for December was around $1.30.</p>
<p>There are two ways to get your files into the CloudFront CDN. You can either upload them to Amazon S3 and give CloudFront the bucket name, or you can set up a &#8220;custom origin&#8221; distribution that makes the CDN automatically pull the required files from your server on an as-needed basis. I went with I went with the second option as the obviously easiest one.</p>
<p>Note, however, that the AWS CloudFront console lacks the ability to create custom origin distributions. You need to use a third-party tool like CloudBerry instead.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://aws.amazon.com/cloudfront/">Amazon CloudFront</a><strong> </strong></li>
<li><a href="http://cloudberrylab.com/">CloudBerry Explorer</a></li>
</ul>
<h3>Enable preload mode in WP-SuperCache</h3>
<p>By default<strong>, </strong>WP-SuperCache caches a post when someone first visits it. So if a post is visited only rarely, it&#8217;s cache entry is likely to expire before someone visits it again, and the next visitor will need to wait for the post to be re-generated. With preload on, WP-SuperCache automatically pre-caches <em>all</em> posts. This ensures that even less popular pages are will have a cached version available and load quickly.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://ocaoimh.ie/preload-cache-wp-super-cache/">Further explanation and discussion of the Preload mode</a></li>
</ul>
<h3>Convert theme images to CSS sprites</h3>
<p>This reduces the number of HTTP requests the browser has to make to render the page. Ideally, there should be only one image that the browser has to load to render all the decorative elements on the page.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://www.alistapart.com/articles/sprites">A tutorial on CSS sprites</a></li>
<li><a href="http://css-sprit.es/">CSS sprite generator</a></li>
<li><a href="http://spriteme.org/">SpriteMe</a> &#8211; a popular choice.</li>
<li><a href="http://www.google.com/search?hl=en&amp;safe=off&amp;client=opera&amp;hs=pVY&amp;rls=en&amp;q=css+sprite+generator&amp;aq=f&amp;aqi=&amp;aql=&amp;oq=">More sprite generators</a></li>
</ul>
<h3>Convert CSS sprites to data: URIs and embed them in the combined CSS file</h3>
<p>And <em>this</em> reduces the number of HTTP requests even further. There are ways of automating data URI generation (see the &#8220;Resources&#8221; section), but I just put my sprites through an online converter and edited the style sheets by hand.</p>
<p>Note that data: URIs don&#8217;t work in IE 7 and IE 6, so be sure to provide a fall-back style sheet specifically for those despicable two.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Data_URI_scheme">data URI scheme</a> on Wikipedia</li>
<li><a href="http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/">Image to data URI converter</a></li>
<li><a href="https://github.com/nzakas/cssembed">CSSEmbed</a> &#8211; a small utility that automates data URI conversion and embedding in CSS files.</li>
</ul>
<h3>Optimize popular content images</h3>
<p>On this site, there are a couple of pages that get a lot more traffic than the rest. &nbsp;By fine-tuning the images used on those pages to load as quickly as possible, I (hopefully) improved the first-visit experience for a significant fraction of this site&#8217;s visitors.</p>
<p>In practice, I uploaded the images to Smush-it, then ran the results through PNGCRUSH. For the trickier ones, I spent an hour or so playing with lossy compression options in Photoshop.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://www.smushit.com/ysmush.it/">Yahoo! Smush-it</a></li>
<li><a href="http://pmt.sourceforge.net/pngcrush/">PNGCRUSH</a></li>
<li><a href="http://optipng.sourceforge.net/">OptiPNG</a></li>
<li><a href="http://www.advsys.net/ken/util/pngout.htm">PNGOUT</a></li>
<li><a href="http://www.punypng.com/">PunyPNG</a></li>
</ul>
<h3>Load AdSense asynchronously</h3>
<p>AdSense ads are loaded <em>synchronously</em>. This means that when the browser encounters an AdSense ad, it will wait until the ad has completely finished downloading before continuing to load the rest of the page. This can slow down your site considerably.</p>
<p>There is, however, <a href="http://iamnoah.github.com/writeCapture/">a hack</a> that lets one load AdSense <em>asynchronously</em> &#8211; in parallel with other content. The details are extremely involved, so I&#8217;ll just give you an implementation example:</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;div id=&quot;adsense_ad&quot; style=&quot;width:336px;height:280px;&quot;&gt; &lt;/div&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;path-to/writeCapture-1.0.5-nolib-min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;&lt;!--
	google_ad_client = &quot;ca-pub-1234567890&quot;;
	google_ad_slot = &quot;987654321&quot;;
	google_ad_width = 336;
	google_ad_height = 280;
	//Async AdSense
	writeCapture.html('#adsense_ad', '&lt;scr'+'ipt type=&quot;text/javascript&quot; src=&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js&quot;&gt;&lt;'+'/script&gt;');
//--&gt;
&lt;/script&gt;
</pre>
<p>Dire warning: While I believe that the AdSense ToS doesn&#8217;t explicitly forbid this technique, I also cannot claim that they allow it. Use at your own risk!</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="https://github.com/iamnoah/writeCapture">writeCapture JS library</a></li>
<li><a href="http://iamnoah.github.com/writeCapture/">writeCapture demo page</a></li>
</ul>
<h3>Remove unnecessary HTML</h3>
<p>Lets face it, WordPress isn&#8217;t exactly thrifty with its markup. For example, it adds a whole slew of META and LINK tags to each page &#8211; a Windows Live Writer manifest, a shortlink, a &#8220;generator&#8221; tag displaying the WordPress version, three different types of feeds, and so on. Each of those tags has a purpose, but in practice only a few will be relevant for your site. You can save a Kb or two by removing the useless ones.</p>
<p>I removed 7(!) useless tags by adding this code to my theme&#8217;s functions.php file:</p>
<pre class="brush: php; title: ; notranslate">
function removeUselessMeta() {
	remove_action('wp_head', 'rsd_link');             //EditURI
	remove_action('wp_head', 'wlwmanifest_link');     //WLW Manifest
	remove_action('wp_head', 'wp_shortlink_wp_head'); //Shortlink

	//My theme already outputs a general feed autodiscovery tag, so no need for more.
	//Also disables comments feed autodiscovery (I doubt anyone really uses it).
	remove_action('wp_head', 'feed_links', 2);
	remove_action('wp_head', 'feed_links_extra', 3);

	//No, don't tell the whole world what version of WP I'm running.
	remove_action('wp_head', 'wp_generator');

	//Disable rel='start' and rel='index' link tags. They make no sense on a site that
	//doesn't contain multi-page/series posts.
	remove_action('wp_head', 'start_post_rel_link');
	remove_action('wp_head', 'index_rel_link');
}
add_action('init', 'removeUselessMeta');
</pre>
<p>You can trim away some more bytes by removing optional tags and optimizing your layout and CSS so that, for example, common class names are not repeated more often than necessary.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://perfectionkills.com/optimizing-html/">Optimizing HTML</a></li>
<li><a href="http://stackoverflow.com/questions/3008593/html-include-or-exclude-optional-closing-tags">List of optional closing tags</a></li>
</ul>
<h3>Cache the FeedBurner counter and convert it to PNG</h3>
<p>A minor optimization to be sure, but it saves one DNS query and the PNG version of the feed counter is about half the size of the original GIF. Here&#8217;s the PHP script I use to create and display the cached image:</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php
//Configuration
$feed_id = 'wshadowcom';
$bg_color = 'B9CFFF';
$fg_color = '330000';
$cache_duration = 3600*12;
$cache_filename = $feed_id . '-cached.png';

if ( !file_exists($cache_filename) || (time() - filemtime($cache_filename) &gt; $cache_duration) ){
	//Retrieve the original badge
	$image_url = sprintf('http://feeds.feedburner.com/~fc/%s?bg=%s&amp;fg=%s&amp;anim=0', $feed_id, $bg_color, $fg_color);
	$image = imagecreatefromgif($image_url);

	//Save as PNG
	imagepng($image, $cache_filename, 9, PNG_NO_FILTER);

	//Cleanup
	imagedestroy($image);
}

//Output the resulting image
header('Content-type: image/png');
header('Content-Length: ' . filesize($cache_filename));
header('Cache-Control: max-age=' . $cache_duration);
readfile($cache_filename);
?&gt;
</pre>
<h3>Lazy-load avatars</h3>
<p>The overwhelming majority of visitors never leave a comment. Chances are, most don&#8217;t even scroll down to the comments section. So why waste their time and bandwidth by loading avatars that they&#8217;ll never see? A better option is to delay the loading of avatars until the user has scrolled far enough to actually see them.</p>
<p>My implementation of this trick is too large to fit on this page, so I will leave it for a future post.</p>
<p><strong>Resources</strong></p>
<ul>
<li><a href="http://www.quirksmode.org/dom/events/scroll.html">scroll and mouse wheel events</a></li>
<li><a href="http://stackoverflow.com/questions/769701/is-there-a-way-to-detect-when-an-html-element-is-hidden-from-view/769728#769728">How to detect when an element scrolls into view</a> &#8211; a starting point.</li>
<li><a href="http://remysharp.com/2009/01/26/element-in-view-event-plugin/">jQuery &#8220;in view&#8221; plugin</a></li>
<li><a href="http://www.javascriptkit.com/javatutors/dom2.shtml">Adding elements to the DOM</a></li>
</ul>
<h3>Disable AdSense (if you can afford it)</h3>
<p>Finally, I disabled my AdSense ads and left them off for several days to test the impact they have on the average page load time. Surprise, surprise: the load time went down almost by a whole second. This is the steep 800 ms dip you saw on the performance graph &#8211; from ~2.3 seconds to ~1.5. The gradual increase back to 2.3 is me deciding that $XX/day from AdSense is worth the performance hit and re-enabling ads.</p>
<p><img style=' display: block; margin-right: auto; margin-left: auto;'  class="aligncenter size-full wp-image-2256" title="AdSense OFF vs AdSense ON performance" src="http://1.shadowcdn.com/wp-content/uploads/2011/01/adsense-off-on-performance.png" alt="" width="250" height="258" /></p>
<p>I must admit I&#8217;m a bit miffed about these results. Consider: a single block of AdSense adds around 800 milliseconds to the page load time. By looking at the graph from Google Webmasters Tools, we can infer that Google sees a site as &#8220;fast&#8221; if it loads in around 1.5 seconds. So if you use AdSense and want your site to meet that speed criteria, <em>everything else</em> on your page must load in 700 milliseconds or less.</p>
<p>You&#8217;d have to do better a job at performance optimization than <em>frickin&#8217; Google </em>did with AdSense.</p>
<h3>Further Considerations</h3>
<p>Here are a few things I considered but didn&#8217;t attempt either because of their tediousness or high costs:</p>
<ul>
<li>Clean up the theme even further. There&#8217;s still a fair bit of redundancy in the markup and CSS.</li>
<li>Get a DNS <a href="http://en.wikipedia.org/wiki/Anycast">anycast</a> provider for my domain name.</li>
<li>Switch from Google Analytics to a something that doesn&#8217;t use JavaScript (e.g. AWStats).</li>
<li>Experiment with different CDNs.</li>
<li>Set up a <a href="http://www.varnish-cache.org/">Varnish cache</a> for WordPress.</li>
<li>Get more points-of-presence around the world. I&#8217;ve noticed that with the current setup &#8211; one server in USA &#8211; the time it takes to download the page HTML alone varies greatly depending on where the client is located.</li>
</ul>
<hr/>Copyright &copy; 2012 <strong><a href="http://w-shadow.com">W-Shadow.com</a></strong>. This Feed is for personal non-commercial use only. If you are not reading this material in your news aggregator, the site you are looking at is guilty of copyright infringement.<!--A43--><!--L0--><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/wshadowcom?a=tSUQXJeJ9Eo:Rk4sOnjQ_k0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/wshadowcom?i=tSUQXJeJ9Eo:Rk4sOnjQ_k0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=tSUQXJeJ9Eo:Rk4sOnjQ_k0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/wshadowcom?a=tSUQXJeJ9Eo:Rk4sOnjQ_k0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/wshadowcom?d=yIl2AUoC8zA" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/wshadowcom/~4/tSUQXJeJ9Eo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://w-shadow.com/blog/2011/01/18/the-quest-for-speed/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		<feedburner:origLink>http://w-shadow.com/blog/2011/01/18/the-quest-for-speed/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 1.363 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-16 17:56:20 -->

