I created a custom post type:

register_post_type('sample_post_type',array(
    'labels' => array(
        'name' => _x('Sample Posts', 'post type general name'),
        'singular_name' => _x('Sample Post', 'post type singular name')
    ),
    'public' => true,
    'show_in_nav_menus' => false,
    'exclude_from_search' => true
));

How can i disable the single post view for this specific post type? Displaying a simple 404 is fine, or redirecting to the homepage. This is inside a plugin, so i can't create a single-sample_post_type.php file to setup an empty page.

up vote 31 down vote accepted

You can use template_redirect hook to redirect for a custom post type, you can use any other URL you want to in place of home_url() and the error code in other argument.

<?php
add_action( 'template_redirect', 'wpse_128636_redirect_post' );

function wpse_128636_redirect_post() {
  $queried_post_type = get_query_var('post_type');
  if ( is_single() && 'sample_post_type' ==  $queried_post_type ) {
    wp_redirect( home_url(), 301 );
    exit;
  }
}
?>

Updated:

A alternative approach would be to set 'publicly_queryable' => false while registering the custom post as mentioned by @gustavo earlier. But that will just give you 404 directly, it'd hide single as well as archive, basically completely hidden from front-end and can be set for custom posts only.

  • A good solution. I found it was helpful to only perform this redirect for non-authenticated users, by checking to see if get_current_user_id() evaluates to 0. – RevNoah Jun 29 '15 at 13:25
  • 2
    Please check the answer form @Gustavo – Richard Nov 18 '16 at 9:17
  • 1
    why not use only is_singular('post-type-slug') in the if() condition instead of 2 conditions? – Akash K. Oct 22 at 20:36
  • @AkashK. Yeah that can work as well, wasn't aware of the function. – sven Oct 23 at 6:26

Just setting the argument

'publicly_queryable'  => false

when you call register_post_type()

  • This looks like the answer to stop your CPT from creating actual web pages while still creating all database references. – TR3B Sep 17 '15 at 18:11
  • 22
    This hides archive too – spaceman Oct 11 '16 at 16:12
  • 1
    By far the best approach, thanks :] – Trebblez Mar 2 '17 at 19:12
  • Really helpful, thanks! – dungey_140 Jun 21 '17 at 8:40
  • This should be the accepted answer. – SinisterBeard Mar 16 at 10:26

A simpler way to do that can be passing the following args when registering the Custom Post Type

register_post_type('sample_post_type',array(
'labels' => array(
    'name' => _x('Sample Posts', 'post type general name'),
    'singular_name' => _x('Sample Post', 'post type singular name')
),
'public' => true,
'exclude_from_search' => true,
'show_in_admin_bar'   => false,
'show_in_nav_menus'   => false,
'publicly_queryable'  => false,
'query_var'           => false
));
  • 1
    You would actually need publically_querable to be true for Post Type Archives to work. – Howdy_McGee Nov 12 '14 at 19:42
  • This does not work for me. It justs redirects back to the homepage when trying to go to the archive – Yahya Uddin Jul 15 '15 at 15:51

One. From your functions file.

add_action( 'template_redirect', 'redirect_cpt_singular_posts' );
    function redirect_cpt_singular_posts() {
      if ( is_singular('your-cpt-slug') ) {
        wp_redirect( home_url(), 302 );
        exit;
      }
    }

Two. From your single.cpt.php file:

<?php wp_redirect( home_url() ); exit; ?>
  • I liked second option. But I need to know is there any drawback with this second option. – user2584538 Oct 10 '17 at 6:27
  • @user2584538 If you don't have a custom single-cpt_name.php file you could not do it. If you put the function in a simple plugin file, you could activate/deactivate without editing any file. – EliasNS Feb 5 at 10:12

Working from of Sven's really good answer, I rewrote his function to make it easier to add multiple post types using in_array() in the if statement and then redirecting to the archive page instead of the home page.

(by the way, I think the setting query_var and/or publically_queryable to false will disable not only the single views, but also the native archive view, overriding 'has_archive' => true. In that case you can still set up a custom WP_query and create your own archive page, in a template, but the main query won't do that any more, will it?)

function fq_disable_single_cpt_views() {
  $queried_post_type = get_query_var('post_type');
  $cpts_without_single_views = array( 'my-post-type', 'my-other-post-type' );
  if ( is_single() && in_array( $queried_post_type, $cpts_without_single_views )  ) {
    wp_redirect( home_url( '/' . $queried_post_type . '/' ), 301 );
    exit;
  }
}

add_action( 'template_redirect', 'fq_disable_single_cpt_views' );

Tested all the ones mentioned above and the actual solution is simpler than any redirects suggested.

In order to have archive be accessible and list the items, and single post not be accessible and auto redirect to 404 set

'query_var' => false

when registering your CPT. If you set publicly_queryable to false your archives will be redirected to home, any other combo wont work. Set the query_var to false and that is it.

Here is full CPT https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a

see line 50 https://gist.github.com/danyj/bfd038d3c8d578548c4d700bd0a7942a#file-thz_cpt_items_single_view_redirect-php-L50

as stated here

https://codex.wordpress.org/Function_Reference/register_post_type

Note: If query_var is empty, null, or a boolean FALSE, WordPress will still attempt to interpret it (4.2.2) and previews/views of your custom post will return 404s.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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