Search
+1 (617) 7782998 | info@iispeed.com

How to optimize your PageSpeed Insights score when using tracking and social media scripts

Author

The problem: lost points on PageSpeed Insights

PageSpeed Insights leverage browser caching violation

Many tracking and social media files are served with a short cache TTL. This zooms in on the Twitter and Facebook buttons plus the Google Analytics tracking script and disqus. This short TTL is perceived by Page Speed Insights as a violation of the recommended best practice to leverage browser caching. The reason these scripts are served with with a short cache TTL is that doing so allows updates to the file to be distributed quickly.

Approach one: DIY with MVC and C#

One thing you could do is catch requests to, say, /scripts/ga.js in a handler and download it from Google on the fly (and cache it subsequently) each time the application pool starts. That ensures a reasonable freshness of the file and allows full control of the response headers.

MVC / C# Code Snippet

    public class MvcApplication : System.Web.HttpApplication
    {
        private static object ga_lock_ = new {};
        private static bool ga_refreshed_ = false;
        private void Application_BeginRequest(object sender, EventArgs e)
        {
            // Avoid taking the lock every time
            if (!ga_refreshed_) {
                lock(ga_lock_) {
                    int minutes = 60 * 24 * 15;
                    Response.CacheControl = "public";
                    Response.Expires = minutes;
                    if (!ga_refreshed_ && application.Context.Request.FilePath.ToLower() == "/scripts/ga.js") {
                        using (WebClient client = new WebClient())
                        {
                            client.DownloadFile("http://www.google-analytics.com/analytics.js", Server.MapPath("/Scripts/ga.js"));
                        }
                        ga_refreshed_ = true;
                    }
                }
            }
        }
    }

MVC / C# Result

Google hosted response

GET http://www.google-analytics.com/analytics.js

    Accept-Ranges: none
    Age: 3849
    Alternate-Protocol: 80:quic,p=0
    Cache-Control: public, max-age=7200
    Content-Type: text/javascript
    Date: Tue, 02 Jun 2015 10:39:17 GMT
    Expires: Tue, 02 Jun 2015 12:39:17 GMT
    Last-Modified: Wed, 27 May 2015 21:02:55 GMT
    Server: Golfe2
    Transfer-Encoding: chunked
    Vary: Accept-Encoding
    X-Content-Type-Options: nosniff
            

Self hosted response

GET http://2015iispeed.localhost/scripts.ga.js

    Accept-Ranges: bytes
    Cache-Control: public
    Content-Encoding: gzip
    Content-Length: 13500
    Content-Type: application/x-javascript
    Date: Tue, 02 Jun 2015 12:00:33 GMT
    Expires: Wed, 17 Jun 2015 12:00:05 GMT
    Server: Microsoft-IIS/7.5
    Vary: Accept-Encoding
    X-Powered-By: ASP.NET
        

In the example above we've used a 15 day expiry which is enough to satisfy PageSpeed Insight Analysis. This approach has some drawbacks:

There is, however, an easier way to do this.

Approach Two: PageSpeed Automatic Optimization

If you run PageSpeed optimization on your website, the solution could be even easier. PageSpeed is able to proxy and optimize external content if you tell it to.

PageSpeed configuration snippet

# Examples for pulling in Google Analytics, facebook, twitter, and disqus
pagespeed MapProxyDomain http://www.mydomain.com/twitjs/ http://platform.twitter.com/
pagespeed MapProxyDomain http://www.mydomain.com/fbjs/ http://connect.facebook.net/
pagespeed MapProxyDomain http://www.mydomain.com/gajs/ http://www.google-analytics.com/
pagespeed MapProxyDomain http://www.mydomain.com/disq/ http://a.disquscdn.com/

# Https is a little more involved, I don't think this is the preferred approach
# but the configuration that should be working seems to fail. This is what we use at iispeed.com
pagespeed MapOriginDomain http://a.disquscdn.com/ https://a.disquscdn.com/
pagespeed MapRewriteDomain https://www.iispeed.com/disq/ https://a.disquscdn.com/
pagespeed MapProxyDomain http://www.iispeed.com/disq/ http://a.disquscdn.com/ https://www.iispeed.com/disq/


PageSpeed Optimization Result

With this in place, PageSpeed is able to optimize the script and shave off a few more bytes next to cache-extend the file to a one year TTL according to confuration while still being able to respect the original cache TTLs and thereby force updates through to visitors at the desired frequencies.

GET http://www.mydomain.com/gajs/analytics.js.pagespeed.a.jm.tDDgRnEFyB.js

    HTTP/1.1 200 OK
    Cache-Control: max-age=31536000
    Content-Type: text/javascript
    Content-Encoding: gzip
    Expires: Wed, 01 Jun 2016 13:19:51 GMT
    Accept-Ranges: none
    Age: 5920
    ETag: W/"0"
    Vary: Accept-Encoding
    Server: Golfe2
    X-Content-Type-Options: nosniff
    X-Page-Speed: 1.9.32.3
    X-Powered-By: ASP.NET
    Date: Tue, 02 Jun 2015 13:19:57 GMT
    Content-Length: 13433
            

Conclusion

The PageSpeed approach seems to be the clear winner, as it respects the origin TTL, shaves off a few bytes, and is far less work. One line of configuration is all that is needed to fix PageSpeed rules compliance. Wether doing so actually improves performance should be measured, as the CDN's used for serving those external assets might outperform the hosting of your website - next to that for some scripts there's a big chance that visitors will already have those in the browser cache. Later wil will run a split a/b test to see if and how this tuning affects performance and publish the result.



Share View Comments
.