Setting Up Custom Category URL Structures in ExpressionEngine
We just finished up a particularly fun project, Casillas, Inc. They’re an amazing custom furniture maker in California. In an odd turn of events, we actually did very little design for the site and became the “backend guys” if you will. As we got into how we wanted the site to be structured we realized that because of the product names (all numbers) we needed to use the category that the product was part of in the URL structure. So for example it would read:
http://site.com/products/sofas/10-123/
And if the user accesses:
http://site.com/products/sofas/
Then all the sofas get shown. Back one more and all the categories. Great! Now how in the world do we do that with ExpressionEngine?
First Problem
By default, EE uses either the category ID number to display all the entries in that category:
http://site.com/products/C12
Or you can turn on URL titles and choose your “trigger” word. So if category was the trigger the URL would be:
http://site.com/products/category/sofas
Hence, we need to figure out how to remove the category trigger.
Second Problem
We want the URL title of the entry (the product number in this case) to immediately follow the category name. And we want that URL scheme to be the permanent location of the product. Because this isn’t how EE works out of the box, there is potential to trip us up down the road and make it hard to create those permalinks reliably. Can we do it? You bet we can!

The Solution
As you can see in the diagram above, we’re going to harness the power of segment variables to make our magic happen. What are segments? Well, it’s pretty easy. Segment 1 is the first section in your URL after your .com, Segment 2 is the next and so on. EE will handle up to 9! I hope I hope I never have to use that many.
First, we need to setup our template group (products in this case) and then on the index template inside that group we begin our work. We’re actually going to manage to put all of this in one template using if statements. Yep, that blew my mind the first time, too. Keep in mind that all this code has been stripped down to bare minimum to keep it easier to follow. My template code for this page was pretty large with all the HTML markup in it.
We’ll start with the categories page:
{if segment_2=="" AND segment_3==""}
{exp:weblog:categories weblog="products" style="linear"}
<p><a href="{path="products/{category_url_title}"}">
{category_name}</a></p>
{/exp:weblog:categories}
Here we tell EE that if Segment 2 and 3 are empty, we use this part of the template. Then we use the weblog:categories tag to list the categories and make them links.
Second is the category entries page:
{if:elseif segment_2!="" AND segment_3==""}
{exp:query sql="SELECT cat_id FROM exp_categories WHERE
cat_url_title = '{segment_2}'"}
{exp:weblog:entries weblog="products" category="{cat_id}"}
<p><a href="{title_permalink={segment_1}/{segment_2}}">
{title}</a></p>
{/exp:weblog:entries}
{/exp:query}
Here we continue the if statement by saying that if Segment 2 has something in it and Segment 3 is empty we use this part of the template. Add to that a little SQL Query magic to pull the category ID from the category URL and then you can start making your links to the products. Notice you need to pass the category ID to the weblog loop and then you can use the title permalink in conjunction with the first two segment variables.
And finally the single entry:
{if:elseif segment_3!=""}
{exp:weblog:entries weblog="products" limit="1"
url_title="{segment_3}"}
Call whatever custom fields you have here
{/exp:weblog:entries}
{/if}
If Segment 3 is populated then we look for the entry inside it and pull the data. It gets more complicated after that to use permalinks and title paths, but we didn’t run into an issue we couldn’t get past. And don’t forget, you can go to http://casillasinc.com/products/ and click around to see how it works. Also, before you think I’m a mad genius or something, this is based on some excellent work by a guy named “TheStig” in the EE forums. The only credit I can take is for making it a little easier to understand
.
Due to line breaks and such I’ve put all of the above together for you in one file so it will be easy to get started. Have fun!
Download: the template code.
Edit: Be aware that next/previous linking and pagination won’t work with this method. For next/previous linking this might help: Nearby Entries
1
.(JavaScript must be enabled to view this email address)
Jun 13, 2011
.(JavaScript must be enabled to view this email address)
Jun 13, 2011
3
.(JavaScript must be enabled to view this email address)
Jun 13, 2011
.(JavaScript must be enabled to view this email address)
Jun 14, 2011
5
Ian Ryde
Sep 11, 2011
.(JavaScript must be enabled to view this email address)
Sep 12, 2011
7
Ian Ryde
Sep 12, 2011
8
.(JavaScript must be enabled to view this email address)
Nov 16, 2011
9
William
Dec 22, 2011
.(JavaScript must be enabled to view this email address)
Dec 22, 2011
11
.(JavaScript must be enabled to view this email address)
Dec 23, 2011
12
.(JavaScript must be enabled to view this email address)
Apr 16, 2012
13
.(JavaScript must be enabled to view this email address)
May 01, 2012
.(JavaScript must be enabled to view this email address)
May 01, 2012
15
.(JavaScript must be enabled to view this email address)
May 07, 2012