Custom Post Types in WordPress 3.x are designed to work from the root of your website i.e. a flat hierarchy.
In a recent project, we created a “Case Study” custom post type and added several new case study posts to our WordPress site.
We also created a page template called “Case Studies” that listed the new custom post types.
Everything was rumbling along just super until we noticed when viewing our new custom post types, the breadcrumb trail and URL permalink weren’t including the Case Studies page that we had clicked through from.
Our Case Studies page URL was /case-studies/ and the breadcrumb trail was also /case-studies/
When clicking on a case study custom post type “Land Owners”, both the URL and breadcrumb trail changed to “/land-owners/”.
Where had the Case Studies page gone in the hierarchy?
Let me be clear, this is not a WordPress bug but rather the way custom post types are currently implemented. And yes, it is very annoying.
WordPress assumes that all custom post types are at the top of the hierarchy. i.e. they have no associated parent.
Unfortunately, this is exactly what we weren’t looking for.
Of course, WordPress may change the way custom post types work in future versions but here’s a fix for now.
We’re going to create a meta box for the custom post type that allows us to enter the ID of a page or post and associate that with the post_parent variable, effectively making that ID our parent page.
We’re using the custom post type called “casestudy” here so change that value to your own custom post type name and copy the following into your functions.php file.
There are three functions here.
- function admin_init() – This initialises the meta box for our casestudy custom post type, pointing to the call-back function that creates it
- function set_case_study_parent_id() – This is the call-back function that contains the HTML code needed to create the meta box on the casestudy custom post type when in edit mode
- function save_case_study_parent_id() – This saves the meta data from the new box into the DB
This will give you the following new meta box on your custom post type, allowing you to enter the ID of a page or post which it will set as the parent document.
We set the meta box value to the ID of our “Case Studies” page which displayed all the custom post types.
Great, now our Yoast breadcrumb trail was picking up the Case Studies parent page from our custom post type, but what about the URL?
There was just one thing left to do to bring everything together.
No slug had been explicitly defined for the custom post type, so they were being displayed in the URL from the server root with just the post title i.e. “/land-owners/”.
We needed to define a slug that would match up with our Case Studies page (slug “case-study”) so that our URL would read “/case-studies/land-owners/”.
Going back into the function that registered our custom post type, we added the following line to the $args array:‘rewrite’ => array(‘slug’ => ‘case-studies’, ‘with_front’ => true)
This rewrites the URL slug from the server root to include “case-studies” in front of the post title.
Just for reference, here’s the complete custom post type registration function with the above line included.
Now our URL matches the breadcrumbs and the Case Studies pages is the parent of our custom post type.
As always, when working with Custom Post Types, navigate to Settings > Permalinks and click on save to regenerate the links for the new post types.