Bits & Babble

A blog in development.

Remove Subcategories from WordPress Permalinks

September 28, 2014  

WordPress has great flexibility when it comes to specifying your permalink structure. I had a request come in recently, however, to use only the topmost category in the permalinks for a site. The settings did not seem to allow this, so I had to find a way to remove subcategories from WordPress permalinks.

No Code

You can get the permalink structure to use just the top-level category, but it requires active participation of the authors, and would require you to edit all existing posts. If you’re starting a brand new site, you can use /%category%/ for the permalink structure. However, with every post, you’ll need to select the subcategory for the post and it’s top-most parent category. WordPress will then be able to find the post by either permalink, with or without the subcategory in the URL.

This is a perfectly acceptable solution, if you have complete control over every post and don’t mind ensuring every parent category is selected on those posts. And if you don’t mind the answering the inevitable question when an author forgets to tick that top-most level category.

Remove Subcategories from WordPress Permalinks, Every Time

To ensure the subcategories are removed without user intervention, we’re going to have to get our hands dirty. With PHP. Get it? I already did a bit of Googling, and found this StackOverflow post, which gave me a handle on the overall approach. So my hands are dirty here, too.

Let’s take a look at the code.

functions.php
raw download
add_filter( 'post_link', 'my_filter_post_link' );
 
function my_get_all_child_categories( $category_id ) {
 
  $subcategories = array();
 
  $category = get_category( $category_id );
  if ( $category->parent ) {
    $subcategories[] = $category->slug . '/';
    $results = my_get_all_child_categories( $category->parent );
    $subcategories = array_merge( $subcategories, $results );
  }
 
  return $subcategories;
}
 
function my_filter_post_link( $permalink, $post, $leavename ) {
 
  if ( 'post' != get_post_type( $post ) )
    return $permalink;
 
  switch ( $post->post_type ) {
    case 'post':
 
      $categories = get_the_category( $post->ID );
      $subcategories = array();
 
      foreach ( $categories as $category ) {
        $results = my_get_all_child_categories( $category->term_id );
        $subcategories = array_merge( $subcategories, $results );
      }
 
      $permalink = str_replace( $subcategories, '', $permalink );
 
      break;
  }
 
  return $permalink;
}

add_filter( 'post_link', 'my_filter_post_link' ); function my_get_all_child_categories( $category_id ) { $subcategories = array(); $category = get_category( $category_id ); if ( $category->parent ) { $subcategories[] = $category->slug . '/'; $results = my_get_all_child_categories( $category->parent ); $subcategories = array_merge( $subcategories, $results ); } return $subcategories; } function my_filter_post_link( $permalink, $post, $leavename ) { if ( 'post' != get_post_type( $post ) ) return $permalink; switch ( $post->post_type ) { case 'post': $categories = get_the_category( $post->ID ); $subcategories = array(); foreach ( $categories as $category ) { $results = my_get_all_child_categories( $category->term_id ); $subcategories = array_merge( $subcategories, $results ); } $permalink = str_replace( $subcategories, '', $permalink ); break; } return $permalink; }

We’re going to need to hook into the post_link filter and do a little bit of recursion. Evaluating the filter hook function, we can see we’re limiting our logic to basic post types. We then use our custom my_get_all_child_categories function to get an array of child category slugs with their trailing slashes.

Once we have all the subcategories in an array, we can simply use str_replace to clean up the post permalink.

Violà! We now completely remove subcategories from WordPress permalinks!

6 Comments

By SPENCER SOKOL
  • About
  • Twitter
  • Studio 27

Categories

  • Alloy
  • Android
  • Appcelerator Titanium
  • Babble
  • Debugging
  • Genesis
  • iOS
  • s2Member
  • Woocommerce
  • Wordpress

About Spencer Sokol

Spencer co-founded Studio 27, a small web and application design and development company in Indianapolis. He has spent many years in both the development and testing side of the software industry, and generally avoids talking to people face to face.

Comments

  1. Jamie Poole says

    November 20, 2014 at 6:59 am

    Thanks for this article – works nicely.

    However, how do you then change the permalink in the actual Post Edit page to reflect the new URL structure?

    Reply
    • Spencer Sokol says

      November 20, 2014 at 8:19 pm

      Oh, you may need to go to Settings > Permalinks and save the settings. (You won’t have to change anything. Clicking save just forces a refresh). Let me know if that fixes it.

      Reply
  2. Younis says

    August 16, 2017 at 6:14 pm

    I tried in my website https://downiz.com but the subcategories not removed

    Reply
    • Spencer Sokol says

      October 17, 2017 at 12:25 pm

      Oh, you may need to go to Settings > Permalinks and save the settings. (You won’t have to change anything. Clicking save just forces a refresh). Let me know if that fixes it.

      Reply
  3. Kamal Choudhary says

    October 17, 2017 at 11:13 am

    Hey … Thanks for great tutorial … I removed the subcategory using first method….

    But I want to use 2nd method and I don’t know where we should paste the code?

    Please let me know how to do it. Thanks!

    Reply
    • Spencer Sokol says

      October 17, 2017 at 12:25 pm

      Probably in your functions.php of your theme. You could also create a plugin, but that may be overkill.

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • About
  • Indianapolis Design & Development
Copyright © 2022 Spencer Sokol

Copyright © 2022 · Bits and Babble on Genesis Framework · WordPress · Log in