W3-Total-Cache and Serving Static Content from a Cookieless Subdomain on Shared Hosting (any shared hosting)
That title’s just gibberish to most people. But if you’re a WordPress blog owner or web developer and, like me, you’ve searched hours and hours for the right caching plugin, read countless reviews, went through countless, frustrating iterations of testing and reconfiguring, and read numerous posts on speeding up your blog that led to this mysterious thing called the “cookieless subdomain”, and you need to set it up on shared/web hosting – then this is the page for you. Bookmark it, read it, and if you want to devote a couple hours to making your website significantly faster, print it and get to work.
Tip! The print service we use will allow you to generate a printer-friendly version that you can use as a checklist. You can even delete paragraphs and print only what you need.
I have written instructions that I believe site administrators of all skill levels can understand. However, I am making four basic assumptions:
- Your WordPress blog is NOT a multi-site blog. Some of my instructions may apply to them as well, but you’ll need to do the research to make the necessary changes.
- Your blog is in the root directory. Its either www.yoursite.com or yoursite.com.
- Your subdomain will be located off the root and named something like uploads.yoursite.com or cdn.yoursite.com.
Note: If you’re moving your WordPress uploads image files to a subdomain, you will need to be able to run one query (provided below) in phpMyAdmin to update the database entries.
- You have at least some experience working with php files and uploading files to your server via FTP to your Godaddy shared hosting account. I recommend the free FTP client Core FTP LE.
Btw: After 8+ years of using shared hosting providers Godaddy (the worst support), 1and1.com, Bluehost and Siteground (the best support), I made the move at the beginning of 2015 to a Knownhost managed VPS plan. Best deals I’ve found anywhere (not those annoying short-term specials) with CPanel included for just $5 extra. I can’t recommend them enough. You don’t need to know much of anything about VPS except learning the basics on setting up accounts in CPanel WHM. Then just use CPanel as you have with shared hosting. They will support you, no matter how inexperienced you may be. And yes, you’ll still do everything on this page to improve performance whether you’re with shared hosting, VPS or Dedicated.
Initial Test Results
Before you start anything, you’ll need some test results for comparison from these free online test sites (I have no affiliation to these sites). Test a static blog page that will not change over time, like your About page.
Load Impact: Great, dynamic update load impact tool. You can do a few, free tests daily, but I recommend that you register to get 5 free tests a month (so don’t waste them) because you can create a test configuration with a user scenario using the same load zone city (in the U.S.) for all tests (the unregistered, free test changes cities at random giving different results). In the initial tests, you should expect to see a rising blue line in the graph that represents the user load time.
That’s because with an economy, shared-hosting plan, as the number of concurrent users hitting your site increases, the user load time usually increases. If you’re lucky enough to be mentioned in a high traffic site and see a spike in visitors, your site can slow to a crawl or fail.
After you’re finished implementing the CDN, caching and compression process below, you should expect to see a flat user load time graph line where the load is evenly balanced even as the number of concurrent users increase (see more details in this faq page).
Which Loads Faster? is a comparison site that will show how your blog stacks-up against another. Choose “Try my own matchup”, enter your blog domain on one side and another blog on the other (compare your About page to a similar static page on the other site). Then record the results that pop-up at the end. Repeat the test two more times and record the average of the three tests. You’ll need to rerun the tests against the same blog after you finish the project.
Web Page Test is one of the most useful, free test sites. You can select the test location, just make sure you use the same city every time. When the test is complete, click the Waterfall graph to see details. Record the Load Time. Repeat this test two more times and record the average.
Pingdom: Pingdom’s Full Page Test results vary wildly because they test from a different city on every test. Ignore the “Your website is faster than …” for now. However, the Performance Grade tab is very useful in isolating your site’s problems. Make a note of the “Perf. Grade” fraction result and then check the recommendations on the Performance Grade tab. Make a note of those numbers, as they will improve after this process is completed. Note: W3TC has more features than Quick Cache and will give better grades, especially for caching.
Update 10/9/12: I’ve tested numerous tools since I wrote this post and these are certainly worthwhile (and they’re free):
- GTMetrix (focus on the Page Speed Grad, ignore the YSlow Grade)
- Website Speed Check
- Online apps to test mobile version of your site
Serving Static Content from a Cookieless Subdomain
You’ve probably read that moving static content to, and serving it from, a cookieless subdomain will improve the page load and speed of your blog. One or both of these scenarios will likely apply to you:
- You have decided to go with the more common use of a subdomain with WordPress, moving the images from your Uploads directory.
- You have tons of other static content in your custom theme that can moved to a subdomain. As you can see, my blog sidebar is loaded with images that affected the page load and speed, in addition to the header image. I’ve also seen some pretty creative uses of WordPress, other than blogging, where images not included in the uploads directory result in a sluggish site.
A cookieless subdomain is the perfect, simple, free solution for any site with lots of images or static content that must load on every, stinkin’, page. The content is still kept on the same server (easy to move), at no extra cost to you (up to 25 free subdomains are included with Godaddy’s Economy Linux hosting plan), and browsers are able to load that content in parallel with the other WordPress files which significantly reduces a blog’s page load time. Its sorta like upgrading from a PC with a single-core processor to one with a dual-core processor. Parallel processing has actually existed since the mainframe (used in Cobol programs). Kudos to the brilliant person who thought of using it with static web content.
UPDATE 5/3/14: Radware reports in their latest testing that big-retail sites using a CDN were actually slower than those NOT using a CDN. However, small to medium sites still benefit tremendously by using a CDN (or cookieless subdomain, the “poor-man’s CDN”).
Note: My immediate need was to move the numerous (optimized) images in my sidebar and header to a subdomain. I chose not to move my WP images (uploads folder) to a subdomain at this time. So, there will be instructions where I’ve done the research and I note what I “BELIEVE” is the correct step for you to migrate your WP images to a subdomain (including helpful links where possible). But since I haven’t followed those steps myself, so you’ll need to verify the steps for yourself (I’ve done most of the leg-work for you). Please leave corrections in the comments so I can update this post (there haven’t been any, so far).
Before you get started on the subdomain, you need to ensure that your blog points to the domain at www.yoursite.com and not to the top level yoursite.com (the subdomain can’t be cookieless if your site points to the top level).
To check on this, go to your WordPress Administration panel, then Settings, General, and see if your home page and home url are set to www.yoursite.com. If yes, you can continue to the next section, Creating the Cookieless Subdomain. If no, you will need to go through the following steps, a process that was written by WordPress.
Note: You should perform this process at a time when guests are least likely to be in the blog, as this will knock them out of the blog until you’re finished).
Changing your root level url to domain level url (www.) in WordPress
- Before you do anything, Backup your WordPress database.
- Instructions Per WordPress,
- Log in to your blog.
- Go to the Administration > Settings > General panel.
- In the box for WordPress address (URI): change the address to the new location of your main WordPress core files – “www.yoursite.com”
- In the box for Site address (URL): change the address to the new location, which should match the WordPress (your public site) address (URI) – “www.yoursite.com”
- Click Save Settings. Do nothing else in the blog.
- Next you need to change the site URL temporarily in your theme’s functions.php file. Without this temporary change, you will not be able to navigate through the blog (its still looking for the url without “www.”). If you do not have a functions.php file in your theme, you’ll need to create one.
Follow the 5 steps in this WordPress doc in the “Edit functions.php” section to add two temporary lines of code, save it, and upload it to your server. This will allow you to navigate through your site. Once you are able to work with your blog, do not forget to remove or comment those two temporary lines of code in the functions.php file, and re-upload it to your server (or if you had to create a functions.php file for your theme, remove it.)
- Next, if you are using Permalinks, go to the Administration > Settings > Permalinks panel and update your Permalink structure by simply re-Saving them.
- Paths in your database entries to images and other files need to be updated to add the “www.” But don’t worry, there’s a plugin for that. I used the Velvet Blues Update URLs plugin, which worked flawlessly. Follow the installation instructions, update the urls, then deactivate and delete the plugin.
- Go to your Settings, Media page and make sure your uploads are going to the domain at www.yoursite.com …
Note: If you are moving your image Uploads directory to a subdomain, you’ll be redoing the Media path again later.
- WordPress lists one last step that depends on your theme:
“If your theme supports menus, links to your home page may still have the old subdirectory embedded in them. Go to Appearance::Menus and update them.”
Your blog is now correctly pointing to the www domain.
Creating the Cookieless Sudomain
- Login to your Godaddy Account, Go to Web Hosting, Launch.
- In the Hosting Manager, Hosting Details (Home) page click Domains, Configure Hosted Domains.
- Click the site domain link, click Add Subdomain
- In the Add Subdomain window, enter the subdomain name you’ve chosen. For example: you can still use “uploads” if you’re moving only WP images, or another subdomain name if you’re moving images plus css, js or other static files and will be adding sub-directories to the subdomain (eg: CDN/uploads,CDN/CSS,CDN/JS).
Leave the Folder option set to “Same as Subdomain …”
Click OK. Your subdomain request will be in pending status for a while (est. 15-30 minutes).
- Click the Refresh button after a while, until the status says Setup.
- Exit Godaddy.
Now we need to set the cookie domain for wordpress:
- Copy the define statement as shown in this document under the heading, “Setting up cookieless domains in WordPress”.
- Open your wp-config.php file and paste the statement somewhere after the first define statement in wp-config.php.
- Change the site domain to your “www … ” domain.
- FTP the file to your server.
At this point you will use an FTP client to copy and paste (not “move”) your images to the new subdomain directory. In my case, I only needed to move the sidebar, header and footer images to my subdomain. However, if you will be using the subdomain as the new location to store your WordPress post images, you will copy the images from your original WordPress uploads directory (or the location you named in your WordPress media setup) and paste them into your new subdomain (or if you also moved other static files, to the appropriate sub-directories within the subdomain). For now, you should leave a copy of the files in the old locations to make for a smooth transition.
Note: Now that all future image uploads in WordPress will be to the cookieless subdomain, there will be a tabbed page called “CDN” in the W3TC settings coming up that you will need to complete.
You must also change all file paths in the blog to your new subdomain location.
Non-wordpress images or static files
All paths to any non-wordpress images that you manually inserted and displayed in your custom theme’s sidebar, header, or footer (as in my case) and other css/js or other static files you may have moved must be changed. You’ll change them in your custom theme files (sidebar.php, header.php, footer.php, style.css and possibly others). If you’re using a free php editor like Php Designer 2007 Personal, you can do a Ctrl+H (find and replace) to replace-all quickly. If you used text widgets to insert image code in your blog sidebar, you’ll need to update the paths manually.
WordPress post images (the uploads folder)
- Go to the Administration panel in your blog, then Settings, Media. There you will change the path to the folder where the blog stores image uploads. If, for example, you’re only moving your uploads images and you created a “uploads.yoursite.com” subdomain, I BELIEVE that in order to take advantage of the parallel processing you should enter”images” in the field labeled “Store uploads in this folder” and the “Full URL path to files” should be entered as “http://images.yoursite.com”. If you created subdirectories under your subdomain, for example, “static.yoursite.com/uploads” (or “CSS”, or “JS” at the level of “uploads”), then I BELIEVE that you would enter “static/uploads” and “http://static.yoursite.com/uploads” in the full path.
- Everything done to this point will take care of FUTURE image uploads in the blog. Your database still contains image paths for the OLD uploads directory location (reminder: the database update plugin we ran earlier only added the “www.” to your site urls). Now you need to run a SQL query in phpMyAdmin. Don’t worry, this site has an excellent article on doing just that and he includes the query statement you’ll need to run. Don’t forget to modify the query provided with your new path to the subdomain! If you’re moving css and js files and have created subdirectories in the subdomain, you’ll need to modify and run the query for each, new directory created.
- Not done yet. What about all those search engine crawls that contain the old image paths? Well, the same site shows you how to add a RedirectMatch statement to your .htaccess file to take care of that.
That’s it for the subdomain part of the project! Test your site, navigate pages, ensure that images are displayed, right-click on them and check the paths in Properties. If all looks good, the hard part is done. On to the easy part.
Installing and Configuring W3-Total-Cache
First of all, one quick paragraph on choosing between the top two caching programs, W3-Total-Cache and WP-Super-Cache. Yes, I tried other caching plugins. I used Quick Cache for a while, which had decent results right out of the box (default settings were ok). I also tried DB Cache Reloaded and Hyper Cache/Extended but just didn’t see satisfactory results. After reading reviews and forum posts on caching plugins for many hours over several days, I concluded that W3-Total-Cache was the best fit for my situation. It got the best reviews, although super cache was close behind, there was nothing special to do when also using Bad Behaviour, and Godaddy just added a page (in june 2012) on setting it up for use with their shared hosting (although I ended up making some changes that resulted in better performance). I’ll admit, I was curious so I had to give super cache a trial run. But in the end I preferred the configuration options of total cache.
W3TC also updates your .htaccess file to enable gzip compression, which compresses your output to the browser by nearly 80% with the same reduction to bandwidth. I had previously added the gzip deflate statements to my .htaccess file to enable compression (manual process that is recommended with Quick Cache), but W3TC’s compression statements are much more advanced than anything I’ve seen and Pingdom Performance results will show you the benefits.
Alright, let’s get started.
First, go to the W3-Total-Cache WordPress Installation page and follow every step, exactly as written (fyi: After activation, you’ll need to go to the Performance tab under Settings, then General Settings. The developer’s instructions need updating.).
Next: Some of the settings will now be changed or added. These settings are the best combination of the recommendations of the plugin developer and numerous articles on the plugin, including a recent article written by Godaddy on installing and setting-up W3TC (written in June 2012. They haven’t written one for Super Cache, yet.), and some adjustments I made to both sets of recommendations that improved performance in my blog (depending on your blog theme and plugins used, you may need to make additional adjustments):
Performance, General Settings
- Page Cache Enabled
- Minify, skip now, we’ll come back to later.
- Database Cache Enabled, Disk
Object Cache Enabled, DiskUpdate – 9/3/12: Enabling object cache caused very long delays when posting: Preview, Save Draft, Publish, Update and Schedule chugged for 15-20 seconds or longer. Disabling object cache reduced that to approx. 5 seconds with no change and even improvements with some testing sites.
- Browser Cache Enabled
- CDN not enabled.
Note: This is not enabled in my case because I only used the cookieless subdomain for the large sidebar images and static files in my blog’s header and sidebar. However, if you are using the cookieless subdomain for WP post images, you’ll need to enable this option and select the Self-Hosted/File Transfer Protocol option.
- Varnish not enabled
- Network Perf … not enabled
- Miscellaneous: Optimized Disk enhanced … enabled, nothing else
- Save all settings
- General: check boxes
- Cache home page
- Cache feeds: site, categories, tags, comments
- Cache requests only for www.yoursite.com hostname
- Don’t cache pages for logged in users
- Skip the rest, Save all settings
- General: check it
- Advanced: 180 seconds, 3600 seconds, skip the rest
- Save all settings
Advanced: 180 seconds, 3600 seconds, skip the rest Save all settings
- General: Check boxes
- Set expires header
- Set cache control header
- Set W3 Total Cache header
- Enable HTTP (gzip) compression
- Do not process 404 errors for static objects with WordPress
- CSS & JS: Check boxes
- Set expires header (31536000 secs)
- Set cache control header (drop-down “cache with max age …”)
- Set W3 Total Cache header
- Check Enable HTTP (gzip) compression
- HTML & XML: Check boxes
- Set expires header (7200 secs). Note: If you have issues with the home page not updating immediately after a new post (for non-logged-in users), and you’ve included the Home Page in your purge setting, deselect this option.
- Set W3 Total Cache header (max-age=EXPIRES_SECONDS, public, must-revalidate, proxy-revalidate)
- Set W3 Total Cache header
- Enable HTTP (gzip) compression
- Media & Other Files: Check boxes
- Set expires header (31536000 secs)
- Set cache control header (drop-down “cache public”)
- Set W3 Total Cache header
- Enable HTTP (gzip) compression
- Save all settings
User Agent Groups
- Manage User Agent Groups: enable both groups, “pass through”, skip the rest
- Save all settings
- Manage Referrer Groups: enable group, “pass through”, skip the rest
- Save all settings
- Set the FTP settings to upload all future post images. Fyi: The FTP login ID/password for your Godaddy host plan is different than your Godaddy account login/password. The “host” is your full domain (www.yoursite.com). Port 21. You may need to setup your FTP account within your Godaddy account.
- Save settings.
Almost finished! At this point you have nearly all of the settings you’ll need, so click the DEPLOY button, then CLEAR ALL CACHES (if the button’s not visible near the top, then go to the Performance menu at the very top and Empty All Caches).
Now open a different browser (if you’re configuring W3TC in Firefox, open IE or Chrome) and be sure to delete all browsing history or empty the cache. Load your blog home page. The initial load of the home page should always take a few seconds. After that, every blog page should load even faster. Some objects remain dynamic and load over a few seconds, like YouTube videos or Google ads. But (excluding the initial page load) the majority of your blog pages should snap to like a soldier!
Fyi: Caching is disabled when you are logged-in to the blog because you need to see everything in real-time (which is why you needed to open a different browser in the last step to view a cached page). However, anytime you create or update a post the cache is updated immediately for your readers to see.
UPDATE 10/3/13: In previous versions of W3TC, minifying any JS files broke the blog layout. I was able to minify the stylesheet. However, minifying the stylesheet in version 0.9.3 break my blog layout, so I am not recommending minifying with this version.
CSS File Management:
Theme: Choose your active theme (should already be selected).
Add a style sheet:
File URI: (here you will enter your theme’s stylesheet, such as:
Template: All Templates
Click Verify URI (your stylesheet will appear in a pop-up. if it looks like your stylesheet, close the window.)
Save all settings. I recommend that your theme stylesheet be the only css file minified. The remaining css files will typically be those belonging to plugins and, from my experience in testing, minifying caused some layout issues.
You are finished configuring W3-Total-Cache with Godaddy Shared Hosting!
Deploy the changes, empty all caches via the Performance link at the top and return to a different browser to test your blog. Navigate fully through all pages, click on the buttons, test features, menus, etc.
- First, go back to the section where you installed the W3TC plugin and began the configuration settings (Installing and Configuring W3-Total-Cache) and verify that you completed every configuration setting from the plugin developer.
- Then go through all the settings that I provided (starting with General Settings).
- If you followed all steps in this page, checking them off as you completed each step, then any issues would have to be related to your custom blog theme and the way it is affected by one or more of the w3TC configuration settings.
Troubleshoot (as you do with plugin conflicts) by disabling one setting at a time and retesting. I’d recommend starting by working backwards through the steps because minifying can cause strange issues; go to the General tab and disable Minify, then clear all caches, return to the “different” browser and reload the page (you may also need to clear the browser cache). If that didn’t fix your issues, continue backwards one setting at time disabling anything that was previously enabled (don’t change other entries, drop-downs) until you find the culprit.
- If you still have issues, the next logical step would be to check for plugin conflicts. Deactivate one plugin at a time, rechecking for the issues you had. If you find a plugin is in conflict with the caching plugin, contact the developers of both W3-Total-Cache and the conflicting plugin.
- Finally, if you’re unable to resolve the issue, you may not be able to use the W3-Total-Cache plugin.
ZenCache/QuickCache is a surprisingly simple plugin that gives pretty great results. The developer says the default settings apply to 95% of WordPress installations. So this list of instructions is intentionally short:
- Install the ZenCache/QuickCache plugin from the Admin panel and activate it. The default settings are ok.
- Add this code to the end of your .htaccess file in the root of your blog. This code will compress files that are sent to your browser using the highly recommended gzip, which is then unzipped in any browser.
- Upload the .htaccess file to your blog app root.
- Test your site.
Note: The initial page load is longer than all subsequent page loads.
Final Test Results
Now that your cache plugin set-up has been completed successfully you should rerun the tests and compare results. Remember to use the same static page you used in the initial tests.
Load Impact: Reminder – You should have seen a rising or exponential graph in the initial tests. Now you should expect to see a relatively flat graph (the blue line) where the load is more evenly balanced.
Which Loads Faster? Choose “Try my own matchup”; enter your blog domain on one side and another blog on the other. Then record the results that pop-up at the end. Be sure to compare to the same blog now that you used at the beginning of the project. You should expect to see an even greater difference between sites (of course the content in both blogs has changed, but still a greater difference).
Web Page Test: Select the same city location that you used at the beginning of the project. When the test is complete, click the Waterfall graph to see details. Record the Load Time and compare it to the load time before the project.
Pingdom: Check the Performance Grade results, the fraction and the numbers on the tab page. All should have shown a significant improvement. Check out our site’s excellent results after applying the previous instructions, configuring W3TC (version 9.2.5), using a cookieless subdomain, and applying the additional optimization tips to follow. Notice the large size of our home page at 2mb. We have loads of images on our home page, but it loads in under 2 seconds!
Note: On the Performance Grade tab you will see recommendations on areas to fix. Click the dropdown arrow on the right of each recommendation to see a list of items. At this point, most of the recommendations listed should be beyond your control: plugins, affiliate ads you may have on your site, traffic stats services, etc.
Additional Optimization Tips
Reducing image size is important, especially if you have the same group of images that load in the header and sidebar on every page load (images you’ve added manually, not those embedded in posts or pages). A check of your test results in Web Page Test (one of the online test sites I recommended) will show you that image files take the longest to load, next to Youtube videos. Gif files are usually the smallest in size, then png files, and jpg/jpeg is always the largest. You can save roughly 50% by converting a jpg file to png 256 colors or gif and notice little difference. You can locate the image loading hogs in Web Page Test (the long blue bars are typically large image loads) and then load the individual images in an online image optimizer. There are many to choose from; I use Dynamic Drive’s free image optimizer. It displays all of the results for you to inspect. Typically, the first remake is the best, and if you’re converting jpg to png 256 or gif you’ll save roughly 50%. Simply right click on the image choice and save it.
On the same subject, before you save and upload a file into your blog posts (because hotlinking is bad!), consider the original size. A large image that is reduced by your selection in the upload steps (large, medium, small, thumnail) gets its display size down to what you need in that post, but the browser still has to download it in it’s original size. So pass on the 600 pixels wide image and look for the smaller version. Or, if you don’t have Photoshop or another expensive image editing app just paste the pic into Windows Paint, resize it in pixels with the aspect ratio maintained and save it. You’ve just cut down your page load time, again.
If you have the same success that I had with this blog, you should see a significant improvement in the speed of your blog page loads, as well as an improvement in test results. Please take a moment to leave a comment after this page if you had success with all or part of the process, or if you have issues or questions. Good luck!