Currently, in the w3tc plugin, we can create user agent groups by specifying agent names, e.g. android or iphone. By using this function, we can create different caches for different sets of devices.
On my blogs, I need to create different caches based on screen width. This is because I serve up different widgets, ads, images, and galleries, based on device screen width. For a site to be truly responsive, we want to alter not just the layout of the site, but also some of its content (i.e. page html).
If we generate different HTML based on screen width, we would necessarily also need to create different cache groups based on screen width.
Group User Agents by Screen Width
One very simple way to do this, would be to create user agent groups based on screen width. For example, we may have a 480 pixel width group where we list all popular devices with the proper screen width. We may create another group for 320 pixels, another for 768 pixels and so on.
There are two big problems with this approach –
1. Unspecified devices may corrupt our main cache.
Unspecified devices (i.e. devices not listed in a user agent group) will end up using the main cache. In this way, a small, unspecified mobile device may cause a page with smaller ads and galleries to get cached.
When this page gets accessed by a larger device or desktop computer, it would not be showing optimal content based on the larger screen width.
It is possible to dump less popular devices in the Rejected User Agents group, which means that pages don’t get cached for those devices. However, it is simply not possible to have a comprehensive list of devices. I.e., while we may be able to lessen the occurrence of this issue, we will not be able to fully prevent it.
2. We need to keep updating our user agent groups with new devices.
Dynamic User Agent Groups
To properly cache pages based on device width, we want to create dynamic user agent groups based on screen width.
NOTE – This is an advanced tutorial. Only make these modifications if you understand what the code does, are familiar with PHP, and know how to restore plugins back to their original state. Do not just copy and paste.
To do this, we need to –
- Upload and open the file /w3-total-cache/lib/W3/CacheCase.php (in our w3tc plugin folder).
- Find the get_group function. This is the function that returns the proper user agent group name.
- To create our own dynamic user agent groups, we need to insert our own dynamic group operations at the beginning of this function.
For example, I load my own group caching file at the beginning of the get_group function.
public function get_group() { static $group = null; if (($group === null) && (get_class($this) == 'W3_Mobile')) { $group = my_shiba_get_group($group); } .....
In general, it is best not to edit core plugin files. However, I have not found a better solution. Please let me know if you do.
Next, we create the my_shiba_get_group function, which returns a group name based on device screen width. This function needs to be accessible from the get_group function, so a simple solution would be to also include my_shiba_get_group in the CacheCase.php file. However, for better separation and maintainability, we may want to put everything in a separate file, and then just load the file from the get_group function.
function my_shiba_get_group($group) { if (!isset($_COOKIE['shiba_screen_w'])) return 'shiba_600'; $w = $_COOKIE['shiba_screen_w']; if ($w >= 600) { return 'shiba_600'; } elseif ($w >= 540) { return 'shiba_540'; } elseif ($w >= 480) { return 'shiba_480'; } elseif ($w >= 400) { return 'shiba_400'; } elseif ($w >= 320) { return 'shiba_320'; } elseif ($w >= 240) { return 'shiba_240'; } else { return 'shiba_600'; } }
In the code above, we assume that the device screen width is stored as a cookie, with id ‘shiba_screen_w’. This is the code that I use to retrieve screen width. I use it together with the cookies.js file by Ryan Parman.
add_action( 'wp_head', array($this, 'get_screen_res'), 11); function get_screen_res() { ?> <script type="text/javascript"> /* <![CDATA[ */ var w = screen.width; var c = new cookie('shiba_screen_w', w, 365); if (c.read() != w) { c.set(); if (document.cookie.indexOf("shiba_screen_w")!=-1) { location.reload(); } } /* ]]> */ </script> }
When a page is loaded, the javascript above runs on the client device and stores its screen width in a cookie, which then gets passed to our server. The screen width code can be added to our theme or a plugin, i.e. it need not be added to the w3tc plugin code.
Return Proper User Agent Groups
We also need to create each of our dynamic groups in the Performance >> User Agent Groups screen. I create mine with a single dummy user agent value, e.g. device600, device540, etc.
These will register our dynamic groups with the w3tc plugin so that caches get updated and flushed properly.
Add Our Dynamic Groups into .htaccess
Finally, the coolest part is that since we are assigning dynamic groups based on cookies, we can also add our dynamic group rules into our .htaccess file to further speed up page load time.
I add my rules below the RewriteBase statement in the “# BEGIN W3TC Page Cache core” section. For example –
# BEGIN W3TC Page Cache core <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{HTTP_COOKIE} shiba_screen_w=([^;]+) RewriteCond %1 >600 [OR] RewriteCond %1 =600 RewriteRule .* - [E=W3TC_UA:_shiba_600]
Mario says
Very interisting solution. I’m currently using the ‘high’ profile of W3 Total Cache. but the reality is that I would prefer to have 3 different sizes, the same sizes which I’m actually using in my media-queries in .css file. If you find a better solution without modifying core files, please let me know.