Optimise your ExpressionEngine site

ExpressionEngine is widely considered to be one of the most designer-friendly content management systems in use today. Part of the system's appeal is due to it not interfering with your HTML or CSS since it does not require dynamic code (such as the infamous WordPress Loop) to be present on a page. Entire sites can be built using a simple template and group model, or it can be used to display highly dynamic content based on one or more templates: it's your choice.

Having just recently completed and stabilised a tricky update to version 2.0, parent company EllisLab now has its sights set firmly on the future with a revised development pipeline and a new designer on board to optimise the user experience for its flagship CMS.

Many web designers praise the ease of use of the system, and thanks to some excellent documentation, those with limited technical knowledge can deploy sites on ExpressionEngine with relative ease.

Although ExpressionEngine runs very well straight out of the box, you may not be familiar with how to streamline your ExpressionEngine installation, and get every drop of performance out of it. I want to share some practical tips that you can perform on all of your ExpressionEngine sites.

This article refers to the latest stable release of ExpressionEngine at the time of writing: ExpressionEngine 2.2.1, build 20110705.

Uninstalling modules

ExpressionEngine uses a module system that allows it to dynamically load resources at runtime. Features of EE such as RSS, Comments and Channel are modules that must be loaded by the system and initialised by the system before a page can be rendered.

If you're not too familiar with ExpressionEngine, or if you're building your first ExpressionEngine site, you might not be familiar with what modules you need in order to complete your site.

Below is a list of some commonly used modules and scenarios whereby it may be best to remove them. These are not intended to be taken as gospel since each website will have its own unique requirements. If in doubt, leave the module installed.

To install/uninstall a module, login to the EE control panel and navigate to Add-Ons -> Modules.


Part of EE native spam prevention features. Designed to block IP addresses based on content submitted by visitors.

WHEN TO UNINSTALL: If your site does not have a blog or news type channel that accepts comments or any form of input from visitors.


Installed by default. The most widely used module. Allows you to display dynamic content in your templates.

WHEN TO UNINSTALL: Although rare, if you're running an entirely static site based on templates and groups. This does somewhat defeat the purpose of using EE in the first place, but EE will run perfectly fine without it.


Installed by default. Used when implementing contact forms and tell-a-friend functionality.

WHEN TO UNINSTALL: If your site does not use contact forms or if you're using more powerful third party tools such as Solspace FreeForm (Free).


Installed by default. Intercepts user input in comments and replaces character combinations with their respective symbols. For example, :) is replaced with a smiley face image.

WHEN TO UNINSTALL: If your site does not have a blog or news type channel that accepts comments or any form of input from visitors.


Allows you to link to jQuery, jQuery UI and various jQuery plug-ins that are stored within your ExpressionEngine installation.

WHEN TO UNINSTALL: If you are loading jQuery from Google's CDN or a version stored locally on your web server.


Installed by default. Member management system. Allows you to accept member registrations through your website.

WHEN TO UNINSTALL: If your site does not accept or use membership registrations.


Allows you to perform raw SQL queries on the EE database from within your templates.

WHEN TO UNINSTALL: If none of your templates utilise the {exp:query} tag. This tag is prone to abuse by EE novices and is many times left switched on after development.


Allows you to track website link referrals to your site.

WHEN TO UNINSTALL: If you utilise Google Analytics, or another server/frontend analytics package. This module is fairly limited in scope, so a dedicated analytics package will provide more a in-depth analysis of link referrals.


Installed by default. Produces correct content headers for syndicated content such as RSS and Atom feeds.

WHEN TO UNINSTALL: If your site does not provide RSS feeds or any other type of syndicated content.


Installed by default. Allows your visitors to publish/update content in your channels.

WHEN TO UNINSTALL: If your site does not use any 'publish' mechanism to allow site visitors/members to post new or update channel entries. This does not include comments on entries, which is powered by the Comment module.

Installed by default. Allows you to create a search mechanism for visitors to search channel content.

WHEN TO UNINSTALL: If your site does not have a search feature, or if you are using a third party system such as Google or Bing site search.


Installed by default. Lets you display site statistics in your templates such as total members logged in, total entries, last comment date etc.

WHEN TO UNINSTALL: If you are not displaying site statistics in your templates. This feature is heavily geared towards use on forums.

Disable tracking

ExpressionEngine has a little used tracking feature that is enabled by default. It is designed to track the number of times a template is viewed, along with channel entry views and site referrals.

Since this tracking feature is based solely on the number of times an item is viewed, you will find that the numbers produced are of little use. Statistics provided by dedicated analytics packages where visits can be filtered by new and recurring as well as cross referenced with site referrals and organic search results will typically be much more useful than the tracking provided by EE.

Hence, if you are using an analytics system such as Google Analytics, it's best to disable the EE tracking features.

# Navigate to Admin -> Security and Privacy -> Tracking Preferences in the EE control panel.
# Enable Online User Tracking - Set to NO.
# Enable Template Hit Tracking - Set to NO.
# Enable Channel Entry View Tracking - Set to NO.

Delivering content faster

Now we've got ExpressionEngine itself running as fast as possible, we can turn our attention to delivering our web pages as fast as possible. But first a note about serving static assets with EE.

Beware CSS and JavaScript Templates types

Although EE supports it and there are certain scenarios where storing your JavaScript and CSS in EE templates can be useful, you’ll always pay for it dearly in regards to performance.


Consider an ExpressionEngine site that serves a web page that contains an HTML link tag pointing to a CSS file stored in an EE template group. When a browser visits this site, ExpressionEngine will initialise, connect to the database, load necessary modules, parse the URL requested and then serve up the correct template. However, as soon as the browser receives this page, it detects the HTML link tag, and performs another request to that CSS URL. Since most web servers treat each request as a separate thread, ExpressionEngine will need to initialise and perform the same steps again in order to serve the requested CSS template.

Using this technique, ExpressionEngine runs twice for every web page requested and this is assuming you have only used a single CSS file. If you link to ExpressionEngine CSS or JavaScript templates five times in your web page, then EE will run six times due to the initial web template request.

Template caching

Template caching in EE is one of the easiest ways to boost site performance. EE will effectively take the final HTML output for a page and store it as a static file ready for the next request for that page. This form of static caching is the fastest form of caching available and is as close as you can get to serving flat HTML files.

Nonetheless there are tradeoffs to using template caching in EE. Beware of following scenarios where your site will not function correctly if you switch caching on:

  • Member information and conditionals: If your templates display member information or use conditionals based on information about the currently logged in member.
  • Template user agent detection/Browser sniffing: If you have conditional code in your templates based on trying to ascertain the browser or visitor type (for example, mobile and tablets).
  • Displaying highly dynamic modules/API‚ feeds: Although this wont break your site, you will want to be careful if you are utilising an ExpressionEngine add-on that displays content that updates regularly (for example, Twitter/Flickr feed). You'll need to keep the template caching Refresh Interval low in order to let the data displayed update regularly.

If you are not using any of the scenarios mentioned above, or you're aware of the potential problems, template caching can be switched on a template by template basis.

To enable template caching:

# Navigate to Design -> Template Manager in the ExpressionEngine control panel
# Click on Edit Preferences next to the template on which you wish to enable caching.
# In the drop down panel that appears, set Enable Caching to YES and then set refresh interval. The refresh interval will be the number of minutes between the cache being refreshed.

Gzip Compression

This feature is very powerful when combined with template caching above. Gzip compression is the process of taking your HTML page and compressing so that it there is less data to transmit between the server and the browser. When the browser receives the data, it uncompresses it and displays that page as normal.

Some older browsers don't support this feature, but thankfully ExpressionEngine is clever enough to detect them and transmit uncompressed data.

As with most things these days, your server needs to support gzip compression and if it does it will increase the server load slightly since the server will need to compress each page it transmits. This is why offsetting the slight server load increase with a decrease due to template caching is an excellent combination.

To enable Gzip compression:
# Navigate to Admin -> System Administration -> Output and Debugging in the ExpressionEngine control panel.
# Enable GZIP Output - Set to YES.

Template optimisation, disabling PHP

All the opimisation in the world is useless if you have hugely complex templates or processing intensive PHP code residing within them. Your first steps should always be to optimise your templates by simplifying conditionals where possible or breaking parts of the page out into embedded templates.

Removing all PHP from your templates, will also improve template parsing performance. Most, if not all, template PHP code can usually be moved to a plug-in for better performance and to help keep your templates easier to read.

If you're not familiar with ExpressionEngine's plug-in architecture, there is a tutorial on the ExpressionEngine site: expressionengine.com/user_guide/development/plugins.html.

Browser optimisation

Although not strictly an ExpressionEngine only optimisation, this technique is often forgotten by many web developers.

Most site optimisations focus on minimising the amount of time a visitor has to wait between the browser request and server response. Using effective server content-expires headers we can prevent the browser needing to make the browser request in the first place.

Content-expires headers are small bits of information that instruct the browser to hold on to a cached copy of the requested file for a certain amount of time. If we correctly configure content-expires headers for items such as images, then the browser will retrieve them from the cache instead of the web server. This effectively minimises the loading time for these assets to zero as a user navigates around your site.

Due to the way ExpressionEngine generates content headers for web pages, we will only be able to utilise this technique for static assets such as images, CSS and JavaScript files.

Adding the htaccess content-expires rules:

# Create a file called .htaccess in the root folder of your web site. If it already exists, you will simply need to add the code outlined below.
# Add the following code (from HTML5 Boilerplate):

<!--- CODE START --><IfModule mod_expires.c> ExpiresActive on# Perhaps better to whitelist expires rules? Perhaps. ExpiresDefault "access plus 1 month"# data ExpiresByType text/xml "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType application/json "access plus 0 seconds"# rss feed ExpiresByType application/rss+xml "access plus 1 hour"# media: images, video, audio ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/jpg "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType audio/ogg "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/webm "access plus 1 month" # css and javascript ExpiresByType text/css "access plus 1 months" ExpiresByType application/javascript "access plus 1 months" ExpiresByType text/javascript "access plus 1 months" <IfModule mod_headers.c> Header append Cache-Control "public" </IfModule> </IfModule><!--- CODE FINISH -->

You can adjust the amount of time a browser will store an asset by adjusting the values above. In our example we have set the CSS, JavaScript and common assets such as images to be stored for one month.


Although adding content-expires headers to files such as CSS might sound like a great idea, it can cause us problems.

If we were to update the CSS file, and someone were to visit the site with a cached copy of the CSS file, then their browser would not request the newly updated CSS file. They would be completely unaware that they are browsing the site with outdated style information, and might think that your site is broken.

It's for this reason that we recommend only setting content-expires headers once the site is live and development is at a minimum. Even so, there are many legitimate times when you need to update files when a site is in production.

There are several solutions to this problem, but most of them revolve around the idea of cache-busting. Cache-busting is the technique whereby you append a query string to any links you want to control, and simply update this query string whenever you want a browser to update its cache.


Say you have a CSS file linked in your HTML header:

<!--- CODE START --><link href="http://www.mysite.com/css/styles.css" type="text/css" rel="stylesheet" /><!--- CODE FINISH -->

You would update this link with a query string as follows:

<!--- CODE START --><link href="http://www.mysite.com/css/styles.css?t=1311783722" type="text/css" rel="stylesheet" /><!--- CODE FINISH -->

Query strings can always be identified by a "?" followed by some extra information. Links with query strings still request the same file (in this case the styles.css file) but allow you to transmit extra information such as the timestamp in this example.

The query string used in this case is irrelevant, but when a browser requests this CSS file it will be stored in its cache according to its full URL, which includes the query string. If we update the query string, the browser will think that the linked file is an entirely new file, and subsequently request it from the server, donwload it and cache it again.

So using this technique we can easily force browsers to refresh their caches by simply updating the query string.

If you are utilising template caching, you can synchronise the cache-buster to update with your template cache by using a free add-on I developed at Moresoda called moreUtilities. You can find instructions on how to install it on the Github repository page.

Thank you for reading 5 articles this month* Join now for unlimited access

Enjoy your first month for just £1 / $1 / €1

*Read 5 free articles per month without a subscription

Join now for unlimited access

Try first month for just £1 / $1 / €1

The Creative Bloq team is made up of a group of design fans, and has changed and evolved since Creative Bloq began back in 2012. The current website team consists of eight full-time members of staff: Editor Georgia Coggan, Deputy Editor Rosie Hilder, Deals Editor Beren Neale, Senior News Editor Daniel Piper, Digital Arts and Design Editor Ian Dean, Tech Reviews Editor Erlingur Einarsson and Ecommerce Writer Beth Nicholls and Staff Writer Natalie Fear, as well as a roster of freelancers from around the world. The 3D World and ImagineFX magazine teams also pitch in, ensuring that content from 3D World and ImagineFX is represented on Creative Bloq.