February 28, 2013

Varnish ESI, WordPress and Custom Header Images

I’ve been working on a school website where they want the main focus to be their recent prospectus photo shoot. We discussed various ideas and settled on random loading images on each page load, provided by WordPress’ built in custom header function. One problem with this is the fact that we cache as much dynamic content as possible with Varnish. I had read about edge side includes (ESI) previously, Varnish supports the esi:include function. It involves adding the following to the vcl_fetch subroutine in your Varnish VCL file:

sub vcl_fetch {
  set beresp.do_esi = true;
  if (req.url ~ "header-esi.php"){
    std.log("ESI found, don't cache, pass to nginx");
    set client.identity = clusternginx;

As you see there, we’ve activated ESI with line 3 and then asked it not to cache the file we’re going to create and call later on.

This post presumes you’re already using custom header images, if not you need to activate it in your functions.php – http://codex.wordpress.org/Custom_Headers.

Next we need to create the file that we want to call with the include statement. I’m a poor programmer, but I know a small amount of jQuery and WordPress based PHP. I chose to set the background that I needed in a jQuery Doc Ready statement as follows:

<!--?php require_once('/var/www/wordpress/wp-load.php'); ?-->// <![CDATA[
  jQuery(document).ready(function() {
    jQuery('header.top-head').css('background-image', 'url()');
// ]]>

Remember to include the wp-load.php file or the header_image(); function won’t work.

Now we need to include the file using ESI in our header.php:

As it’s JS I put it in the head, it will most likely work in the footer also if you prefer to put it there. The esi:include src location is relative to your hostname, e.g. http://blog.ed.gs/anything/after/the/domain/name.php.

There’s probably a much better way to accomplish this, but it’s working great for me. I now have random images loading with the rest of the page cached, see it in action at http://hortongrange.edusite.co.uk/.

Update – Quick Note: If you return(pipe) for logged in users, the esi:include will not work. You have to return(pass) so it hits the vcl_fetch subroutine or the include will never get caught by Varnish. I got around the problem for us by including the background-image: url(< ?php header_image(); ?>); in my element, then the jQuery will overwrite it on a cached page for non-logged in users.

Leave a Reply

Your email address will not be published. Required fields are marked *