Dynamically updating parts of a cached page with WPSC

boltgolt
4 min readJan 31, 2021

WPSC uses a static cache to serve requests extremely fast, but what if you have content on your site that needs to be customized for each visitor? Using a self-written cache plugin can help you fully customize your cached page before it gets served to the visitor.

In my daily job we build websites for our clients with WordPress as a recognizable and easy to use backend, while our own custom system creates fast and efficient frontend pages. However, this means that WordPress adds some overhead and we like to serve pages as quickly as possible.

With WordPress Super Cache any page can be cached as a pre-rendered HTML page stored on disk. These will be served directly to the visitor without even loading much of the WordPress backend. This also creates a big problem: Because the same page is served to all visitors, every visitor would see the cookie bar, even if they already agreed to cookies before.

By writing our own cache plugin we made WPSC serve different content to every visitor, with only 1ms of a hit to performance. There is very little documentation on how to write one of these plugins, so my hope is that this how-to helps some other developers.

Writing your own cache plugin

I’m going to assume you know how to install and activate WordPress plugins and that you’ve read the unfinished blogpost that is the only developer documentation listed on wordpress.org.

After installing WPSC you should have a file called wp-cache-config.php in your wp-content folder. This is were all cache configuration options live. WPSC can’t store its configuration in the database as that part of WordPress is never loaded.

We’re going to move the cache plugin directory so it is no longer in the WPSC folder. If you do not update this location your plugin will be deleted every time WPSC gets updated. Create a new folder called wp-super-cache-plugins in the plugin directory. Now change the $wp_cache_plugins_dir variable in wp-cache-config.php to the new folder called wp-super-cache-plugins

$wp_cache_plugins_dir = WP_CONTENT_DIR . ‘/plugins/wp-super-cache-plugins’

While we’re in this config file, enable dynamic cache plugins by setting the $wp_cache_mfunc_enabled option to 1.

$wp_cache_mfunc_enabled = 1;

Now it’s time to create the plugin file. Create a new php file in the wp-super-cache-plugins directory with a descriptive name, like testplugin.php

In this file we need to declare our plugin. (well, we don’t really need to do so as the plugin will work perfectly fine without declaring it first, but it is a good place to start) Add the following code to your plugin file:

function wpsc_testplugin_list($list) {
$list[‘testplugin’] = array(
‘key’ => ‘testplugin’,
‘url’ => ‘https://example.com',
‘title’ => ‘Test Plugin’,
‘desc’ => ‘Just a simple test plugin’
);
return $list;
}
add_cacheaction(‘wpsc_filter_list’, ‘wpsc_testplugin_list’);

Notice the add_cacheaction() function on the last line, which functions like add_action() in a normal WordPress script.

Filtering HTML from cache

Now that we have our cache plugin up and running we can start changing the cache data. Hook into the wpsc_cachedata cache action to change the HTML before it is served from the cache:

function wpsc_testplugin_replace($content) {
$content = str_replace('not cached', 'is cached', $content);
return $content;
}
add_cacheaction('wpsc_cachedata', 'wpsc_testplugin_replace');

This function works like a WordPress filter, giving a $content argument to your function which you can modify and then have to return. Test this by adding the string not cached to the HTML of your website, and adding the code above to your cache plugin. The first time you load the page should be slow and display the default “not cached” string, but loading the same page again should be much faster and show the updated string “is cached”.

The first load was generated by WordPress, and the second was served from cache and modified by your plugin. If you want your plugin to always filter the page, even on the first load, you can add the following code:

function wpsc_testplugin_safety() {
return 1;
}
add_cacheaction(‘wpsc_cachedata_safety’, ‘wpsc_testplugin_safety’);

As explained by this 8 year old blog post, this will tell WordPress Super Cache that it’s safe to run the filter function on the content. You could also use this function to disable the filter in certain scenarios.

Filtering HTML before it’s cached

For some scenarios it might also be helpful to be able to change content before it is saved as a HTML cache file to disk. For example, i added a function that automatically compresses the content so smaller cache files are served to visitors.

The totally not confusingly named add_cacheaction cache action can be used for this. The purpose of this action is to be able to safely hook into other actions within WordPress from a cache plugin. In that action we can finally hook into wpsupercache_buffer to catch content before it is saved to cache:

function wpsc_testplugin_filter() {
add_filter(‘wpsupercache_buffer’, ‘wpsc_testplugin_content’);
}
add_cacheaction(‘add_cacheaction’, ‘wpsc_testplugin_filter’);

In short, these 4 lines will cause wpsc_testplugin_content()to be called after a page is rendered but before it is saved. You can use this function as a filter, just like the filter we used before:

function wpsc_testplugin_content($content) {
$content = preg_replace(‘/^\s+/m’, ‘’, $content);
return $content;
}

If you load a fresh page and check your cache files after adding those two hooks you will see that all white space at the start of every line has been removed by this filter.

--

--