Setting up subdomain cookies, Google Analytics and Nginx for faster asset serving

23 June 2009 tags:

UPDATE: The code below for asynchronous Google Analytics tracking is no longer required, just use their new tracking snippet.

Not long ago I wrote about using subdomains to improve your sites’ performance. I also put up some code to make Google Analytics load after all your page has loaded. Well this is one way you can combine it all to speed up your site.

Nginx subdomain setup

Firstly, you need to set up a separate subdomain to serve your static, cookie-less content. Let’s say http://static.example.com/. This requires a section in your Nginx server config as follows:

server {
  server_name example.com www.example.com;
  root   /var/www/.../example.com/htdocs/;

  # lets add www
  if ($host !~* "^www\.") {
    rewrite  ^/(.*)$  http://www.$host/$1  permanent;
  }

  # serve static files directly
  if ($request_uri ~* "\.(jpe?g|gif|css|png|js|ico|pdf|zip|gz)$") {
    expires 30d;
    break;
  }

  #... other stuff here ...

}

server {
  server_name static.example.com;

  if ($request_uri !~* "\.(jpe?g|gif|css|png|js|ico|pdf|zip|gz)$") {
    rewrite ^(.*) http://www.example.com$1 permanent;
    break;
  }

  location / {
    root   /var/www/.../example.com/htdocs/;
    expires max;
    add_header Cache-Control private;
  }
}

Some of the important points to notice:

This setup allows us to set cookies on the www.example.com domain and not static.example.com.

Google Analytics tracking domain setup

This section is now redundant with Google’s asynchronous analytics code, see here for more details http://googlecode.blogspot.com/2009/12/google-analytics-launches-asynchronous.html

We then need to adjust our Google Analytics code from my previous post to enable setting the domain for the cookies. The updated code is below:

function gaLoad (key, domain) {
  if (domain == null) {
    domain = 'auto';
  }
  // account for SSL
  var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  var t;
  var s;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = gaJsHost + 'google-analytics.com/ga.js';
  s.loaded = false;

  // call the GA tracker
  function ga() {
    t = _gat._getTracker(key);
    t._setDomainName(domain);
    t._trackPageview();
  }

  // set up the hooks
  s.onload = function () {
    s.loaded = true;
    ga();
  };
  s.onreadystatechange = function() {
    // test that it is complete(4), exists(200) and hasn't already been loaded
    if (s.readyState == 4  && !s.onloadDone && s.status == 200) {
      s.loaded = true;
      ga();
    }
  };

  // insert the script into the head
  document.getElementsByTagName('head')[0].appendChild(s);
}

This is then called like this:

// load Google Analytics
gaLoad('UA-XXXXXX-X','www.example.com'); 

This sets the Google Analytics cookie only for the domain www.example.com meaning that requests to our assets from static.example.com will not have the cookie set. If you leave off the domain it defaults to Google’s ‘auto’ method of determining the domain. I also added this code to my git repository to keep track of any changes.

Now you just have to remember to refer to static elements of your page from the static.example.com domain. This is only for items that are unlikely to change like images, CSS, javascript etc.

Varnish’s cache

Varnish (or another proxy) will now be able to cache all content from static.example.com as it has no cookies set. There are ways to set up Varnish to enable caching of cookied content but it is easy to run into trouble there. This method can be done on a per site basis without having to adjust Varnish and have very good results.

Conclusion

By being a little more careful in how you construct your subdomain structure and how your site uses it, you are able to reduce bandwidth and enable other parts of the delivery chain to do their job better.


Possibly Similar Pages


Comments on this post

blog comments powered by Disqus
loading