I Doubled my Income in a Year

WordPress allowed me to get a better job & better projects in just a Year. I will give you tips, tricks and guide you into WordPress development so you can get more income. Sign up to my 7-day email course!

Custom WordPress Rewrite Rule to Combine Taxonomy and Post Type

WordPress permalinks are great for having friendly urls that your visitors can also remember and that benefit your SEO optimization. Some solutions will require you to have an url made of a combination of different content. In this tutorial we will look how to have a custom taxonomy and also append the custom post type slug to the end of it.

Reason for a Custom WordPress Rewrite Rule

Let’s look at a scenario to better understand the reason for this. We have a custom post type Resources that also needs a custom taxonomy Type so that we can categorize them under different types of resource. We will display the resources under their category. When our visitors visit an url www.yoursite.com/resources, they will get a list of resources that are categorized as Featured.

If our visitor visits another url such as www.yoursite.com/resources/e-books they will get a list of all our resources of type e-books.

So, you do get it right? Our main slug in the url is actually a slug for the taxonomy and not our post type. But, when our visitor clicks on an e-book, they will get to an url such as www.yoursite.com/resources/e-books/my-new-book.

The my-new-book is a slug for our Resource.

Let’s learn now how to accomplish that.

The Custom Post Type

Our custom post type will be a resource_post_type. This ensures that the WordPress does not look for the post type when on url /resources/. We will create our own custom WordPress rewrite rule to handle our resources.

The only part that interests us here is the taxonomies key that defined a relationship with a taxonomy. Let’s make that taxonomy now.

The Custom Taxonomy

The taxonomy will be registered for our post type Resource. We will also add a rewrite rule immediately when registering it. This will ensure that the WordPress does look for the taxonomy Resource Type when visiting the url /resources/.

The WordPress rewrite rule is created under the parameter rewrite. Now we have the url structure set for our taxonomies to be displayed when visiting resources/ and any sub page such as resources/e-books.

The Custom WordPress Rewrite Rule

Now we need to get on the business and create the WordPress rewrite rule to handle third level slugs such as resources/e-books/my-new-book.

We are hooking our function resources_cpt_generating_rule to the filter generate_rewrite_rules. This filter will be called when flushing rewrite rules. I recommend you go to Settings > Permalinks and just save them once again to flush the rewrite rules.

When our WordPress rewrite rule is being generated, we are getting all our terms from the Resource Type taxonomy. Even those that do not contain any resource relationship. Do take note that you will have to save the permalinks when creating a new taxonomy term, just in case.

Once we get all the terms, we iterate through all of them and create a WordPress rewrite rule for each. The rewrite rule will say something like this:

When you visit resources/e-books/my-new-book, get the third level slug my-new-book and set the query string to look for a post type resources_post_type with the slug (name) my-new-book.

The Custom Post Type Link

So now we have the url structure all set with our new WordPress rewrite rule. But what happens when you save that Resource? The link that is generated once we save our new Resource will be something like resources_post_type/my-new-book. This is not right.

It should be resources/e-books/my-new-book. This can be done using the filter post_type_link.

Here we are checking if the post is of type resources_post_type. This will ensure that we create a different post link only for our Resources. We get all the terms from our custom taxonomy, but only for the current Resource.

While we iterate through all of them, we escape the slug featured because this is just a secondary type. You don’t have to do that, but if you have a secondary type, don’t include them for the link. Use only the main one.

When we set a term slug, we break out of the loop. We then create a permalink structure that follows our custom WordPress rewrite rule and return it from that filter.

Now you also have a good structured link when saving your Resource.

Conclusion

In this tutorial we have learned how to create custom WordPress rewrite rules and also make a relationship between different content in the url structure. This could benefit the SEO also but more importantly, your visitors will have a really friendly url for the resources they want to see or read.

About the Author Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

follow me on:

EDD for Developers

In less than 2 weeks, I have earned $1,800 by working on a custom solution with Easy Digital Downloads without any prior experience. Let me teach you how you can too with various custom solutions.

Get the eBook

Leave a Comment:

15 comments
Iñigo N. says March 21, 2017

Good post, it’s very interesting

I have a problem with this from the permalink. How can I make the permalinks show me this route: resources/e-books/history/my-new-book and this other route: resources/e-books/history/modern/my-new-book
I’ve been looking for the solution for a few days but I still have not found anything, I would appreciate your help.

Thanks.

Reply
    Igor Benic says March 22, 2017

    Hi Iñigo, I am glad you like the article!

    You could use the similar code I have written there, but you would need to have some more loops. You can loop through the terms (parent) and then also get the children terms from each parent. Then you can loop through them and set them like this in the code.

    You could try something like this: https://gist.github.com/igorbenic/3ba41de1db69bf028651e98b4615cfee

    Reply
Iñigo N. says March 22, 2017

Hi Igor,

Thank you very much for your answer

I have tried the new code and it does not work for me, it still does the same thing as before but now the single- {resources_post_type} .php gives 404 error, I have updated the permalinks but nothing.

My structure is:
– Category 1
– Category 1.1
– Category 1.1.1
– Resource 1
– Resource 2
– Resource 3
– Category 1.1.2
– Resource 4
– Resource 5
– Resource 6
– Category 1.1.3
– Resource 7
– Resource 8
– Resource 9
– Category 1.1.4
– Resource 10
– Resource 11
– Resource 12
– Category 1.2
– Resource 13
– Resource 14
– Resource 15
– Category 1.3
……
– Category 2
– Category 2.1
……
– Category 2.2
……
– Category 2.3
……

With your code when i go to:
category 1 -> resources/categoria-1/ OK
category 1.1 -> resources/categoria-1-1/ ERROR should be resources/categoria-1/categoria-1-1/ and projects of category 1.1.1
resource 1 -> resources/categoria-1-1-1/resource-1/ ERROR should be resources/categoria-1/categoria-1-1/categoria-1-1-1/resource-1/ and return error 404

Any ideas?
Thank you very much for your help.

Reply
    Igor Benic says March 22, 2017

    I have changed the post type into ‘resources’ instead of ‘resources_post_type’. If you change the $post_type back to resources_post_type, would that work? What post type slug are you using?

    Reply
Iñigo N. says March 22, 2017

I have this code in functions.php:

https://gist.github.com/igorbenic/3ba41de1db69bf028651e98b4615cfee#file-request-php

Reply
    Igor Benic says March 22, 2017

    I have edited your comment with the link to the code so that we don’t waste space here if other readers want to read the comments.

    I will have to get back to you later today or tomorrow on this since this is something I have to create and test.:)

    Reply
      Iñigo N. says March 22, 2017

      Thanks a lot.
      In github it is much cleaner

      Reply
        Igor Benic says March 27, 2017

        I have wrapped it a little: https://gist.github.com/igorbenic/3ba41de1db69bf028651e98b4615cfee#file-solution-php

        This will work for the category/resource-content

        For something like category/category-2/resource-content, I would need a little more time on this to check. This is a little harder to achieve because WordPress then won’t know if category/category-2 is a resource or a resource_type since category/resource-content is also possible.

        That is why even core WordPress won’t give you the ability to have category-1/category-2

        Reply
Iñigo N. says March 27, 2017

Hi Igor,

thanks for your help, I did not get what you said either, the core of wp is closed with this theme.
I have managed to make it work but I do not think it is a correct solution because it does not recognize the single-{post-type} and i need to use templates to show the single post.

https://gist.github.com/igorbenic/3ba41de1db69bf028651e98b4615cfee#file-request2-php

Thanks

Reply
    Igor Benic says May 3, 2017

    You should check what is wrong with it, which template does it include. I assume this could actually see the pages as taxonomies and not singular pages. That is why I said it’s a bit hard to get two categories one below the other. If for some pattern you would like to look at it as a singular page (single-{post-type}.php), then you should maybe exclude the taxonomy slug in the rewrite rule.

    Reply
Gareth says June 20, 2017

Hi Igor, great tutorial! I have been looking for something like this for a while now and I have my permalinks working perfectly thanks to what you have done.

Here is my question. In your tutorial you have the resources page set to show only featured resource types. What if I wanted to use a proper resources-archive template with pagination? At the moment I am having to create a page called “resources” and give that a template with a custom WP_Query object on it but it would be better if I could bring the default archive functionality into play.

Thanks

Reply
    Gareth says June 27, 2017

    Never mind, think I worked it out. I set “has_archive” to true for the CPT then I wrote a header redirect that redirects the default slug (example.com/resource_post_type) for the post type to “example.com/resources” and then wrote a rewrite rule that fetches the correct post type when on that url.

    So now all of the following work:

    http://www.example.com/resources/e-books/my-new-book – loads the correct post
    http://www.example.com/resources/e-books – loads a taxonomy archive of all posts with a resource type of ebook
    http://www.example.com/resources – loads all posts that are resource custom posts

    Really pleased with this! One of those things I’ve been meaning to get to grips with for ages and thanks to this article was finally able to crack it!

    Reply
      Igor Benic says June 28, 2017

      Thank you, Gareth for the kind words. I am really glad you liked the tutorial and that it has helped you. Also, thank you very much for the examples you have posted here with explanations on what you have achieved with it!

      I am sure it will help others who stumble upon this:)

      Reply
Kabolobari says September 5, 2017

Hi, Igor, thanks for the post. I did implement it on a project (still local) that I’m working on.

I however ran into a bit of trouble. With “The Custom Post Type Link” example used and edited to fit my parameters, I no longer have the ability to edit the slug, the remaining part with the post name, in fact, WordPress does not automatically write out this part. So that except, I manually edit the slug field from the Screen Options settings then I have no complete url for a post and then I get 404.

I wonder if my explanation is clear enough and I wish I had a way to post screenshots and code to you.

Could you guide? Thanks.

Reply
    Igor Benic says September 7, 2017

    Hi Kabolobari, when setting a custom post type link, WordPress “thinks” you won’t have to edit the slug anymore since you’ve set it programmatically. That’s why you aren’t able to edit it anymore.

    A plugin such as “Custom Permalinks” (https://wordpress.org/plugins/custom-permalinks/) could enable the editing once more. Feel free to look at that code if you don’t want another plugin installed and see how they enable that.

    Reply
Add Your Reply

Custom WordPress Rewrite Rule to Combine Taxonomy and Post Type

by Igor Benic time to read: 3 min
Complete course to Become a WordPress DeveloperJoin the Course
+