Skip to content

How we built

Posted on in Engineering

After reading and enjoying Mark Jaqueth’s How I built “Have Baby. Need Stuff” post, I thought it would be fun to write one of our own. Without further ado, here’s how we built

A screenshot of the homepage

This post is a technical overview of how we built the site, we also have a case study with more details.

What we didn’t do

The site was designed by the talented folks at Syndicut and the majority of the HTML & CSS was handled internally by Yell, lots of kudos to everyone else involved.

Getting organised

We hosted the code for the site in a private GitHub repo (we love GitHub and use it for everything). Internally Yell use SVN so for releases we have to deploy from Git to SVN, more on that later (hint: we don’t use git-svn).

For project management and bug tracking we used Yell’s existing Jira setup with the wonderful Iker Larranaga as scrum master. We don’t use Jira internally but it’s something we find larger clients often bring with them to the project, over all I like it, it’s hugely flexible and powerful, so much so that you really need someone who’s sole responsibility is tending to it.

As with 99% of our projects we used Skype for our day to day communication, we set up a group chat, gave it a name and I then favourited it so it was pinned at the top of the sidebar.

WordPress in Git

We built Yell before we really got to grips with having WordPress as a Git submodule so we just had the whole of WordPress in our Git Repo, yuk!

Here’s the .gitignore file:

We committed the live, staging and an example dev wp-config.php files to Git as wp-config-live.php, wp-config-staging.php & wp-config-dev.php, same for .htaccess, then on the servers we just symlinked the correct ones into place. Because all the updates would be handled through a defined release process we didn’t want people seeing update nags so we removed them with using the following code:

Carrington Build

The homepage and the bulk of the product pages are managed using the fantastic Carrington Build from Crowd Favorite, we’ve used it before on a smaller project so it was interested to see how it worked on a site of this size.

It’s what allows Yell’s content team to produce such varied product page layouts without having to write a single line of code. Here’s a short screencast of me using it.

We wrote 18 custom modules to cover all the various parts of the product page layouts, all in all Yell created around 100 different pages out of those 18 modules. Without Carrington Build it would be very difficult to get layout flexibility whilst keeping all the content editable. The alternative would have been some mix of page templates, shortcodes, metaboxes and likely would have still required some html knowledge on the part of the editor, not ideal.

Here’s an example product page annotated with how we broke it down in various Carrington Modules:

Along the way we sent several feature requests and a couple of bugs Crowd Favorites way, which, to their credit, were implemented and released very quickly.

Content manage everything

In addition to using Carrington Build to allow the complex product pages to be easily content managed we also worked hard to make every other part of the site easily editable through the WordPress admin as well. We used WordPress Menu’s for the main and footer menus and several widget areas for the various sidebars in the blog section and footer.

We used a simple custom post_type for the promos (internal ads which can be dropped into the middle of pages to highlight some related section of the site), editors simply upload an image and add a url and a title.

The design of the Category archive pages required us to add some custom fields to the default edit term page, in addition to title, slug, parent and description we added the ability to define the header image. Because the sidebar on each category archive page needed to be controlled individually we decided to move the sidebar widget management to the category edit page as well, the Widget admin in WordPress falls down when there are lots of sidebars or widget content needs to be controllable per page.

Underneath we stored all this extra category meta data in a termmeta table. Include the following code in your site and then define add_theme_support( 'term-meta' ); in your function.php to enable term meta, it’s forward compatible so if support for term meta is ever added to core it will start using the core implementation.


The site is hosted internally on Yell’s own servers, servers which, as external suppliers, we don’t have access to. In addition to a set of 6 production servers there is also a Yell controlled QA server which all changes are tested on prior to release. On top of that we maintain a dev site which we can use for testing changes before they are pushed to Yell’s QA environment.

All the day to day coding happens in our private GitHub repo, thats setup so that the dev site auto pulls every commit – here’s the rough script which does that:

Once we are happy that everything is ready for release it’s time to push all the changes to the Yell SVN repo (we used codespaces). To achieve this I simply have my local version of the site running in both git and SVN, with the .git and .svn folders hidden from each other, pre SVN 1.7 this was a pain because of the need for a .svn folder in each directory, thats all gone with SVN 1.7 though, now it works just like git with one folder in the root of the site.

Originally I tried to use git-svn however the lack of support for handling git submodules made this impossible. We use the same process with WordPress plugins so that they can be stored in git for day to day development but still use SVN for releases.


We don’t use W3 Total Cache. Unfortunately due to Yell’s server setup we couldn’t get APC or memcache installed (we wanted APC for opcode caching and memcache for object caching), instead we rely wholly on Varnish with a year long ttl on all assets and a 10 min ttl on html, we don’t bother doing any purging as content changes are never that time sensitive.

Here’s an example of our WordPress vcl file:

The actual ttl’s are set as HTTP Expires headers, that way they are used by both Varnish and proxy/browser caches. Here’s the rules we used in the httpd.conf

There are many more things we did which I’d love to cover, but this post is already too long, things like a popular posts widget powered by Google Analytics data, or the custom exporter which pipes Gravity Forms data into Yell’s internal Oracle customer database or the scalable related posts code. I’ll leave those for another post.