register_post_type
allows you to specify whether a post is ‘publicly_queryable’
publicly_queryable
(boolean) (optional) Whether queries can be performed on the front end as part of parse_request().Default: value of public argument
Note: The queries affected include the following (also initiated when rewrites are handled)
- ?post_type={post_type_key}
- ?{post_type_key}={single_post_slug}
- ?{post_type_query_var}={single_post_slug}
It doesn’t mention anything about queries of the form ?p=
, and from memory, these will still serve your custom post types event with the publicly_queryable set to false. To prevent this you can hook onto template_redirect
and redirect to a different (404?) page.