How to Change the Slug of a Post Type in WordPress
The slug of a post type is a string that identifies the post type in web addresses.
Problem
If URL rewriting is enabled for a post type, WordPress by default uses as slug the identifier of the post type. On the other hand, best practices recommend that post-type identifiers should be prefixed to avoid conflicts.
The result is that URLs generated for the post type look ugly and are not easy to remember. Consider a post type registered as 'ns_book_cpt'
:
- https://example.com/ns_book_cpt/ is the URL to access the post type archive
- https://example.com/ns_book_cpt/book-1/ is the URL to access an entry of the post type
Solution
Specify a new slug using the 'slug'
member of the 'rewrite'
attribute when the post type is registered in WordPress. For completeness and if it makes sense in your scenario, customize the 'query_var'
attribute too.
Example
The following code registers the custom post type Book. The identifier of the custom post type is 'ns_book_cpt'
, but its slug is set to 'books'
and the query variable is set to 'book'
.
/*
* Registers the custom post type Book.
*/
function ns_register_book_cpt(){
// See all possible labels in the PHPDoc of the function get_post_type_labels
$labels = array(
'name' => __('Books', 'ns'),
'singular_name' => __('Book', 'ns'),
'menu_name' => __('Books', 'ns'),
'all_items' => __('All Books', 'ns'),
'add_new' => __('Add New', 'ns'),
'add_new_item' => __('Add New Book', 'ns'),
'edit_item' => __('Edit Book', 'ns'),
'new_item' => __('New Book', 'ns'),
'view_item' => __('View Book', 'ns'),
'view_items' => __('View Books', 'ns'),
'search_items' => __('Search Books', 'ns'),
'not_found' => __('No books found.', 'ns'),
'not_found_in_trash' => __('No books found in Trash.', 'ns'),
'archives' => __('Book Archives', 'ns'),
'filter_items_list' => __('Filter books list', 'ns'),
'items_list_navigation' => __('Books list navigation', 'ns'),
'items_list' => __('Books list', 'ns')
);
// See all possible attributes in the PHPDoc of the function register_post_type
$args = array(
'label' => __('Books', 'ns'),
'labels' => $labels,
'public' => true,
'exclude_from_search' => false,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_nav_menus' => true,
'show_in_menu' => true,
'show_in_admin_bar' => true,
'hierarchical' => false,
'supports' => array('title', 'editor', 'author'),
'taxonomies' => array('post_tag'),
'has_archive' => true,
'rewrite' => array('slug' => 'books'),
'query_var' => 'book'
);
register_post_type('ns_book_cpt', $args);
}
add_action('init', 'ns_register_book_cpt', 10, 0);
Since the post type Book is registered specifying a custom slug, URLs generated for the post type will have the following form:
- https://example.com/books/ —URL of the post type archive
- https://example.com/books/book-1/ —URL of an entry of the post type
Issues
If you get a “Page not found” error when you try to visit a book or an entry of any other custom post type, apply this procedure:
- Open the administration area
- Go to the Settings menu
- Go to the Permalinks submenu
- Click the Save Changes button
Further reading
I recommend the other tutorials in this series to learn more about post types in WordPress.
- Post Types in WordPress
- How to Register a Custom Post Type in WordPress
- How to Register a Custom Post Type Using a Plugin in WordPress
- How to Unregister a Custom Post Type in WordPress
- How to Modify a Post Type in WordPress
- How to Change the Slug of a Post Type in WordPress
- How to Check if a Post Type Exists in WordPress
- How to Get the Registered Post Types in WordPress
- How to Get the Attributes of a Post Type in WordPress
- How to Get the URL of a Post Type Archive in WordPress
- How to Add Custom Post Types to the Main Query in WordPress
Source code
The source code developed in this tutorial is available here.
Comments