One of the most powerful features of WordPress is the ability to create Custom Post Types (CPTs). One of the questions that often arises when creating a CPT is whether the permalink (URL) slug should be singular or plural.
e.g. Should the CPT slug be recipe
or recipes
# plural
http://ferrarello.com/recipes/guacamole
#singular
http://ferrarello.com/recipe/guacamole
Yet another option, I’ve seen used is to use the plural on the archive page and singular on the single page, which at first glance does appear to have some appeal.
WordPress CPT Slugs Should Always be Plural
The answer is
WordPress Custom Post Type slugs should always be plural whether the URL is for the single post or archive the page, as they make the URL more useable.
e.g.
# Archive Page for Recipes
http://ferrarello.com/recipes/
// Single recipe
http://ferrarello.com/recipes/guacamole
Mixing Singular & Plural Does Not Work
Initially websites were static creations consisting of files and directories. WordPress and other CMSes intercept these requests for files and directories and generate content based on rules and data from the database. If this were a static site you could take a URL like http://ferrarello.com/recipes/guacamole
remove the final element (/guacamole
) and get a new URL higher up in the tree (http://ferrarello.com/recipes
). This establishes a consistent slug (either singular or plural) should be used rather than using one for a single page and a different slug for the archive page.
Jakob Nielsen writes about this idea when he advocates for
URLs that are “hackable” to allow users to move to higher levels of the information architecture by hacking off the end of the URL
Why Plural and Not Singular
It is an established best practice when creating a directory of images to name it (/images
) making a URL like https://example.com/images/funny.jpg a common sight. On the other hand, using a singular slug for an archive page, e.g. https://example.com/image, is illogical and against common best practice.
Consistent Plural CPT Slug
This leaves us with a consistent plural Custom Post Type slug as the best choice when constructing a WordPress CPT permalink.
Exceptions
There are exceptions when you can get away with using a singular CPT slug. Specifically, if your CPT does not include an archive page it would be acceptable to use a singular slug, however,
- I would recommend you include an archive page whenever possible
- even in the case where you do not have an archive page, I do not see any harm in using the plural form of the CPT slug
Other Custom Post Type Information
If you’re interested in some other thoughts on creating WordPress Custom Post Types, see my post WordPress CPT Best Practices.
I’ve gone back and forth on this in various projects. This is a clear, concise explanation. Thanks!
Always reassuring to find out I’m not the only one who wrestled with this. Thank you.
I would love to hear your thoughts on using custom post types for services.
When I create a CPT to display services offered, I always use both plural and singular.
For example:
/services/
will display all services offered
/services/heating/
will display all heating services offered
/services/heating/furnace
will display all furnace services offered
However, I think it’s getting out of hand to go a step further with:
/services/heating/furnace/furnace-replacement
So, when we get to the singular service, I like to change it to:
/service/furnace-replacement
Each page adds value to the customer and is not just a boring and plain archive page. It seems to work with the search engines and is easy to navigate.
What do you think? Is there a better way?
Hi Matt,
Based on your example, I assume your using a hierarchical custom post type, where you can set one of your posts as a parent for another post and do this multiple levels deep.
I find I seldom use hierarchical posts, generally preferring to organize the posts through tags (by using custom taxonomies).
In your situation, I can imagine two taxonomies (one for heating/cooling and the other for the type of unit, e.g. furnace).
Then through either custom code (or a plugin like FacetWP), you can setup filtering of these services based on the terms assigned in the taxonomies.
Of course if what you are doing works for you, I don’t see any reason you need to change it. It is always good to see how different developers address different challenges.
Thanks for your comment.