I want clean URLs without a custom taxonomy name or custom post name. The project and its structure are somewhat complex. The customer wants certain strings from a third party plugin to be removed from the URLs. I achieved this that way:

function append_query_string($url) {
    //check if the URL contains sortiment/(.+) or getraenke-entdecken/(.+) and replace it with ''
    $url = preg_replace('/(sortiment|getraenke-entdecken)\/(.+)/', '$2', $url);
    return $url;
add_filter('post_type_link', 'append_query_string');
add_filter('post_link', 'append_query_string');
add_filter('category_link', 'append_query_string');
add_filter('term_link', 'append_query_string');

Basically I want both of the following URL Structures to work:

  1. /{custom term title}/{custom post title}
  2. /{category title}/{post title} (<- Thats core behaviour)
  3. /{page title}/{page title} (<- Thats core behaviour)

I tried a lot of approaches, but all end up getting too complex or priducing 404 Errors all over the place. It should be possible with a somewhat complex SQL manipulation thing. But since it seems to be possible for the WordPress Core, I would like to do it the way WordPress does.

What makes my brain explode is: In WordPress core it does work. WordPress can determine between URL #2 and #3. But everywhere the behaviour of WordPress is explained to be: The first rewrite rule gets matched.

I have debugged a bit and I just cant understand how it works but magically. Here are two sets of url and the matched regex and the query thats run:

URL: 'unternehmen/unsere-neuprodukte'
Regex: '(.+?)/([^/]+)(?:/([0-9]+))?/?$'
Query: 'category_name=unternehmen&name=unsere-neuprodukte&page='

URL: 'unser-unternehmen/geschichte'
Regex: '(.?.+?)(?:/([0-9]+))?/?$'
Query: 'pagename=unser-unternehmen%2Fgeschichte&page='

If I'm not completely lost right now, that should not be possible. Both URLS can match both rules, so both should actually match the same rule since the rules are iterated over until the first match. Please tell me what I'm missing. Am I really that brain-blocked right now?

1 Answer 1


I dont know how I missed out on that while looking for aproaches, but I have a working solution now based on this answer.

I modified it to check for slashes in $query->request, if there is none I first look for my custom post type (get_posts() with'slug' => $query->request). If no post is found I do the same for the taxonomy (get_terms()). If there is one slash, I explode the $query->request to $parts and look for a custom post with 'slug' => $parts[1] and a tax_query array for the custom taxonomy. Whenever something is found I do something like:

$new_query = array(
    'post_type' => 'my_post_type',
    'name' => $name
$query->query_vars = $new_query;

If nothing is found the query is untouched, and in the end I just return $query;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.