Setting up subdomain cookies, Google Analytics and Nginx for faster asset serving
23 June 2009UPDATE: 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:
- We do a permanent redirect to the ‘www’ subdomain for any requests to example.com.
- We also set a month expires on any static content served from www.example.com just in case.
- The second ‘server’ section catches requests to static.example.com and sets the expires header and the cache control header for longevity. Notice it has the same ‘root’ setting as it is essentially the same as the first server configuration except with different headers. We also catch content requests that should have gone to the main domain and redirect them with a 301 redirect.
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.
« Site translation using jQuery and Google Upload Maildir to Google Mail »
Comments on this post
blog comments powered by Disqus