How to Fix the Leverage Browser Caching Warning in WordPress

Updated on September 24, 2017

If you have ever run your WordPress website through Google PageSpeed Insights or Pingdom then you have probably seen that big yellow Leverage Browser Caching warning. And that is probably why you ended up at this post. Today we will dive into what this warning means, how it affects you, and what your options are as it pertains to your WordPress site.

What is the Leverage Browser Caching Warning?

The leverage browser caching warning, as shown below in the screenshot, is referring to your browser cache. Whenever you visit a website, it downloads assets, such as HTML, CSS, JavaScript and images into your browser’s local cache. This way it doesn’t have to retrieve them on every page load. The warning itself is returned when your web server, or a third-party server, doesn’t have the correct HTTP cache headers implemented. Or the headers might exist, but the cache time is set too short.

leverage browser caching pagespeed insights

Set an expiry date or age in HTTP headers

You might also see this warning in the new “think with Google” website speed test, which is powered by Google PageSpeed Insights. This was designed to be more of a marketing tool by Google, but this has resulted in lot of clients now simply forwarding these errors to their webmasters. Leaving WordPress developers and designers looking for ways to quickly fix it to appease their clients.

think with google speed test

think with Google speed test

Fix the Leverage Browser Caching Warning in WordPress

When it comes to fixing the leverage browser caching warning there are a couple different scenarios that are usually encountered by WordPress users. Obviously the most common one is that your web server is not correctly configured. The second ironically is that the Google Analytic’s script gives us the warning. And the third is other third party scripts returning the warning. See what your options are below.

1. Leverage Browser Caching on Server

The first and most common reason the leverage browser caching warning is triggered is that your web server doesn’t have the appropriate headers in place. In the screenshot below in Google PageSpeed Insights you will see the reason is because an expiration is not specified. When it comes to caching there are two primary methods which are used, Cache-Control headers and Expires headers. While the Cache-Control header turns on client-side caching and sets the max-age of a resource, the Expires header is used to specify a specific point in time the resource is no longer valid.

leverage browser caching pagespeed insights assets

Leverage browser caching warning in Google PageSpeed Insights

So now let’s explore how to add these headers to your web server. Note: You don’t necessarily need to add both of the headers, as this is a little redundant. Cache-Control is newer and usually the recommended method, however, some web performance tools like GTmetrix still check for Expires headers. These are all examples, you can change file types, expire times, etc. based on your needs.

Important! Editing your Nginx config or Apache .htaccess file could break your site if not done correctly. If you are not comfortable doing this, please check with your web host or developer first.

Adding Cache-Control Header in Nginx

You can add Cache-Control headers in Nginx by adding the following to your server config’s server location or block.

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
 expires 30d;
 add_header Cache-Control "public, no-transform";
}

So what exactly is the code above doing? Basically, it is telling the server that the file types are not going to change for at least one month. So instead of having to download the resource every time, it caches it on your computer. This way it is faster for return visits.

Adding Expires Headers in Nginx

You can add Expires headers in Nginx by adding the following to your server block. In this example, you can see how to specify different expire times based on file types.

    location ~*  \.(jpg|jpeg|gif|png)$ {
        expires 365d;
    }

    location ~*  \.(pdf|css|html|js|swf)$ {
        expires 2d;
    }

Adding Cache-Control Headers in Apache

You can add Cache-Control headers in Apache by adding the following to your .htaccess file.

<filesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=84600, public"
</filesMatch>

Adding Expires Headers in Apache

You can add Expires headers in Apache by adding the following to your .htaccess file.

## EXPIRES HEADER CACHING ##
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType image/gif "access 1 year"
ExpiresByType image/png "access 1 year"
ExpiresByType text/css "access 1 month"
ExpiresByType application/pdf "access 1 month"
ExpiresByType application/javascript "access 1 month"
ExpiresByType application/x-javascript "access 1 month"
ExpiresByType application/x-shockwave-flash "access 1 month"
ExpiresByType image/x-icon "access 1 year"
ExpiresDefault "access 2 days"
</IfModule>
## EXPIRES HEADER CACHING ##

If you are a Kinsta client you don’t have to worry about adding these headers. These are already in place on all of our Nginx servers. And remember, if you use CDN provider like KeyCDN, these headers are most likely already being set on your assets.

You can check your headers in Chrome DevTools network panel or simply be re-running your WordPress site through Google PageSpeed Insights again to ensure the warning is now gone.

caching headers wordpress

HTTP caching headers

2. Leverage Browser Caching and Google Analytics

The second most common leverage browser caching warning actually comes from Google Analytics. This is kind of ironic seeing as this is Google’s own script. The issue is that they set a low 2 hour cache time on their asset, as seen in the screenshot below. They most likely do this because if for some reason they were to modify something on there end they want all users to get the changes as fast as possible.  However there is a way to get around this, and that is by hosting Google Analytics script on your own server. Please be aware though that this is not supported by Google.

leverage browser caching-pagespeed insights analytics

Google Analytics caching

There is a great free little plugin called Complete Analytics Optimization Suite, created and developed by Daan van den Bergh, which allows you to host Google Analytics locally on your WordPress website.

host google analytics locally plugin

CAOS plugin

You can download Complete Analytics Optimization Suite from the WordPress repository or by searching for it under “Add New” plugins in your WordPress dashboard. The plugin allows you to host your Google Analytics JavaScript file (analytics.js) locally and keep it updated using wp_cron(). Other features include being able to easily anonymize the IP address of your visitors, set an adjusted bounce rate, and placement of the script (header or footer).

Some additional benefits to hosting your analytics script locally is that you reduce your external HTTP requests to Google from 2 down to 1 and you now have full control over the caching of the file. This means you can utilize the cache headers as we showed you above.

Just install the plugin, enter your Google Analytics Tracking ID, and the plugin adds the necessary tracking code for Google Analytics to your WordPress website, downloads and saves the analytics.js file to your server and keeps it updated using a scheduled script in wp_cron(). We recommend also setting it to load in the footer. Note: This plugin won’t work with other Google Analytics WordPress plugins.

local analytics settings

Locally hosted analytics settings

3. What About Other 3rd Party Scripts?

If you are running a business on your WordPress website, most likely you have additional 3rd party scripts running to track conversions, A/B tests, etc. This might include scripts like Facebook conversion pixels, Twitter, CrazyEgg, Hotjar, etc. Unfortunately, since you can’t host those locally there is nothing much that can be done as you don’t have control over the caching of those 3rd party assets. But for many smaller sites and bloggers, you most likely can get rid of that leverage browser caching warning altogether by following the recommendations above.

leverage browser caching 3rd party scripts

Leverage browser caching warning from 3rd party scripts

Summary

You definitely have some options available to you when trying to fix that annoying leverage browser caching warning on your WordPress site. For most people, you can probably clear it up altogether. Remember, these web performance tools should be used as guidelines. We wouldn’t recommend obsessing over the scores too much. But fixing the warnings will usually result in a faster WordPress website in the end.

Have any other tips about fixing the leverage browser caching warning? If so, feel free to drop us a comment below.

This article was written by Brian Jackson

Brian focuses on our inbound marketing efforts; everything from developing new online growth strategies, content creation, technical SEO, and outreach within the WordPress community. He has a huge passion for WordPress, has been using it for 8+ years, and even develops a couple premium plugins. Brian enjoys blogging, movies, bike rides, and flipping websites.

Hand-picked related articles

  1. Gravatar for this comment's author
    Adrian Pauly December 3, 2016 at 1:17 pm

    Thanks but your method didn’t work. Even though I can see the Cache Control and Expires headers when loading my site, I’m still getting the same “Leverage browser caching” message from PageSpeed and gtmetrix

    1. Gravatar for this comment's author
      Brian Jackson December 4, 2016 at 4:40 pm

      Is this on your 89decibeles.com website? I am looking at it in PageSpeed insights and you are all good as far as your server goes. The only leverage browser caching warnings left are from Facebook script and Google Analytics. An alternative solution for fixing Google Analytics is above in the post and for Facebook script you have no control over that, since it is a 3rd party script. Your only option would be to remove it. Hopefully that helps!

      1. Gravatar for this comment's author
        Adrian Pauly December 15, 2016 at 8:03 am

        Thanks a lot Brian! Managed to solve it now.

        1. Gravatar for this comment's author
          Brian Jackson December 15, 2016 at 8:20 am

          Great, glad to hear it!

  2. Gravatar for this comment's author
    Annapurna Agrawal February 20, 2017 at 11:03 pm

    .htaccess method doesn’t work for me. Can you please let me know why?
    Even after adding codes to .htaccess file, the same issue for leverage browser caching shows.
    Please help me out.

    1. Gravatar for this comment's author
      Brian Jackson March 27, 2017 at 12:23 pm

      Did you add them at the top or bottom of your .htaccess file? Also, do you have an 3rd party caching plugins that are perhaps overwriting the file?

  3. Gravatar for this comment's author
    Shawn Rebelo March 7, 2017 at 11:14 am

    To me the biggest problem is google not recognizing the changes, therefore we get problems like mentioned below. Then someone else checks, and its fine? Been siting here for 30 min. I know what i am doing, tried all the methods. And every single freaken time “YOU NEEED LEVERAGE CACHING!” I start to question whether or not this is a reliable too at all since it cannot easily and efficiently recognize changes.

    1. Gravatar for this comment's author
      Brian Jackson March 27, 2017 at 12:22 pm

      We have noticed this as well… Make sure you test with cleared cache as this can sometimes affect the tests. Do you know which scripts were causing your leverage caching warning?

  4. Gravatar for this comment's author
    Michael March 22, 2017 at 3:01 pm

    Well, thanks, but I did that and https://testmysite.thinkwithgoogle.com/ is still telling me that I didn`t do it.

    1. Gravatar for this comment's author
      Brian Jackson March 27, 2017 at 12:22 pm

      Which scripts were causing your warning?

  5. Gravatar for this comment's author
    Phillip Ray Switzer April 7, 2017 at 7:10 am

    With google tag manager you can shift that issue off of your site a little right? Since the bundle generated is cached by Google anyways.

  6. Gravatar for this comment's author
    Umar Shah May 16, 2017 at 8:28 am

    Thanks for this

  7. Gravatar for this comment's author
    radicalwindsurfing June 9, 2017 at 3:59 am

    Thanks for this helpful info. I’ve been trying to fix the Leverage browser caching issue for https://ssl.google-analytics.com/ga.js (2 hours) but no success yet. I tried the following ones, also ga-lite version, but none of them is working,
    http://diywpblog.com/leverage-browser-cache-optimize-google-analytics/
    https://www.keycdn.com/blog/leverage-browser-caching/

    I have these plugins installed, Aoutoptimize, CDN Enabler, CAOS, Google XML sitemaps, WP Super Cache, YoastSEO, etc and set up SSL with Cloudflare.

    I can’t think of anything else at this point. Please help.

  8. Gravatar for this comment's author
    radicalwindsurfing June 9, 2017 at 5:33 am

    NVM, just figured it out.

  9. Gravatar for this comment's author
    Marc Striebeck July 4, 2017 at 11:48 am

    Hi, I solved the problem of all the images slowing down my site, and then of course a butt load of other scripts came up just after, and these are the third party scripts you mention.

    Here you say :
    “But for many smaller sites and bloggers, you most likely can get rid of that leverage browser caching warning altogether by following the recommendations above.”

    Well you see, I don’t see anywhere about the “recommendations above”, unless you’re talking about the Google Analytics Plugin, which is the only thing I see, but then you go on to say that 3rd party scripts can’t be locally hosted, assuming that you are referring to the google analytic plugin. So which recommendation exactly are you talking about.

    BTW, thank you for the .htaccess header scripts, I have apache, and I only needed the first script, took care of all the images and their speed, but then like I mentioned, a bumch of other scripts came up.

    My site is https://kingsmangold.com/ and here are the scripts it came up with :

    https://static.doubleclick.net/instream/ad_status.js (15 minutes)
    https://kingsmangold.com/…awesome/css/font-awesome.min.css?ver=4.8 (23.5 hours)
    https://kingsmangold.com/…plugins/maxbuttons/js/min/front.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…et/js/q2w3-fixed-widget.min.js?ver=5.0.4 (23.5 hours)
    https://kingsmangold.com/…e/widgets/button/css/style.css?ver=1.9.3 (23.5 hours)
    https://kingsmangold.com/…esia/css/animate/animate.min.css?ver=4.8 (23.5 hours)
    https://kingsmangold.com/…ia/css/bootstrap/bootstrap.min.css?ver=1 (23.5 hours)
    https://kingsmangold.com/…oesia/fonts/font-awesome.min.css?ver=4.8 (23.5 hours)
    https://kingsmangold.com/…themes/moesia/js/jquery.fitvids.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…/themes/moesia/js/jquery.sticky.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…mes/moesia/js/navigation.js?ver=20120206 (23.5 hours)
    https://kingsmangold.com/…ontent/themes/moesia/js/scripts.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…a/js/skip-link-focus-fix.js?ver=20130115 (23.5 hours)
    https://kingsmangold.com/…/themes/moesia/js/waypoints.min.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…ntent/themes/moesia/js/wow-init.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…ontent/themes/moesia/js/wow.min.js?ver=1 (23.5 hours)
    https://kingsmangold.com/…-content/themes/moesia/style.css?ver=4.8 (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/06/4.jpg (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/06/5.png (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/06/RA-Logo.png (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/06/gold2.1.png (23.5 hours)
    https://kingsmangold.com/…/06/wholesale-metals-direct-300×84-1.png (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/07/1.jpg (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/07/2.jpg (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/07/3.png (23.5 hours)
    https://kingsmangold.com/wp-content/uploads/2017/07/bbb.png (23.5 hours)
    https://kingsmangold.com/…wp-content/uploads/2017/07/jefferson.png (23.5 hours)
    https://kingsmangold.com/…sow-button-wire-3b4d2344f593.css?ver=4.8 (23.5 hours)
    https://kingsmangold.com/…s/jquery/jquery-migrate.min.js?ver=1.4.1 (23.5 hours)
    https://kingsmangold.com/…-includes/js/jquery/jquery.js?ver=1.12.4 (23.5 hours)
    https://kingsmangold.com/wp-includes/js/wp-embed.min.js?ver=4.8 (23.5 hours)
    https://kingsmangold.com/…ludes/js/wp-emoji-release.min.js?ver=4.8 (23.5 hours)

    I’ve checked with another browser with it’s history completely cleared, as well as most of my WP Plugins, deactivated, I really don’t want to uninstall them either. Whatever shall I do to please the almighty Google?

    Simultaneously, here is another website that you maybe able to get some ideas from. https://moz.com/blog/how-to-achieve-100100-with-the-google-page-speed-test-tool

    Thanks in advance.

  10. Gravatar for this comment's author
    Marc Striebeck July 4, 2017 at 1:05 pm

    Ok, well, it was a link to show you the homepage so you can see what was going on with it.

    1. Gravatar for this comment's author
      Brian Jackson July 4, 2017 at 1:07 pm

      We didn’t delete it, we have moderation enabled whenever someone post links. This is to prevent spam. I have approved the comment and will try to respond to it here shortly. Thanks

  11. Gravatar for this comment's author
    Marc Striebeck July 4, 2017 at 1:08 pm

    Were you able to read the post before it was rudely and disruptively deleted?

    1. Gravatar for this comment's author
      Brian Jackson July 4, 2017 at 1:10 pm

      Marc, we don’t delete comments. It was automatically flagged for moderation due to posting links in it. This is to prevent spam.

  12. Gravatar for this comment's author
    Marc Striebeck July 4, 2017 at 1:13 pm

    Ok, that’s fine, a bit limiting, but fine, So anyways, for when the author comes back, I implemented the header code into the .htaccess file on my server, and it basically has changed from (expiration not specified) to (23.5 hours) beside all the items in the list, including the images that were there previously, along with the new scripts, which I am at a loss of trying to figure out what to do about it, I wish I could get a straight answer on it, I mean should I simply just move them to the bottom of the code or host them on a CDN, which is easier, and which is faster, and which is harder, to save some time here.

    I mean because it still says the same thing, I am referring to the 3rd party scripts, where should they go? Also is seems like if one optimization is taken care of, it may add or subtract from other optimizations.

  13. Gravatar for this comment's author
    Marc Striebeck July 5, 2017 at 11:28 am

    Hi, I just wanted to thank you and that the longer apache script finally worked for me, I’m not sure why it didn’t work in the first place, but it does now.

    It wasn’t until I got a hold of my host, and she gave me the same script and for some reason it worked that time, maybe it was Google’s 30 second rule or something.

    But I feel quite elated after trying all day and almost all 20 items or so with Leverage Browser Caching Warning are gone except for the https://static.doubleclick.net/instream/ad_status.js (15 minutes) script, not sure what to do about that.

    1. Gravatar for this comment's author
      Brian Jackson July 5, 2017 at 11:47 am

      Glad to hear it Marc! Most likely it was the placement in your .htaccess file or perhaps like you said, you didn’t wait long enough. For that last one, I am pretty sure it is because you have remarketing enabled on your Analytics script. See here: https://woorkup.com/speed-up-wordpress/#10-Google-Analytics-8211-Removed-Advertising-and-Remarketing

      1. Gravatar for this comment's author
        Marc Striebeck July 5, 2017 at 11:51 am

        Hi, no I figured out it’s a YouTube video I have in the side bar, I have no idea how to get rid of it without actually eliminating the video, which is senseless, because that video plays a large role considering content.

        1. Gravatar for this comment's author
          Brian Jackson July 5, 2017 at 11:53 am

          Oh, ya for that my only suggestion might be to utilize a plugin like this: https://wordpress.org/plugins/lazy-load-for-videos/ Basically it replaces your video with an image until someone clicks on it. This means it wouldn’t load that script on pageload. Not sure if it works in widgets, but you can try :)

          1. Gravatar for this comment's author
            Marc Striebeck July 5, 2017 at 11:56 am

            Thanks! Ya I’ll try that as soon as I can, that simple one little video is eating up a huge resource that is normally just a few kilobytes of loaded data for the entire page.

  14. Gravatar for this comment's author
    Manjesh M. Pillai July 15, 2017 at 2:44 am

    How can i do this in DigitalOcean with Apache/2.4.25 (Ubuntu) server?

  15. Gravatar for this comment's author
    Aabirah Sajid September 26, 2017 at 4:21 am

    Hey ! i have same leverage browser cache issue on my website. I have tried every possible method but didn’t work. I also use every premium plugin but not see luck. So i have decided to make a new website. I also bear expence. new site in under folder on same hosting and domain. But when i copy it to main domain. got the same error

    Can you help me please

  16. Gravatar for this comment's author
    kelmara October 7, 2017 at 10:38 am

    PLEASE HELP ME!!!

    I just follow this steps (Browser caching for .htaccess)

    I put this in my .htaccess , and after this crash my web site, and i can´t go in in my wordpress.

    When you click in my site now appear this messenger:

    Internal Server Error

    The server encountered an internal error or misconfiguration and was unable to complete your request.

    Please contact the server administrator at webmaster@kokodrift.com to inform them of the time this error occurred, and the actions you performed just before this error.

    More information about this error may be available in the server error log.

    Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.

    PLEASE HELP ME I M CRYING!!!!!!!! =……….(
    1s
    Kelmara Lemos’s profile photo
    Kelmara Lemos
    After i put this crash my website please hellp me!!!!

    ## EXPIRES CACHING ##

    ExpiresActive On
    ExpiresByType image/jpg “access 1 year”
    ExpiresByType image/jpeg “access 1 year”
    ExpiresByType image/gif “access 1 year”
    ExpiresByType image/png “access 1 year”
    ExpiresByType text/css “access 1 month”
    ExpiresByType text/html “access 1 month”
    ExpiresByType application/pdf “access 1 month”
    ExpiresByType text/x-javascript “access 1 month”
    ExpiresByType application/x-shockwave-flash “access 1 month”
    ExpiresByType image/x-icon “access 1 year”
    ExpiresDefault “access 1 month”

    ## EXPIRES CACHING ##

    my facebook is kelmara lemos please help me

    1. Gravatar for this comment's author
      Brian Jackson October 8, 2017 at 12:08 pm

      Hi, just put your old .htaccess file back and you’ll be good to go :) Most likely you have a spacing/typo or something which is breaking it. Feel free to ask your host if you need assistance using the code above.

Leave a Reply to Annapurna Agrawal Cancel reply

Use WordPress?

Join 20,000+ others who get our FREE weekly newsletter with WordPress tips on how to drive more traffic and revenue to your business!

You have Successfully Subscribed!

Send this to a friend