Let me give you a scenario of what I'm trying to do. I have a custom post type "customer" and I can go in and "add new customer". Here I see my custom fields such as name, logo, review, etc. The problem is Wordpress generates a URL for this. This isn't meant to be a page so I just redirect all of my http://website.com/customers/* to somewhere else so that no one goes to these pages (for now).

Is there a way when registering my custom post types in the functions.php file (or some other way) to tell Wordpress to not generate a URL / actual page for it? It's really just a slot to hold my data.

My thoughts were maybe it has to do with: 'capability_type' => 'post', or something similar that I'm over looking.


3 Answers 3


OK, so there are some arguments of register_post_type that you should use.

The crucial arguments for you are:

  • public - Controls how the type is visible to authors (show_in_nav_menus, show_ui) and readers (exclude_from_search, publicly_queryable). If it's false, then exclude_from_search will be true, publicly_queryable - false, show_in_nav_menus - false, and show_ui - false. So the CPT will be hidden all the way.

  • exclude_from_search - Whether to exclude posts with this post type from front end search results. Default: value of the opposite of public argument.

  • publicly_queryable - Whether queries can be performed on the front end as part of parse_request(). Default: value of public argument. So we have to et it true.

  • show_ui - Whether to generate a default UI for managing this post type in the admin. Default: value of public argument.

  • rewrite - Triggers the handling of rewrites for this post type. To prevent rewrites, set to false. Default: true and use $post_type as slug. So we have to set it false.

Below you can find the code:

$labels = array( /*removed for example*/ );

$args = array(
    'labels'             => $labels,
    'description'        => __( 'Description.', 'your-plugin-textdomain' ),
    'public'             => false,
    'show_ui'            => true,
    'rewrite'            => false,
    'capability_type'    => 'post',
    'hierarchical'       => false,
    /* ... Any other arguments like menu_icon, and so on */
    'supports'           => array( /* list of supported fields */ )

register_post_type( 'customer', $args );

This generator maybe helpful, if you don't want to learn all the arguments: https://generatewp.com/post-type/

And the list of all arguments, as always, you can find in Codex: https://codex.wordpress.org/Function_Reference/register_post_type

  • Thanks for your response!! This is actually very very close to what I read earlier on another thread. I followed the same steps, I would have taken my question down since I technically found the answer already but I do like hearing others approaches.
    – danielle
    Mar 16, 2018 at 20:22
  • 1
    You all were right and very useful but I'm choosing yours as the correct answer only because you said what everyone else said plus some more. Thanks again
    – danielle
    Mar 16, 2018 at 20:23

One of the parameters for register_post_type() is publicly_queryable. Simply set this to false to prevent individual page creation. You may also wish to exclude from search, etc.


In the example given in the WP Codex, you can see this parameter is set to true. Depending on your exact needs, you can hide the post type altogether with the public param or control levels of visibility with the explicit parameters, such pas publicly_queryable.


Example code from WP Codex

add_action( 'init', 'codex_book_init' );
 * Register a book post type.
 * @link http://codex.wordpress.org/Function_Reference/register_post_type
function codex_book_init() {
    $labels = array( /*removed for example*/ );

    $args = array(
        'labels'             => $labels,
        'description'        => __( 'Description.', 'your-plugin-textdomain' ),
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'book' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' )

    register_post_type( 'book', $args );

Post Type Archive It is important to note here that setting publicly_queryable to false will also hide the archive page of that post type. In the example code above for the post type book, the archive page at https://yourdomain.com/book would also be removed.

  • I’m pretty sure that the code you’ve posted above doesn’t do the trick. It will register CPT with ‘book’ as slug. Mar 16, 2018 at 19:57
  • That is correct. This is sample code from the documentation. It simply presents an example of the use of the argument.
    – jdm2112
    Mar 16, 2018 at 20:03

will repeat what @jdm2112 said in (hopefully) clearer english and no code at all ;)

Basically what you are looking for is a private CPT. This kind of CPT is useful for storing data in the DB in similar way to posts which gives you the advantage of (optional) still getting the same type of admin interface, and use the same query, meta and term APIs on it.

"Private" is actually a misleading word, it is not that the content is private, but that wordpress will not try to publish it on the front end by itself. You can, if you want to, display the content on the front end but you will need to write the code for that by yourself. In your specific case a simplistic way to do that is to create a page template which displays all the posts in that CPT. This way you have flexible control on the address of the page and whatever SEO you might want to do in it.

Just keep in mind that there is a lot of default functionality you might need to reinvent, and it might be simpler to just have the CPT public, and have a sort of "see more clients" call to action on the single CPT pages.

  • Thanks!!! I actually liked the code because it miniked my custom post type and showed me similar values. Just nice to have a visual representation. And yes I think what you mean is setting public to false instead of true. My post types are all created, its just the fact that we dont use the URL so I just want to ditch it so I can stop writing redirects (the URL goes to a crap page since no template is set)
    – danielle
    Mar 16, 2018 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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