Caching WPtouch themes with WP Total Cache

How to make W3 Turbo Cache play more cleverly alongside the WP Touch iPhone interface plugin.

THE COOKIE NAME HAS CHANGED, PLEASE ADD wptouch_switch_toggle INSTEAD

I really like WordPress. I like the interface and the available plug-ins. It’s impressive how much you can do without coding, just configuring things. I use WPTouch to provide an iPhone/mobile devices theme. However, as a PHP application WordPress famously doesn’t scale to being Fireballed, Slashdotted, Dugg when you’re running on a small server. Even if you’re not too worried about being popular, by the time you’ve installed a few plugins, your site might be feeling a bit sluggish.

Like anyone with the naive belief I could write just such a post, but sensible enough to know it’ll too late to fix if I do, I’ve always had a caching plugin installed. Firstly it was WP Supercache, but now I use WP Total Cache (W3TC).

Short of using a caching front-end server such as Varnish (which is my next side project), WP Supercache/WPTC’s “disk (enhanced)” Page-Caching is the fastest way to serve your pages, because it’s done an Apache level. PHP isn’t loaded, databases aren’t queried, static files are served off disk.

W3TC also does JS/CSS minification, compression, and CDN distribution. These also can accelerate your site, but again won’t always work with all the plug-ins that you have installed. I would suggest you start off with basic caching, enable modules selectively, and test many times.

Caching, and things like themes don’t really co-exist that well, especially if you try and share the same URL for one bit of content rather than having the m.mysite.com thing. The normal install guides for WPtouch and caching plug-ins involve preventing page caching for all mobile user-agents. While it works, it’s not the most efficient use of your server, especially given people clicking on links from Twitter clients on mobile devices may prove part of the onslaught.

Rather than preventing all mobile traffic being cached, what you can do instead is request that pages are cached until “wptouch_toggle_cookie” is set. This is the cookie which allows users to jump back to the desktop view of the site on a mobile device. In this way you’re caching the first hit to your site, and all hits until they change theme. That should cover a lot of visitors.

You have two parallel caching silos: The normal site, and the mobile site. You direct to the correct one of these based on user-agent, and when the user manually flips, the cookie is set, and you’re no longer doing page level caching. You still getting the benefit of the Database and Object caching that WP Total Cache does, but it’s much slower. If you are lucky enough to be suddenly very popular, hopefully the vastly reduced load of the majority of users should mean that even non-cached users get the right content, and not a 500 error.

I’m not going to cover installing W3TC because the plugin itself covers this quite well, and other places. If you’re on Debian I’ll flag up that you can install all the additional libraries like APC/memcached for caching, Curl for CDN uploads etc from packages, and avoid compiling anything.

WARNING: this is potentially brittle. If the cookie name changes you will be leaving mobile users stranded in the mobile interface, with a “turn mobile off” button that doesn’t work. That said, if you have any mismatches between user-agents in the variety of lists they can appear, that also can cause problems. Check this all works after you update any of WordPress, WP Touch, WP Total Cache.

How to do it

WARNING: When you edit this group, WP Turbo Cache is editing .htaccess files. It doesn’t not escape them automatically, it’s VERY easy to break your website, including your admin interface… Don’t attempt to do this without file access, access to apache error logs, and ideally SSH access. Backup before you start: Your WordPress files, your wordpress database and also the WPTC config (there’s a download button on the first page).

To enable this hack you’ll have to do two things, one create the user agent group that will get the mobile touch theme.

1) Define the WP Touch User Agent Group

What we’re doing here is defining a list of the agents that should be redirected to the alternative cache pool, that shows the mobile theme.

My current WP Touch plugin claims on the admin interface to support “Android, CUPCAKE, bada, blackberry 9800, blackberry9500, blackberry9520, blackberry9530, blackberry9550, dream, iPhone, iPod, incognito, s8000, webOS, webmate

The list in W3 Total Cache must match what WPTouch expects, if it doesn’t then you could well have mobile served to desktops, and vice versa. The nicest way of doing this would be if your mobile theme was in fact a standalone theme, as W3TC can serve different themes to different User Agent Groups, and you’d only be doing the switch once. This isn’t possible though.

Select “User Agent Groups” from the dropdown in the W3TC admin panel

Copying, pasting and editing from the existing User Agent groups, I created a group with the following. When you save this page, you can easily cause 500 errors on your site, until you manually edit/remove various .htaccess files in your website directory. If this happens you’ll need to read the apache error log to track down the offending files.

android
blackberry9500
blackberry9520
blackberry9530
blackberry9550
blackberry9800
cupcake
dream
incognito
iphone
ipod
samsung\-s8000
webos
webmate

Delete the other groups that WP Total Cache has put in place by default. That keeps the set of mod_rewrite rules used by Apache smaller.

2) Add the cookie exemption

On the Page Cache Settings, add “wptouch_switch_toggle” (which used to be “wptouch_switch_cookie”) to the rejected cookies list.

Save, Deploy & Flush all the caches and test

After you’ve done that, you’re good to go. Apply the config, purge all your caches, then try to access the site on a “clean” desktop browser. Verify that you’re getting the desktop version, and the comments in the source show you’re being page-cached. (compare to a browser where you’re logged in where you should see something about ‘cookie rejected’)

The try on your nearest iPod/iPhone etc. You may will want to install a Javascript source viewer to debug and verify you’re indeed getting a cached copy, then comparing what happens as soon as you turn the mobile version off. You should the desktop site, with the “change to mobile” button. Expect to do a lot of user-agent faking, and cookie clearing to verify you’re really seeing what you should be getting.

Finally, hit reload lots, and if you’re cached, your server shouldn’t really notice and speed should be quite fast.

At this point you’ll also want to ask a few friends just to see what they are seeing on the site, just to check for consistency.

a new look and a (partial) admission of defeat

While it’s tempting to try and do everything myself, using the work of others makes more sense.

For years I’ve been talking about my new theme. It was going to be lovely, it was going to use things like JQuery and BlueTrip. It was going to show my technical credentials as understanding HTML, Progressive Uplift & all that good stuff. It was going to pull in data-feeds from around the web.

In short, it was going to be a most awesome theme.

It’s just a shame then that I’m not proficient enough to do this. Much like doing the revision timetable instead of revising, I’d think about Version Control, and editors, and local development instances. I was great at the meta-work, less good at phasing development and the design work.

Eventually, I probably could just about knock something together, and it’d work in Safari on the Mac. It might work in some versions of Firefox, and IE. But it would always be a bit hit and miss for compatibility, and I’d always be playing catch-up to new features in WordPress.

So instead I used the new TwentyTen, the new WordPress 3.0 theme. It’s nice, compatible and configurable. And I have more time to write actual posts, instead of spending endless time deciding on the <div> structure.

I still have ideas on clever data feeds though, but they can wait.