Using /%postname% for a custom post type

I have a custom post type whose permalink needs to sit in the same space as pages, like so:

/an-example-thing  <--  custom post type 'thing'
/about-the-things  <--  a normal page

I’m well aware that this isn’t the recommended way to do it, but I don’t really have a choice – that’s what the client has specified.

I’ve created the custom types with register_post_type, and used the Custom Post Permalinks plugin to set their permalink like so:


However, this creates a conflict between the rule that recognises my custom posts, and the one for normal pages – which turns all normal pages into 404s. This problem disappears when the permalink is changed to something like this:


Using the Monkeyman Rewrite Analyser shows that the rule for the custom post is coming first. Even when I try forcing it to use verbose rules:

global $wp_rewrite;
$wp_rewrite->use_verbose_page_rules = true;

the custom post type rule is higher priority than the verbose rules for pages so they still get a 404.

I’d like it to look for things first, and when none is found with that name look for pages. The other way round would be acceptable. Is there no way of persuading it to look for both things and pages before hitting a 404?

Solutions Collecting From Web of "Using /%postname% for a custom post type"

You start with one bonus point for using my rewrite analyzer 🙂

Indeed, even if you use verbose page rules, since version 3.1 (or something around that) the taxonomy rewrite rules come even before that. I recently answered another question with a way to move them really to the top. This should work if you don’t mind having verbose page rules (if you don’t have more than 25 pages or so).

If you don’t want verbose page rules you will have to extend the core WP class so it can deal with “ambiguous” situations where the URL can refer to a page or a custom post type. Mike once provided a nice way to do this. His answer is written for a custom taxonomy, but it should be adaptable to a custom post type too.

I found one solution, but it’s really ugly: hook into 404 routing to deliver the page that should be delivered. The code is bit complicated because I have a multisite prefix to deal with as well.


global $current_blog;
$prefix = $current_blog->path;
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace("!^$prefix!i", "", $path);
$path = preg_replace("!\?.*$!i", "", $path);
$path = trim($path, '/');
$page = get_page_by_path($path);

if (isset($page)) {
  $template = get_post_meta($page->ID, '_wp_page_template', true);
  if (empty($template))
    $template = get_page_template();
...actually handle a 404...

Having identified a page, it has to run query_posts again to load all the data correctly. This is far from the ideal solution, but it at least worked for me. I’d gladly replace it with a better solution if anyone can suggest one.

There are two plugin that address this problem.

This one removes the type slug by adding a specific rule for each custom post type page.

This one seems more advanced, it lets you set up any slug structure you want, but it also is abandoned by the developer.

I got both of them to work, although initially I had to debug with Monkeyman Rewrite Analyzer because some other rules were interfering.