How to Reach a PageSpeed of 100
Welcome to part two of our series on Google PageSpeed. In the first episode, I optimized the PageSpeed of my site’s then theme, MySiteMyWay’s Construct. I managed to get to 70 Mobile and 86 Desktop.
However, with MySite’s closure, I chose a new theme and reached a 100 PageSpeed for Mobile and Desktop. It took me about 12 hours of extra effort to accomplish this. Now, my site’s performance is one of the fastest WordPress sites I’ve seen in a long time—check it out. Browsing’s almost instantaneous.
In this tutorial, I’ll walk you through how I accomplished this and what I learned about WordPress and Google PageSpeed. For much of the day I worked on it, I thought I might top out in the 90s. I was surprised a bit when it jumped suddenly to 100 for Desktop—and there were just a few details left to maximize Mobile.
For those that don’t know, Google PageSpeed is a free tool that assesses the performance and usability of your website for mobile and desktop platforms. It’s extra important because Google uses it in determining key elements of our SEO ranking, i.e. how high we appear in their search results.
If you want more background about the benefits of increased site speed, read Moz’s Why Site Speed Optimisation Should Be Part of Your SEO Strategy. It highlights, “…several case studies have shown faster loading pages strongly correlate to higher revenue.”
Google and WordPress Don’t Make This Easy
Ultimately, optimizing my PageSpeed took a lot of time and effort and left my site vulnerable to future plugin and Google script updates. A lot of this work is quite confounding, detail-oriented and time-consuming. It’s also a bit crazy-making and mind-numbing. Thanks, Google.
A static site usually has one file with CSS and JS includes that can be easily minified and combined. WordPress is a lot more complex. So much is created dynamically through WordPress’s—ahem—less than perfect architecture.
Image credit: My photo from Picasso Museo in Paris. Could now be called “Sad Developer Confronting PageSpeed of Mobile 55 / Desktop 62”
That said, let me encourage you by showing how I did it (you don’t have anything useful to do today, do you?). Keep in mind, your site’s needs may differ from mine a bit.
Before we get started, please remember, I do try to participate in the discussions below. If you have a question or topic suggestion, please post a comment below or contact me on Twitter @reifman. I’m interested in your experience with WordPress and PageSpeed.
The Foundational Steps to PageSpeed 100
Selecting a New Theme
If you’re in the market for a new WordPress theme and want to evaluate PageSpeed, you may be surprised that the scores for well-known themes often run in the 60s and 70s but also up to the 90s. Here are a couple of articles assessing themes and PageSpeed via ColorLib and WPMU. In any case, I expected higher.
Just as an example of industry expectations, The New York Times website scores 53/55 for me, far below 100.
Array Themes Medium
The first was its baseline speed. Medium scores Mobile 74 and Desktop 89 to start from their demo server. While this was already slightly better than I had maximized Construct to, it was a more modern theme and there were a lot of remaining optimization steps I could try. I hoped to bring PageSpeed into the high 80s or low 90s.
Also, given the growth of mobile readership, I wanted to move away from relying on sidebars—especially for advertising placement (I hope to write about my new revenue directions in our ongoing Google DFP series). The Medium theme does a good job of folding the left sidebar into a responsive menu and concealing its right sidebar.
Medium’s Initial PageSpeeds
Here was the initial PageSpeed for the demo of Medium (demo hosting is never tightly optimized). It was actually encouraging to see it had lots of unaddressed issues because it showed that it was better than my optimized Construct before extra effort was applied and similar tasks I knew to perform to maximize its score:
Here are more of the issues:
And the user experience challenges, which were more localized:
Finally, here is its demo Desktop score:
Encouraged by the foundation score, I purchased and installed the Medium theme on my server and got to work.
Keep in mind that changing themes can be quite complicated. For me, replacing, eliminating and updating built-in shortcodes from the Construct theme took the most time, and I’m not fully done, e.g. dropcaps, pullquote variations, buttons, tabs and page-based navigation menus. My drive for 100 pushed me to trudge ahead regardless. How to Perform Mass Search and Replace in WordPress offers some good solutions for finding and replacing shortcodes.
While this tutorial won’t guide you through exact steps for raising your site’s PageSpeed to 100, it will guide you through a lot of the possible solutions and identify common roadblocks. There’s another great generalized resource I’ll share at the end.
Cornerstones of Performance in WordPress
I did contact ArrayThemes a bit about the sub-100 demo performance of the Medium theme. They sent an excellent response:
The PageSpeed optimization test should be taken with a grain of salt … our demo is being dinged for not caching, but we don’t actually need caching on our demos … PageSpeed suggestions aren’t entirely accurate or exemplary of the performance of a theme. It will depend entirely on your setup, server, caching and other optimizations you decide to make.
This makes a perfect launching point to reviewing the common foundational elements for WordPress performance. All of the areas of performance below address underlying PageSpeed scores, not completely but the basics.
WordPress caching is critical for performance, and I’ve regularly written about my favorites: W3TC and Varnish Cache, e.g. Optimizing WordPress with Varnish and W3 Total Cache.
It turns out that there are a handful of plugins designed to help you take on the challenge of efficient caching. Here are two of the best that I tried:
- Dependency Minification: Automatically concatenates and minifies any scripts and stylesheets enqueued using the standard dependency system.
Image credit: WordPress Tavern
Both were helpful, but neither quite removed barriers for me related to PageSpeed, such as embedding CSS within my
<head> tag to remove PageSpeed problems; in other words, this plugin won’t likely get you all the way to 100 PageSpeed. I found Dependency Minification to be efficient and helpful, but its lack of flexibility made me walk away.
Ultimately, I would repeatedly return to W3 Total Cache and find new more powerful ways to press it for performance. It’s not perfect and definitely has some UX bugs, it worked well in enough ways for me to find my path with other approaches to PageSpeed 100.
In the end, I chose only one new plugin which made it easy to remove PageSpeed problems with Disqus—I’ll review this further below.
Content Delivery Networks (CDN)
Another service that’s critical is a content delivery network. Earlier I wrote about Accelerate Your Content Delivery With KeyCDN at Envato Tuts+ and then decided to switch to them as a customer.
Recently, I began experimenting with KeyCDN’s new Optimus image optimization service and WordPress plugin. There’s a small possibility it’s run by robots built with old Apple Lisas and Macs:
It works well, but another popular alternative is WP-Smush, an older plugin with more than 300,000 users.
Eliminating Render Blocking
If you have a large variety of files that need to be loaded to style (CSS) and activate (JS) the functionality of your web page, most browsers will slow down after four resources are requested in parallel.
Here’s an example of the CSS render blocking complaint in PageSpeed:
This can be a hard WordPress item to eliminate due to the theme and plugin architecture. We’ll come back to it.
What Steps Ultimately Pushed My Site to 100?
Targeted Optimization Approaches
If you’ve done all the major basics above, improving your PageSpeed with WordPress turns out to require significant effort and can be quite time-consuming.
Let’s go step by step through the identified problem areas and the ways I solved them. In truth, I did a vast amount of experimenting with different tools and approaches. I regularly dropped one approach and returned to another. My solution turned out to be a fairly well-managed patchwork of solutions. The path was not direct Yoda.
For example, here’s how you minimize HTML within W3 Total Cache:
<head> but instead just before
Minimizing Combined CSS From Themes and Plugins
In order to block plugins from loading their own CSS and instruct W3TC to load compressed and combined versions, you need to find the plugin’s handle for the CSS file (distinct from filenames) and add code to your theme to interrupt the plugin loading instructions. Then, enter the path to each CSS file within the W3TC dialog box above to be loaded with the others.
Blogger Justin Tadlock offered some guidance explaining how to ask WordPress not to load the CSS files that my plugins had enqueued for loading. The answer is to deregister them and then load a combined file on your own.
Here’s my Table of Contents plugin enqueuing its JS and CSS files:
Following Tadlock’s suggestion, I deregistered my plugin includes in my theme’s functions.php, starting with the CSS—you have to find the references used by the plugin developer:
add_action( 'wp_print_styles', 'my_deregister_styles', 100 ); function my_deregister_styles() wp_deregister_style( 'toc-screen' );
I manually created a combined CSS files with those three plugin stylesheets. Then, I asked W3TC to minify and combine that file into its own mega-stylesheet as shown above.
Optimizing CSS Loading for PageSpeed
W3TC may combine all my theme and plugin files, but PageSpeed still doesn’t like seeing even one CSS include (so much for good HTML development practices):
I ultimately loaded nine CSS files (only seven shown below). Firstly, you have to find plugin handles for CSS and deregister them in your theme as described above. Then, you have to point them all to W3TC.
While there are several ways to get a minified version of all of these, I actually just grabbed W3TC’s compressed file. I removed all of the caching query arguments, e.g.
?cbe3w2, with search and replace in TextEditor. I’m still a loyal TextMate user, but it actually had huge delays and hangs whenever I tried to navigate a minified CSS file. So TextEditor helped me edit these files individually. Apologies to purists, I haven’t moved on to Sublime yet.
While it worked for me to paste my minified CSS into my header, I later needed to change it to dynamically get the contents of CSS files and echo them into place.
<![endif]--> <style type="text/css"> <?php $css = file_get_contents('/mypathtowp/wp-content/themes/medium/includes/styles/combined.min.css'); $css2=file_get_contents('/mypathtowp/wp-content/themes/medium/includes/styles/osd-social.css'); echo $css.$css2; ?> </style> <!-- add js class -->
Once I added another plugin for social sharing, pasting no longer worked and I had to separate the files with the above mechanism. This also provides more flexibility for the future. Google PageSpeed never sees this, and my Varnish cache conceals any slowdown of including two files.
Ultimately, I configured all of my CSS files in W3TC, made copies of the compressed files, and then turned off this include feature:
One shortcoming of W3TC is that it repeatedly shows annoying error messages even though you are deliberately using it in an unusual way.
When moving CSS files out of plugin directories, make sure you set correct relative paths to images and so on for operating from the site’s root directory. I had a lot of situations where images wouldn’t load until I found where to resolve these things. I’ll share an example in the Troubleshooting section below.
Caching External Scripts in the Browser
This turned out to be quite a big obstacle and requires a lot of time and complexity to fully resolve these issues.
Removing Flickr Embed Problems
First, I had recently returned from a trip to India and put individual blog posts with Flickr-embedded photos on the home page. My Medium theme quickly scrolls through a number of posts, so PageSpeed complained about all of them.
This is a good example of how trying to use a powerful third-party service with the simple purpose of embedding photos kills your PageSpeed score. Flickr hasn’t done an optimal job of helping WordPress users solve this. Just as an example, they would need to:
- offer embedded sizes that keep PageSpeed’s image optimization happy (possibly as separate export options compromised for your PageSpeed—Flickr’s about image quality)
With my remaining Google files, the best solution was to locally host a copy of scripts for Analytics and DFP and use cron scripts to regularly update them on a server.
First, I stopped using my Google Analytics plugin and manually added modified code to my theme’s header:
Notice I changed the paths to my local copies of the scripts. Then, I made local copies of the scripts for Google Analytics and Google DFP, and shortly after my browser caching was resolved in PageSpeed except for Disqus.
Solving the Disqus Plugin Loading Problem
I’m not sure exactly whether it’s for security or multi-platform support or pure “cleverness”, but Disqus and other providers like Flickr seem to obscure the actual files they are loading with other files. This makes optimizing PageSpeed much more difficult and often unsolvable.
Admittedly, I spent two to three hours trying different approaches to optimize the Disqus plugin—nothing worked for me.
Ultimately, I uninstalled the Disqus plugin and installed Disqus Conditional Load:
While it’s meant to do a lot of things, it also makes it possible to optimize PageSpeed with installation.
Suddenly, PageSpeed’s Leverage Browser Caching demerits were gone. Kudos to DCL!
Fixing the Tap Targets
PageSpeed often complains about links too closely spaced in mobile devices. I experimented with a few approaches and ultimately just stopped displaying tags on mobile devices.
If I spend more time, I can probably improve their UX and pass with PageSpeed.
<?php if( is_page() ) else ?> <ul class="meta"> <li ><span><?php _e( 'Category: ', 'medium' ); ?></span><span><?php the_category( ', ' ); ?></span><br /></li> <?php if (!wp_is_mobile()) ?> <!-- not mobile --> <?php $posttags = get_the_tags(); if ( $posttags ) ?> <li><span><?php _e( 'Tag: ', 'medium' ); ?></span> <?php the_tags( '', ', ', '' ); ?></li> <?php ?> <?php ?> <!-- end not mobile --> <?php if( is_single() ) ?> <li><?php previous_post_link( '%link', __( '<strong>Previous Post: </strong>', 'medium' ) . '%title' ); ?></li> <li><?php next_post_link( '%link', __( '<strong>Next Post: </strong>', 'medium' ) . '%title' ); ?></li> <?php ?> </ul> <?php ?>
Missing Images From Compressed and Combined CSS
The ArrayToolkit Plugin, which displays follow icons in the right sidebar, stopped working for me. It took me a while to sort out which paths needed to be coded with absolute paths to make it work.
Ultimately, I found and replaced these paths with corrected relative paths to the original plugin directory:
// Had to put path in plugin css @font-face font-family: 'array'; src: url('./fontello/array.eot'); src: url('./fontello/array.eot#iefix') format('embedded-opentype'), url('./fontello/array.woff') format('woff'), url('./fontello/array.ttf') format('truetype'), url('./fontello/array.svg#array') format('svg'); font-weight: normal; font-style: normal;
I still have one problem I need to resolve. My new tabs plugin (Construct had built-in tabs) stopped working along the way. I just need to spend time debugging it, but it should be fairly easy to sort out.
Choosing the Best Minifier
If you’re interested in figuring out what I did wrong, you can install Java and YUICompressor like this:
#good luck sudo apt-get install openjdk-6-jre cd /usr/local/lib sudo wget https://github.com/yui/yuicompressor/releases/download/v2.4.8/yuicompressor-2.4.8.jar
Please post in the comments if you know how to make it play well with WordPress.
After this second round of work on the new theme, everything worked out better than I’d hoped. I was never sure I’d reach my optimal goal.
My Final PageSpeed Scores
I scored 100 PageSpeed for both Mobile and Desktop. Even more noticeably, my site was running super-fast—faster than I’ve ever had a blog run before. I’m very curious to see how inbound search traffic and readership activity reacts to the faster scores and performance over the next few months.
Here are my final PageSpeed scores, first Mobile:
And now Desktop:
Desktop reached 100 first, and I had to go back and finish some adjustments (addressing tap targets) to get Mobile there.
And again, the speed of the site makes it worth a quick visit. If you know of other commercial websites running at 100 PageSpeed, please share them in the comments. I’d enjoy seeing them.
Just as one example of SEO changes, my popular essay on dating jumped to third ranked on mobile results under “Seattle dating” (not on desktop yet.) This tells me that perhaps stories on major sites beating it have poor mobile PageSpeeds, because it’s not easy.
To maximize my site’s PageSpeed, I had to make a number of adjustments to my theme, which will now create dependencies on changes to external scripts and updates to the theme and plugins. Now that I’m done with my short-term goal, I have work to do to organize my systems to more easily manage this.
Cron for External Files
Soon I’ll need to go implement that cron script to synchronize my self-hosted Google scripts for Analytics and DFP.
Here’s a company that provides a simpler approach to using Analytics without PageSpeed being penalized, fixing the last point on Google PageSpeed Insights. I’d rather not rely on other third parties.
Managing Theme Updates
Managing Plugin Updates
Similarly, when plugins update, I’ll need to watch for the same kinds of updates. It may help me to better organize my use of GitHub with WordPress plugins. I already use it for my theme.
Finally, one of my surprises is that SSL is not required to achieve a PageSpeed of 100. This somewhat makes sense but highlights that a variety of different components may affect your Google search ranking. I’ll be writing about implementing Let’s Encrypt’s free SSL with WordPress soon.
If you’ve enjoyed this but want to read a more general tutorial that doesn’t go as deeply into specifics that may or may not apply to you, KeyCDN’s Google PageSpeed Scoring 100/100 with WordPress is an excellent complementary piece. I’ve also written a sponsored piece about their CDN at Envato Tuts+ (Accelerate Your Content Delivery With KeyCDN) and went on to continue with them as a customer.
In the future, I’ll be looking at a few more enhancements to improve my site’s overall performance. These include:
- Review the individual PageSpeed of my most popular posts such as Amazon Marketplace Fraud Made Easy (currently 97), to ensure they are all running at 100. As in this example, it’s often just embedded image size(s) which perturbs PageSpeed.
- Improving management of my theme and plugins to sustain these optimizations as easily as possible as updates arrive, e.g. tracking changes to JS and CSS files in updates, keeping copies of external JS files like Analytics updated, re-compressing updated files, etc.
- Upgrading my server to PHP7. The upgrade promises nearly 2x performance improvements. It’s not simple to upgrade prior to the bundled Ubuntu release, but it’s not too difficult.
- Upgrading my server to Varnish4. The upgrade requires some reworking of configuration files, and I’m unsure of its performance improvement and compatibility with W3 Total Cache, but I’m willing to give it a try.
- Explore KeyCDN’s CacheEnabler for serving more efficient Webp images to Chrome users. Webp file sizes are significantly smaller but not yet supported by Safari. I’m actually quite excited about improving the user experience with this.
If you have questions, please post them below. Or, you can contact me on Twitter @reifman. Please check out my Envato Tuts+ instructor page to see other tutorials I’ve written, such as Cloning WordPress in Linux (in 90 seconds).