Something I have been thinking a lot about lately is website speed. The load times for one of my largest clients, OverstockDrugstore, were getting worse by the day. It was due to an increased amount of traffic coming to a website that wasn’t properly tuned. After taking a very aggressive approach to decrease load times, conversions (sales) increased by 1-1.5% on days following. It blew my mind (and others at the company) that load times would have a direct impact on conversions.
If you think about it. it makes sense. 75% of their website visitors are new. So, they are visiting and experiencing the website for the first time. Also, many of them are coming from price engines. Most likely when they do a search on an engine, they go down the list clicking on each link. If the page loads slower than the other sites, they may either loose confidence or at least get a little impatient, which would cause them to choose someone else.
So, I thought I would share some of the things I did. Hopefully it will help you increase your overall website speed and in turn increase your conversions (whatever they may be). And if we all work together on implementing these techniques, and maybe even standardizing them, we could make the internet faster, and greener (saving energy). The following only applies to a Linux Server running PHP.
BENCHMARKING
It’s important before you begin, to get an idea of how your website is performing before you try to make it faster. This will give you an idea first of what to focus on and also a benchmark to compare and look back on. First, I would recommend downloading these add-ons for Firefox:
The first thing to do in order to simulate a first-time visitor, who we will mainly focus on, is to disable cacheing. The Web Developer toolbar makes this really easy. On the very left of the toolbar, there is a disable button. Click on it, and select the first option: “Disable Cache”. This will cause every element of a page to be loaded from the server each time you visit the website… exactly what happens when you visit a site for the first time.
The next thing to do is use Yahoo!’s tool, YSlow. It only works if firebug is already installed. But basically, you will see the icon in the bottom right corner of firefox. Load your page, and take note of the amount of seconds it takes to load the page. I would refresh 3-4 times and take an average number to get a good idea of what your load time for a first-time visitor is.
Next, use YSlow’s Performance analyzer to see in what types of areas you can improve. It gives you an overall grade, along with a grade for each area. I am not going to get into each one, since if you click on the name it will open up to a detailed explanation from Yahoo!. They don’t do a great job in explaining HOW to fix the problem though. Also, keep in mind the grade isn’t an end all – be all. Overstockdrugstore is graded a D overall. It’s a bit misleading, since the items may not apply to you at all or be possible for your organization.
MAKE FEWER HTTP REQUESTS is one of the most important things to look at when it comes to speed. Basically, your browser has to send a request for each separate element (image, js/css file, flash etc). The more elements you have, the more requests have to line up and be processed. The number of requests decreases dramatically with Browser-side cacheing, however that doesn’t help first time visitors. So, it’s important to try and cut this number down. A real easy way, is combining all of your CSS into one file, and all of your js code in a single file. For a lot of coders, this can seem a bit dirt but it is a really easy way to start cutting back on the number of GET requests your browser has to make. If you are a seasoned CSS coder, you could also create a CSS sprite. The benefit is having the user only have to download one large image. CSS is then used to show which region of the image is shown.
Expert Note: What I actually do with Overstockdrugstore is use PHP combine all of the js and css files at runtime and cache the result. My script then checks to see if any of the individual files have changed. If not, it uses the cache. If so, it rebuilds the single file. So, I am able to keep files separate for organization as a coding, but combine them into one for the end user. If you haven’t yet, take a look at Minify.
USE A CDN : A CDN or Content Delivery Network, is a server designed especially for delivering content. Amazon has one called CloudFront which is very affordable. The idea behind this is the content you put on your CDN is delivered to the user simulatenously as your page is loading. Your browser can only send two parallel requests per hostname at a time. But it can load content from multiple domains simultaneously. Also, the CDN delivers your content from a server that is closest to the user, increasing speed. If anything, it is a great way to offset your bandwidth.
Expert Note: If a CDN isn’t a reasonable solution, you could always host your images/css/js on a subdomain and deliver the content that way. Although it will always be sent from the location of your host, it could reduce the number of GET requests and organize your static content.
ADD AN EXPIRES HEADER : This has no impact on first-time visitors but can have a huge impact on subsequent page views. Basically, you need to tell your the Browser when the various elements on your page expire. Yahoo! talks about using a future expires header, which basically means saying an element doesn’t expire for 10 years or so. This wasn’t a practical approach for us, since it would cause you to change the filename of the element each time for the browser to download it. With making changes to our javascript/css all the time, this wouldn’t work.
However, putting an expires header of 600 seconds for each element did make since. Looking at our analytics, I realized that a visitor on average would visit the site for around 10 minutes. Because we change images and update products all the time, I figured it would be best to cache things only for around 10 minutes. I figured as well that if someone was comfortable enough to spend 10 minutes on the site, they would unlikely exit due to a sudden page load of a few more seconds (when the cache expired and they had to re-download elements). This number could be different for you, but using some of the logic I laid out you can find a balance.
An easy way to add an expires header to each element is using your htaccess file. Here is what I use for many of my websites:
<FilesMatch “\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|js|css)$”>
Header set Cache-Control “max-age=600, public”
</FilesMatch>
Basically, any element that matches (css/img/js/swf etc) will have an expires header of 600 seconds added to it before it is sent to the browser. Note, this snippet may not do what it is supposed to. Many shared hosts remove the ability to turn this on using htaccess. So, check with your host if it doesn’t seem to do the trick. How do you know if it’s working? Run YSlow Performance again and click on the Components tab. It will list every element and whether there is an expire time associated with it.
GZIP COMPONENTS: This will have an impact on first time visitors. Most browsers have the ability to uncompress files sent to them in a Zipped (compressed) format. This decreases the length of each GET request, since each element is compressed. The browser then uncompresses it and sends it to your screen. Using htaccess it is really easy to apply a rule that will apply to all the elements you want to be sent using GZip:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/x-javascript text/css text/html text/xml text/javascript
</IfModule>
Using GZip on text files will have the greatest impact. Since images and PDF’s for example are already compressed, it’s a waste of CPU power to compress them as well.
PUT CSS AT THE TOP: I am not sure why any of you reading this wouldn’t be in the habit of putting CSS between the <HEAD> tags at the top of your page. But I guess a good reminder.
PUT JAVASCRIPT AT THE BOTTOM: Depending on what you are using javascript for, this may not be possible. However, any javascript that you can put at the bottom that won’t affect page rendering should. If you have a big js file at the top that has to load, that will plug up your HTTP requests, and could slow down the browser from downloading images/logos etc. Basically a page is loaded from top to bottom, so moving things to the bottom that may stop visual things from loading, which intern act as a progress bar, can hinder users from sticking around.
AVOID CSS EXPRESSIONS: Just click on the link within your YSlow to learn more about this one. My guess is it affects very few of you.
MAKE JAVASCRIPT AND CSS EXTERNAL: Putting all of your CSS and Javascript in external files doesn’t only follow web standards, but it allows the individual files to be cached. Inline javascript or CSS is read every time the page is loaded. By having them in separate files, you can have them cache individually. Keep in mind the comment above, that you should combine all of your javascript and css into a single file (if possible) to also reduce your amount of GET requests.
REDUCE DNS LOOKUPS: This one is a bit touchy, since above I was saying how it’s better to spread your requests across different hostnames. Well, if you get too carried away, your browser has to resolve each individual hostname which could I guess slow things down. Although, DNS requests are generally very fast so I wouldn’t worry about this one as much as looking into a CDN server or using subdomains to deliver content. I think the key is just not getting too carried away. Yahoo! recommends only having 4 hostnames at use on your site at a time.
MINIFY JAVASCRIPT: If you have ever looked at the source code of a javascript file and became upset because there was no formatting, and it was basically impossible to read, that is most likely because the host was being smart, and minifying the javascript. This approach basically cleans out a lot of whitespace javascript files can have along with any developer comments that are added. This can decrease the filesize by quite a bit. Yahoo! provides a few ways for you to get this working. I personally use a PHP app called Minify. It can minify your js and css files at runtime and cache the result for future requests.
AVOID REDIRECTS: Read more at Yahoo!
REMOVE DUPLICATE SCRIPTS: Read more at Yahoo!
CONFIGURE ETAGS: My guess is you don’t need to use Etags. They are basically a flexible way to validate entities. If you don’t have a need for them, you might as well not send them to the browser. Doing so will cut down the amount of information attached to your elements. An easy was is to add the line ” FileETag none ” to the htaccess I showed above for expiration headers:
<FilesMatch “\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|js|css)$”>
FileETag none
Header set Cache-Control “max-age=600, public”
</FilesMatch>
This will take of Etags for any of the file types mentioned.
In Yahoo!’s article, they provide a few other things you can be doing to increase website performance. There are a couple things I would like to cover that have made a huge difference.
SERVER-SIDE CACHING: One thing that can have a huge impact on the amount of time it takes for a new user to access your site is how long it takes the page to get generated. Basically, if you have a dynamic website, PHP has to run a lot of database queries in order to get the content of the page. Delivering a static HTML page doesn’t require any database queries, since the file exists it is simply sent to the browser.
I would recommend using a library like Cache Lite or Memcache. The idea here is using these libraries to reduce the amount of database queries you make in order to generate a page. You can set an expire header which will regenerate the page as frequently as you want. If you have a wordpress blog, I would highly recommend looking into Super Cache, a plugin which will allow anyone who knows how to install a wordpress plugin full server-side caching abilities.
IMAGE COMPRESSION: Please take the time to learn the types of images that are best for your project. For example, JPG images are better at compressing pictures with a lot of colors and or gradients. A PNG however would be a much better choice for images with less blending and or color blocks (like a button). Make sure you are optimizing each image on your site, by selecting the appropriate type and compressing it accordingly. It is a very easy practice that a lot of people overlook, but doing it correctly can make a huge difference for first-time load times.
Conclusion:
I personally think that Caching should be a part of web standards. Implementing proper caching isn’t only easy, it decreases the amount of wasted bandwidth and CPU power across the internet. It feel with how flexible and easy to learn certain programming languages are, programmers/coders are becoming lazy in how they write their code. Let’s work together to standardize caching to improve the speed of the internet as a whole as well as free up bandwidth being wasted on sloppy code.
Also, I must say that the things I mentioned are only a piece of the pie. There are a lot of things that can be done to “tune” your apache server or mysql database, and other techniques to decrease the actaul size of your web pages. Please add to this list.

As always….thanks Patrick for the great information!
This is a very informative post! Keep up the good work.
There is an open source tool for complete website acceleration – Web Optimizer ( http://code.google.com/p/web-optimizator/ ). It applied all possible actions for client side optimization (and has dozens of settings for tuning).
Hi Patrick,
A very good post and lots of valuable information for programming noobies like me
Hope you haven’t forgotten me completely.
Adarsh.
Pingback: Speed up a wordpress website « My Blog
Hey Patrick, been a long time, I hope that your family is doing well. I switched careers and I now work for a global internet marketing company. I have been assigned the task of running speed tests on our corporate site. I came across this article while browsing the web. I was wondering if you might have any additional information or resources that you would recommend on this topic.
Downloaded firebug and it was of a great help to me. Haven’t tried the other 2 though. Shall download it soon. Thanks for sharing