In this article: Steps I took to optimize a WordPress-based site for Google’s upcoming mobile search prioritization. It started with a PageSpeed Insights score of 8/100 and ended at 62/100.
Plugins used: W3 Total Cache
Time spent: Several hours of trial and error, but this guide should help you through it much quicker.
Google announced in January that they’re going to take a site’s mobile speed into account for searches beginning July 2018. I’ve always tried to make my WordPress sites mobile-friendly, but it looks like there’s some room for improvement.
One of my biggest (and highest-earning) sites scored just an 8 out of 100 for mobile optimization. Ouch.
(You can test your own site here: https://developers.google.com/speed/pagespeed/insights/ )
What I’ve already done to optimize this WordPress site
I’ve managed this site for a few years and have already put some effort into optimizing it for search and mobile.
The site already scores well for these categories:
- Avoid landing page redirects
- Enable compression
- Minify CSS
- Minify HTML
- Minify JavaScript
- Optimize images
- Prioritize visible content
Some of those scores are probably due to the site already using a CDN, lazy loading, a good caching plugin, and a good hosting plan. Here’s what the site uses:
- MaxCDN for delivering its images
- Lazy loading (via this WordPress plugin)
- W3 Total Cache (my favorite WordPress caching plugin)
- Mesmerize, a mobile friendly theme
- SiteGround hosting (“GoGeek” tier)
However, there’s more work to be done! Here’s what I did to raise my Google Insights mobile score.
Fixing render-blocking JavaScript on above-the-fold content on a WordPress site using W3 Total Cache and a CDN
Let’s look at this render-blocking JS/CSS problem first:
Eliminate render-blocking JavaScript and CSS in above-the-fold content. Your page has 8 blocking script resources and 12 blocking CSS resources. This causes a delay in rendering your page. None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronosly load blocking resources, or inline the critical portions of those resources directly in the HTML.
This message is followed by a list of all the JS and CSS scripts causing the render blocking, which were 8 JavaScript files and 3 CSS files in my site’s case.
These guides were helpful to me while working on this problem:
- How to eliminate render-blocking JavaScript and CSS on WordPress
- How to fix render-blocking JavaScript in Google PageSpeed with W3 Total Cache
- The Ultimate Guide to W3 Total Cache: All Your Questions Answered (particularly the part about fixing the flash of unstyled content and the part about accepting that some files will be render-blocking)
To fix the blocking JavaScript files I had to do a number of things to configure W3 Total Cache. This part took a couple hours of trial and error and some steps were not covered in the guides I used (or my situation was different from theirs), so I’ve attempted to document the process as I experienced it in this guide.
First, I enabled Minify in the general W3 Total Cache settings. Go to Performance > General Settings > Minify > check the “Enable” box and select the “Manual” radio button.
Next, go to Performance > Minify to work on minify settings as they pertain to JavaScript and CSS. You’ll need the list of blocking files from PageSpeed Insights report.
Watch out! The file paths shown in the PageSpeed Insights results might be truncated. To get the full path, you have to hover over the truncated path and copy the path from the tool tip.
In other words, make sure you are copying a complete path:
https://your-cdn.netdna-ssl.com/wp-includes/js/jquery/jquery.js?ver=1.12.4
and not a path with … in it:
https://your-cdn.netdna-ssl.com/…-includes/js/jquery/jquery.js?ver=1.12.4
In Performance > Minify there are a variety of options that apply to all the script in a particular area (before head, after body begins, before end of body). In my case, code in the head tag was already minified, so I set it to “Combine only” (rather than re-minify it). I also needed to keep it blocking, or else my page filled Chrome’s console with “can’t find JQuery!” errors.
Next, under JS file management, add all of the blocking files from the PageSpeed Insights results – be sure to get the full file path, not the truncated version.
Also! If you’re using a CDN, you’ll have to change the domain in the file paths that you paste.
Instead of this:
https://your-cdn.com/wp-includes/etc
You need to use your website’s actual domain. For each path you paste, change the CDN part to be your site’s domain instead, like this:
https://yourwebsitesrealdomain.com/wp-includes/etc
Or you can remove that part of the url entirely and go with something like:
/wp-includes/etc
…which is what I did for mine:
Note: I needed to set the jquery files to embed in <head> to avoid a slew of console errors when visiting the site. As per the earlier settings, anything embedded in head is going to be blocking. I think some blocking files might be inevitable; the point of these settings is to tease out which files belong where in the load sequence.
Save settings and purge all caches, then test again in PageSpeed Insights.
Woohoo – no JS files blocking loading. I also tested the site manually, and verified that it doesn’t look like garbage and doesn’t fill the console with errors. So far, so good.
Fixing render-blocking CSS with Autoptimize
I initially set up all the CSS file paths in W3 Total Cache but ran into these two cases that I couldn’t figure out how deal with through W3 Total Cache alone:
One blocking css file is from w3tc itself:
https://mywebsite.com/?w3tc_minify=6951f.default.include.89e358.css
And another is from Google Fonts:
https://fonts.googleapis.com/css?family=Open+Sans%3A300%2C400%2C600%2C700%7CMuli%3A300%2C300italic%2C400%2C400italic%2C600%2C600italic%2C700%2C700italic%2C900%2C900italic%7CPlayfair+Display%3A400%2C400italic%2C700%2C700italic&subset=latin%2Clatin-ext
To fix the Google Fonts, I installed the very lightweight plugin Autoptimize and checked these boxes:
I also used Autoptimize to disable Google Fonts. Whether you want to do this is up to you, but I went ahead with it because I am happy with a default system font for this site.
To fix the w3tc minify, I disabled CSS in W3TC and let Autoptimize handle it. I also had to uncheck this setting:
Finally, for the sake of completeness, here’s what my HTML minify settings look like:
At this point, I loaded my site and found it was using serif typefaces on buttons and it wasn’t scaling the hero (header) image correctly. To fix this, I added custom CSS to Autoptimize’s custom CSS section. This CSS gets loaded right away, so the page doesn’t get stuck waiting on the js or css to “fix” certain issues that are visible right away to a visitor.
.button { font-family: "Open Sans", sans-serif !important; } .header-homepage { padding-top: 120px !important; }
One more thing: I also uploaded a significantly more compressed “hero” banner image jpg to the site (old size: about 350kb, new size: about 110kb).
The reward for all these optimizations:
Note that I still have one render-blocking w3tc js file. For now, I’m going to call this “good enough”, since I don’t know how to fix this last one without breaking some fundamental aspect of the site, so I’m going to move onto the expiry problems and see if I can get the score higher that way.
Fixing “leverage browser caching” with W3 Total Cache
PageSpeed Insights found a few files it thinks could leverage browser caching. These files are all .js files.
I found this guide helpful and accurate at the time of this writing: Leverage Browser Caching with W3 Total Cache
The first step is to enable browser caching in W3 Total Cache’s settings. Go to Performance > General Settings and make sure Browser Cache is enabled.
Then, go to the actual Browser Cache section of the plugin. As per the guide, I ensured these boxes were checked:
- Set expires header
- Set cache control header
- Set entity tag (eTag)
- Set W3 Total Cache Header – this one was not already checked for me
- Enable HTTP (gzip) compression
(I re-ran the PageSpeed Insights test at this time just in case that one checkbox was all it took. Alas, there was no change in the results.)
The next thing I did was scroll down a little bit to the CSS & JS section. My “expires header lifetime” was set to 172800, which is way less than the recommended 604800 (2 weeks) the guide recommends. I saved that change, cleared cache, and ran the test again.
Now I have just three files with unsuitable caching times:
Alas, two of the remaining files are out of my hands: they are Google Analytics’s own .js files. After reading this guide to browser caching Google Analytics, I decided not to try to cache the analytics js file myself. Doing so would require manually updating it periodically. Even the guide’s author says they don’t recommend this method. That’s fine by me.
But how about this emoji js file? I don’t use emojis on my site, so I wouldn’t mind removing them and reaping a small page speed boost.
Normally, removing them is as simple as adding these two lines in your site’s functions.php:
remove_action( 'wp_head', 'print_emoji_detection_script', 7 ); remove_action( 'wp_print_styles', 'print_emoji_styles' );
But I’m using a pro theme that gets automatic updates (which will clobber this code if I add it to functions.php), and I don’t want to make a child theme for the express purpose of removing emojis.
So, I did what any good WP user does and installed yet another plugin: Disable Emojis. (Yes, I also canceled Christmas and summer break while I was heartlessly removing emojis from my very srs blog.)
I ran PageSpeed Insights again and….
Woohoo! (It initially came out worse, but network latency has some affect on the score, too. I tried again and got a 62/100).
My report has never looked better:
PSI estimates this page requires 2 render-blocking round trips and ~26 resources (0.4MB) to load. The median page requires 4 render-blocking round trips and ~75 resources (1MB) to load. Fewer round trips and bytes results in faster pages.
Fixing the “flash of unstyled content”
A new problem has been introduced by all this work: now my page looks unstyled for half a second or so while it’s loading.
I used this tool: Critical Path CSS to identify a the “minimum” CSS needed to make the “above the fold” content look good (it’s a huge block, I’m sure a human could produce something more elegant but for now, it’ll do).
I put this CSS into Autoptimize’s “above the fold” CSS section and the flash of unstyled content seems to look better now, though I still see the fonts looking bad before the preferred “open sans” style comes into effect.
Done… for now
At this point, I’ve gotta call it good enough for now. My site’s score went from 8/100 to about 62/100. I still have a one blocking JS file that I don’t know what to do with and two files from Google Analytics with unsuitable cache expiration times.
I’ll update this page when I make further improvements to the site.