Fixing WordPress site’s low mobile score in Google’s PageInsights with W3 Total Cache

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:

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:

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.

Blogging for bucks: Year 1 report, mistakes made, lessons learned

Today I’m going to talk about my blogs and how they did this year. Since this is the first post in what I hope will become an annual (or even more regular) series, I’m going to share a long-winded history of my blogs, too, so that you can learn what I did and what my first year of blogging was like.

Just to set expectations, I didn’t make a mint in 2014. I made around $3500 this year off Amazon Affiliate and Google Adsense combined. Nearly half of that amount was made in the last three months of the year. To put the amount in perspective, we spent about that same amount on food in 2014 (for two adults). Or, it’s 10 payments on a car leased for $350 a month. Hey, I’ll take it! I know there are SEO wizards making enough to buy a new Lamborghini every day with their blogs, and that’s awesome, but that didn’t happen to me (yet :D).

However, everything I did is 100% doable by you if you’d like to try out blogging for a little side income!

Backstory

I’ve been putting content online since about 1997. My early efforts were what you’d expect from a 13 year old: a Tamagotchi fan site on Tripod, an AOL site dedicated to my dog, my Sailor Moon fan art. It was so rewarding to share stuff I cared about and find (small) audiences for it! I even made some really good friends through my sites and artwork.

Monetizing the content I made, however, never really occurred to me. I suppose I might have said, “Who would pay me for this? The Internet is full of free stuff!”

Sharing stuff online became nearly everyone’s hobby as the Internet’s popularity exploded and sharing stuff became easier and easier (and this is awesome – no matter how obscure a thing is, 99.9% of the time I can Google it and find someone talking about it).

Nonetheless, in 2013 I found inspiration in the works of bloggers like Young House Love (now retired?) and Smart Passive Income (written by a smart guy who makes a lot of money online by telling others how to make money online).

The formula couldn’t be simpler: build a site on a profitable topic, get traffic, earn money through affiliate sales. Sounds good to me!

First Blogs

April 2011: House Blog

A few years ago I bought a house that needed a lot of work done. I thought it would be fun to write about it and document the projects. (It was.) I bought a domain and put a WordPress blog on it.

House Blog was all over the place in terms of content, and it certainly wasn’t set up to make money. No ads or affiliate links. I was giving my posts “clever” titles, not SEO-friendly titles. And I certainly wasn’t writing with revenue in mind.

House Blog just sat there, getting a new post whenever I felt like it (maybe once a month) but it had a nice little trickle of 20-30 visitors a day.

The blog was 2 years old when I got interested in “passive income” from blogging. I discovered the Amazon Affiliate program through a couple other blogs I followed. I wanted to see if it would work for me, so I re-wrote a couple of my older House Blog articles (and wrote a few new ones) to include Amazon Affiliate links to appropriate products.

Within a week, I had my first sale! :O

I made about 30 cents off it (lol). But that was enough to convince me the formula worked and I could scale it from here.

I decided to start a new blog (and keep House Blog, of course). This one would be more focused. Rather than try to be an all-over-the-place home renovation blog (which was seriously hard to generate content for: how often do you replace a toilet?), I’d choose fewer topics and discuss them in excruciating detail (which I enjoy).

July 2013: Craft Blog

Actually, what happened was I started a whole bunch of blogs, all centered around different topics. (Sigh)

Craft Blog is the only one of that batch that has made any money to this day, so I’ll just talk about it. (Lesson: don’t run out and buy 5 domains the second you have a few ideas.)

Craft Blog’s domain was purchased in the first week of July 2013. I put some lorem ipsum content up while I enthusiastically spent an entire weekend customizing the theme (another mistake: it’s not necessary to spend hours – or days – customizing the theme until you have steady traffic). On the bright side, I learned a lot about WordPress and CSS during those early days of obsessing over the site’s design.

Setting up a new WordPress site, customizing it, and planning its articles gave me a much-needed creative outlet. I wasn’t challenged in my day job, so having this site to look forward to at the end of the day was very exciting and motivating.

A few days later, a visitor came to the site! Oh no! I had spent all my time customizing the site’s design. The only content on the site was placeholder junk!

I loved working on Craft Blog, so banging out a few pages of content that fit the site’s niche was easy and fun. For my “monetization” articles, I reviewed stuff I either owned or had used, and I made recommendations based on my own personal wishlist and research. (If there’s one thing I love more than buying new toys, it’s researching those new toys for weeks prior.) I added Amazon links to help visitors find the stuff I was talking about.

Of course, I had lots of ideas for articles that weren’t Amazon-oriented, and I wrote those, too. I love writing tutorials, so I also put some nice Photoshop and Etsy tutorials on the site. End result: the site looked better for the 1-2 visitors it was getting a day.

By August, I had 12 good articles. Some were long (1500 words), some shorter (500 words), but all were nice original content I wrote myself. There was very little traffic at this time, maybe 25 visitors the whole month.

I did a Pinterest blitz around this time, hoping to “go viral” there, but that never happened. I don’t enjoy Pinterest, so I was pretty quick to let that part of my blog marketing slide. In fact, I let most of my marketing efforts slide. I might be allergic to self-promotion. I found it too difficult to do a lot of the stuff the experts say you should do to market your blog, and I was content, at least for now, to just write useful content and post it on the site.

By September 2013, I was up to 22 articles on Craft Blog. I only had 147 visitors total that month (about 3 months into the site’s life), and no sales, but I was enjoying the project so much I just kept going through October when I decided to start a new site and let Craft Blog coast for a while.

October 2013: Disney Ride Blog

In September 2013 I went to Disneyland. It was great! I caught a bad cold when I returned home, though, and had nothing to do but lay in bed and think about how much fun I had at Disneyland. I decided to start a blog about my favorite Disney ride. It would just be a nice place to collect all the history, legends, and secrets of the ride in one place. I bought a domain and wrote a couple short articles about the ride and what I knew about it.

Within a few days, the site was getting traffic.

Whoa, what?!

In its first 30 days, Disney Ride Blog got more traffic than Craft Blog had had in its entire 4-month life. This inspired an obsession with the site, which I worked on regularly for the next two months. By January 2014, the site had its first 100 visitor day!

The site was a traffic monster, but it was making almost no money (literally pennies a day, if anything).

I think the site stood out because of a lack of competition. Lesson: if no one else is in a niche, maybe that’s because there’s no money in it? :D

Unfortunately, while Disney Ride Blog was my strongest traffic site almost until the end of 2014, it has barely made a dollar. I love the site and it’s easily one of my favorite hobbies, but it just eats up bandwidth and brings in nothing. I’ve experimented with ad placement, Affiliate links, etc, but it’s stubbornly unprofitable.

Fortunately, Craft Blog got a few clicks and sales before the end of 2013, which gave me some ideas as to what to do next for making a “money” blog.

2013 blog income: $17.16

Yup, $17.16 for three sites over the whole year. Rollin’ in it.

2014 in Review

January 2014: Gizmo Blog

Six months into this “blogging for bucks” endeavor I had been writing content for three blogs fairly regularly and seen traffic grow accordingly, but between Adsense and Amazon Affiliate I had made a grand total of about $17 for the entire year. I think a lot of people would have called it quits at this point, because that’s a pretty embarrassing return on investment.

Not me! Haha, I bought a new domain in January, this one for a particular category of “smart home” gadgets I was very interested in.

Gizmo Blog would be the culmination of all my learning thus far: niche topic that not many people were covering in great detail yet with a focus on customers on the verge of making a purchase (and Amazon Affiliate links to guide them to the product’s Amazon page).

With one comparison article (including a comparison chart and about 1500 words of original written content), the site had its first visitors from Google and its first Amazon link click within 7 days (!!!).

January 2014 blog income: $8.66

Hey, that’s nearly half of what I made over half of last year!

I added a few more articles to Gizmo Blog cover the basics and then decided to let it sit. In the meantime, I did some footwork: I went to hardware stores and even an open house to see the products in person, since it would be impractical for me to install all of them into my own home. This helped me write smarter “hands on” reviews. It helps that I genuinely find the technology interesting – I can’t imagine writing a site like this without loving the thing you’re writing about.

February 2014: Double digit earnings!

February went better: as traffic grew (1660 visitors across all sites!), so did clicks to Amazon. I had my first double-digit earnings month. I didn’t do anything special or get any links, I just added a few new (long) articles to each site. From humble beginnings…

February 2014 blog income: $35.63

May 2014: First $100 month

Three important things happened between February and May 2014:

Thing 1: One of the manufacturers of a product I reviewed on Gizmo Blog tweeted a link to the review! This brought in a surge of traffic (58 in a day, woohoo!) and seemed to legitimize the site a bit in the eyes of Google because from this point on, traffic kept climbing – sometimes doubling with each passing month.

Thing 2: In May 2014, someone linked to one of my reviews on a forum, which is like a gift that just keeps giving because it not only sends regular traffic, it counts as a quality backlink in Google’s ranking algorithm.

Thing 3: I quit my day job and focused all my time on blogging and growing my web developer skills.

May 2014 blog income: $115.15

During the spring I also made a better effort at marketing the blogs. I created a Facebook, Twitter, Pinterest, and Google+ presence for all of them and re-tweeted / re-posted content to them regularly (1-2 times a week) for a while.

I don’t know how to make something “go viral” and I don’t enjoy spending a lot of time on social media doing what feels like an elaborate “look at me” routine, so again, I let marketing efforts fade out after a while.

Traffic grew steadily across all sites, which was great. Disney Ride Blog remained by far my strongest traffic-puller, but my weakest earner.

June 2014: My host complains

My long-time web host (Lunarpages, since 2005!) served me with a ticket and a complaint that my sites were consuming too many resources. This started my mad scramble to optimize my sites. Ultimately, I added W3 Total Cache to my sites which took a load off the servers (for a while – see December 2014). Without caching, each of my sites was re-loading all of its resources every time users navigated around the site.

At the time, I was surprised that WordPress didn’t come with optimizations built-in. It’s up to the user to add things like caching, lazy loading of images, minification of CSS and JS, automatic backups, and security measures like limits to login attempts.

Lesson: optimization becomes very important once your site(s) are bringing in around 50+ visitors a day.

October 2014: Holiday season begins

The summer was very good by my beginner standards: about $140 a month on average for June, July, August, and September. At least, until October raised the bar.

I added zero content between July and September, thanks to attending the full time Code Fellows Dev Accelerator and having negative free time for blogging.

Yet traffic continued to grow! The best part was, for the first time, my blogs were truly earning “passively” since I had done absolutely nothing on them. October really turned things around – nearly $600 in earnings, plus I’d done nothing on the sites in months.

October 2014 blog income: $594.19!

This sudden uptick in earnings inspired me to put those new web dev skills to use and optimize all the sites for mobile, which may explain at least some of the traffic increase that I saw in November and December. Disney Ride Blog and Gizmo Blog had been virtually unusable on mobile, now they work great on phones and tablets.

December 2014: Shopping season ends, host complains again

If October was great, then November was spectacular: $870 in earnings! I’ve read from other bloggers that the last three months of the year are the best for Amazon Affiliates and ecommerce sites, and I believe it. What a great way to end the year!

rue Color Image

However, I expect the earnings to fall back to their summer levels (if not lower) as soon as Christmas comes and goes.

Alas, my host complained again in December. They don’t have a problem with my bandwidth usage (that’s “unlimited”!) but they do have a problem with CPU resources being used, some of which are used every time someone visits one of my sites. With average daily visitors now around 3,000 for my sites combined, I was hitting it too hard for them.

Unfortunately, traffic peaked at the same time some bot network attacked many of my sites (or maybe the bots were always there, but weren’t causing any trouble until traffic reached a certain point). From the logs, it looks like at least one bot was trying to get in through wp-admin, and another seemed to be hitting the comments functionality of several of my sites.

I played wack-a-mole for 5 days trying to solve or at lease reduce the effect of the various attacks across my many sites. I banned IPs, tweaked cache settings on my WordPress sites, added login attempt limiting plugins, turned off plugins, turned on and off themes… no one thing was causing the high CPU usage. Lunarpages doesn’t offer great tools for debugging and the update time is slow – as much as a day before I can see if what I did had any effect.

It was time for something drastic.

I moved Gizmo Blog off Lunarpages and onto DigitalOcean, a scalable VPS that is probably more appropriate for a site that continues to grow in traffic every month.

digitalocean

I’ve been with DigitalOcean less than a week and while the process of moving the site over and locking it down security-wise took some time, the end result seems to be an immediate reduction in traffic to my stressed-out primary host. You can see the drop in traffic on December 16th- that’s the day Gizmo Blog left Lunarpages for greener pastures.

gizmo_blog_moved

It was probably inevitable, because this is how Gizmo Blog’s traffic is trending:

gizmo_blog_traffic

To Lunarpages‘s credit, they did not kick me out or shut down my blogs in response to my unintentionally high CPU use. In researching this CPU problem over the past week, I’ve found many bloggers who did get shut down by their hosts for this sort of problem.

To address my WordPress CPU usage problems, I used a combination of:

  • W3 Total Cache and WP Super Cache (I think I like Super Cache better so far)
  • BJ Lazy Load so image-heavy posts load images on an as-needed basis
  • WP smush.it for negligible image optimization (I already use save for web on all images, your mileage may vary)
  • Simple Firewall for better login security and other firewall features
  • WP Clone for moving Gizmo Blog to a new host with minimal pain
  • WP Optimize for clearing unused revisions out of the database
  • Disable Comments an emergency measure I deployed to help reduce the load on the server
  • WP Maintenance Mode another emergency measure I used to shut down Disney Ride Blog while I experiencing CPU overages (unprofitable sites are the first to go in times of need :P)
  • GTMetrix and its WordPress plugin for monitoring site load time and performance
  • CloudFlare free version on my highest traffic sites (how CloudFlare works)

It’s too soon to say if this is the end of the CPU overages saga, and I suspect it’s not. I’m currently using three hosts for my sites (Lunarpages, BlueHost, and DigitalOcean), all of which have been satisfactory in terms of what I expect from them (in other words, I don’t expect world class speed and performance out of a host charging me $5/month for shared hosting). Craft Blog will most likely be moving onto its own VPS in the near future and I may try someone other than DigitalOcean and see how they compare.

What’s next?

I don’t think I’ll start any new blogs this year. Maintaining individual blogs has become time consuming. Every update to WordPress has to be deployed individually to each site, and problems like CPU overages and hacker attacks often have to be debugged on all sites.

As for the ones I have, I plan to add content, continue to optimize the sites, move them to more suitable hosts, and just keep ’em growing. I’m eager to see where earnings fall to in the first months of the year, and whether traffic can continue to grow on its own during times where I don’t add content regularly.

If you (TILCode reader!) have enjoyed this break from coding talk, let me know in the comments and I’ll share blog updates more regularly. I’m not sure the web needs yet another site on how to blog for bucks, but I could be wrong. :) Hope you enjoyed this massive first installment!