Custom post types is a very powerful feature in WordPress 3.0. With custom post types you can easily create post-like objects and automatically have menus, metaboxes, icons, permalinks, and much more added without having to code any of it yourself.
Here we consider custom post type permalinks – how to set it, what the different options mean, and how each of them affects your custom post type permalink structure.
In Custom Post Type Permalinks- Part 2, we consider how to flexibly modify the permalinks to something other than the given defaults. This article gives a more in-depth explanation of WordPress permalinks in general.
In the examples below, we assume our new custom post type is called gallery.
Register Post Type Permalink Options
Permalink behavior can be easily defined in our call to register_post_type. The options in register_post_type that relate to permalinks include –
- publicly_queryable
- query_var
- rewrite
- permalink_epmask
1. publicly_queryable
Defines whether users can query our custom post type from the main blog page. For example, if we set publicly_queryable to true, we can enter –
http://shibashake.com/wordpress-theme?gallery=test-1
This will show the gallery object that has the slug test-1. If publicly_queryable is set to false, then users will get a 404 or file not found error page instead.
2. query_var
Defines the name used in our public query above. query_var defaults to our custom post type name – e.g., gallery.
We can also set our query_var to be something else. For example, if we set the query_var argument to ‘foo’, then our gallery object query will look like this –
http://shibashake.com/wordpress-theme?foo=test-1
gallery=test-1 will no longer work because we have set our query_var to foo.
3. rewrite
Rewrite will add pretty permalink rules for our new custom post type. For example, if we set rewrite to true, then we can access our gallery objects with the following link –
http://shibashake.com/wordpress-theme/gallery/test-1
We can further specify two additional arguments in our rewrite argument –
- slug
- with_front
'rewrite' => array('slug' => 'shiba-gallery', 'with_front' => FALSE)
This means our gallery pretty permalink will now become –
http://shibashake.com/wordpress-theme/shiba-gallery/test-1
with_front determines whether or not to prepend our blog permalink structure in front of our custom post type object. If we set with_front to true and our blog permalink structure is –
/%year%/%monthnum%/%postname%
Then both of the following permalinks will show our gallery object –
http://shibashake.com/wordpress-theme/shiba-gallery/test-1 http://shibashake.com/wordpress-theme/2010/06/shiba-gallery/test-1
4. permalink_epmask
Permalink epmask is a bit more complex, and need not be used in most cases.
epmask stands for endpoint mask.
An endpoint is something that is added to the end of an object permalink. For example, /trackback/ is an endpoint.
Different endpoints are attached to different epmasks using the add_rewrite_endpoint command.
epmasks indicate which type of links an endpoint (e.g. /trackback/) should be added to. epmasks may contain the following values or combinations of the following values (for example if we want an endpoint to be added into several different types of links).
- EP_NONE
- EP_PERMALINK
- EP_ATTACHMENT
- EP_DATE
- EP_YEAR
- EP_MONTH
- EP_DAY
- EP_ROOT
- EP_COMMENTS
- EP_SEARCH
- EP_CATEGORIES
- EP_TAGS
- EP_AUTHORS
- EP_PAGES
- EP_ALL
The permalink_epmask argument allows us to specify which group(s) of endpoints we want to add to our custom post type permalinks. For example, if we set permalink_epmask to EP_PAGES & EP_TAGS then we will associate all endpoints that are linked to pages and tags with our custom object permalinks.
The permalink_epmask argument defaults to EP_PERMALINK. This is the link type for regular posts. I.e., the same endpoints being added to posts will also get added to our new custom post type.
If we do not want to add any endpoints to our new gallery object, then we want to set permalink_epmask to EP_NONE.
If we want to add all endpoints to our new gallery object, then we want to set permalink_epmask to EP_ALL.
Flush Permalink Rules
Note – If you change permalink settings, you may need to flush your previous rewrite rules before the new changes will take effect.
To do this, you want to add the flush_rules function call to your plugin activation and deactivation function.
// add to your plugin deactivation function global $wp_rewrite; $wp_rewrite->flush_rules();
Custom Post Type Permalinks- Part 2 explains how we can fully modify our entire custom post type permalink structure.
yogendra sharma says
I need to know that how do i set permalink for selected category/tag/post. I want to use google news sitemap for one of my entertainment site yetket.com without changing the old permalink for all posts.
BenRacicot says
Great article. Big questions though. I was able to get my first CPT to pretty URLs but my second one 404’s on the page. The perms save correct in edit.php… I CANNOT understand why at this point.
ShibaShake says
Sounds like it could be because of permalink conflicts-
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict
Rico Leuthold says
Excellent – ‘with_front’ => FALSE is exactly what I was looking for. Thanks!
chris says
hey, great tutorials. works well to change the permalink, however with the new ones set up i just get a 404 error. The post edit page shows the new permalink but when I open it, 404 error still.
is there anything i might be missing?
thanks 🙂
ShibaShake says
Sounds like it could be a permalink conflict –
http://shibashake.com/wordpress-theme/custom-post-type-permalinks-part-2#conflict
Michael says
Thanks for this article, helped me fix up the permalinks on my custom post types.
Kirsy says
Hi There! Thanks for the post. I’m kind of a newby with this stuff. Can you tell me where (which .php?) i need to ad this:
global $wp_rewrite;
$wp_rewrite->flush_rules();
Hope you can help me out..
Tnx! Kirsy
ShibaShake says
I usually flush the rewrite rules on my deactivation function – i.e. the function tied to my plugin deactivation hook.