Remove post type slugs from permalinks

⏲️ Time: 2 mins

One question that comes up semi-regularly with my support work for Custom Post Type UI is how to remove the post type slug from a given permalink. While I know that the slug is an important component, I also understand why some people may want to have it removed as well.

Without the slug in place, WordPress will be looking for just posts with the post post type, and thus not find a result to display.

For my tutorial today, I am going to provide some code that will help remove the slug from the generated permalink value as well as help WordPress still query for the post type when it’s making its request.

All of the code can go in your active theme’s functions.php or child theme if you have one of that. Alternatively you could create your own quick plugin or drop the code into a file put in your mu-plugin folder.

Permalink string

For the first part of the code, we will remove the slug from the generated permalink string. We are also only going to do this for published posts in our post type. Our example post type slug is movie and you will need to change that to whatever post type slug you’re removing in your own example.

function cptui_demo_remove_slug_from_permalink_string( $post_link, $post ) {

	if ( 'publish' !== $post->post_status ) {
		return $post_link;

	if ( 'movie' === $post->post_type ) {
		$post_link = str_replace(
			'/' . $post->post_type . '/',

	return $post_link;
add_filter( 'post_type_link', 'cptui_demo_remove_slug_from_permalink_string', 10, 2 );

Query modification

Now that we have the generated link recognized, the next thing to do is make sure WordPress includes the post type in its queries going forward. For that we will make use of the pre_get_posts action hook. This is a very actively used hook so we have multiple guards in place. We do not want this being run if you are in the WordPress admin dashboard and if not on the main query for a given request. Lastly, we need to make sure are querying by post name. If all conditions check out, then we add in our post type for consideration. By default, WordPress is only doing this for the post and page post types.

function cptui_demo_add_post_type_to_query( $query ) {

	if ( is_admin() || ! $query->is_main_query() ) {

	if ( empty( $query->query['name'] ) ) {

add_action( 'pre_get_posts', 'cptui_demo_add_post_type_to_query' );

Once both parts are in place, you may need to visit your permalinks page to flush the rewrite rules, but once done, you should not be receiving any 404 errors for your slug-less post type posts any more.

Adapted from a post made by Kellen Mace.

Michael is a seasoned developer who loves helping build stuff for the internet. He brings over a decade of varied experiences working with both front and back end developer stacks.

His primary focus has been WordPress and PHP and all the components that go along with them. During the day, he is a Support Engineer with Maintainn and WebDevStudios, helping clients get the best that they can out of their own websites.

Categories: Web DevelopmentTags: , ,

3 thoughts on “Remove post type slugs from permalinks

  1. Hey Michael!

    It worked for me.. I used Code Snippet plugin to write the codes so i dont lose them after i update the theme. Just wondering what if i have multiple custom post types? What should the code look like?

    1. Probably need to amend this line:

      `if ( ‘movie’ === $post->post_type ) {` to do extra checks, and make sure to include all the ones you’re adding, to the query portion.

      `if ( ‘movie’ === $post->post_type || ‘tv_show’ === $post->post_type ) {`

  2. Hi Michael!

    I am recreating my WordPress tutorial web site and this time using the Custom Post Type UI (CPTUI) plugin where I made a CPT I called tutorials. As I am updating a bunch of older tutorials I would like to keep the same slug they have had for many years. This meant I had to remove the tutorials CPT slug. Using your tutorial I was able to remove the slug.

    Thank you!

Leave a Reply

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