• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Mastodon GitHub Twitter (inactive)
You are here: Home / Programming / Prefix WordPress Custom Post Type Names

Prefix WordPress Custom Post Type Names

Last updated on July 15, 2016 by Sal Ferrarello

When you call the register_post_type() function to register a custom post type, the first parameter is a unique string to identify the post_type you’re creating. Since this string needs to be unique, it is a bad idea to use a string that others might use (e.g. book).

If another plugin does try to register the same “unique” custom post type, things break. It is bad when things break so please use a prefix on your post type. Below I’ll walk you through the URL problems that occur when you use a prefixed post type and how to fix them.

Register a WordPress Custom Post Type

Here we are registering a custom post type, without prefixing the post type string. This is a bad idea.

While the URLs look good, we are using a post type of book which has a high probability of collision (i.e. another plugin using the same post type).

Do NOT use this code

function fe_register_cpt_fe_book() {
    $args = array(
      'public' => true,
      'label'  => 'Books',
      'has_archive' => true,
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'fe_register_cpt_fe_book' );

Now when I create an example post called “Anathem”, I have the following:

  • http://example.com/book/anathem/ (Single Post Page)
  • http://example.com/book/ (Archive Page of CPT book)
  • http://example.com/wp-admin/edit.php?post_type=book (wp-admin page listing book posts)

Register a Prefixed WordPress CPT

Here we are going to use a prefixed post type name, which is good. Unfortunately, this has a negative impact on our URLs.

Do NOT use this code either

function fe_register_cpt_fe_book() {
    $args = array(
      'public' => true,
      'label'  => 'Books',
      'has_archive' => true,
    );
    register_post_type( 'fe_book', $args );
}
add_action( 'init', 'fe_register_cpt_fe_book' );

You’ll notice the only thing I’ve changed is the first parameter for register_post_type(), I’ve changed book to fe_book.

This results in the following URLs.

Note: If you’re trying this at home, you’ll have to recreate the Anathem post because WordPress will no longer find it (since the previous post was type book rather than fe_book).

  • http://example.com/fe_book/anathem/ (Single Post Page) Problem
  • http://example.com/fe_book/ (Archive Page of CPT fe_book) Problem
  • http://example.com/wp-admin/edit.php?post_type=fe_book (wp-admin page listing fe_book posts)

You’ll notice I’ve marked two URLs as problems. We don’t want our public facing URLs to have fe_book. We would rather have books in the URL.

Register a Prefixed WordPress CPT with Rewrite

Here we use a prefixed post type and use the rewrite parameter to get the URLs we want.

This is the solution we want

function fe_register_cpt_fe_book() {
    $args = array(
        'public' => true,
        'label'  => 'Books',
        'has_archive' => true,
        'rewrite'     => array(
            'slug' => 'books',
        ),
    );
    register_post_type( 'fe_book', $args );
}
add_action( 'init', 'fe_register_cpt_fe_book' );

You’ll notice this time we added rewrite with a slug of books to the $args array.

This results in the following URLs.

  • http://example.com/books/anathem/ (Single Post Page)
  • http://example.com/books/ (Archive Page of CPT fe_book)
  • http://example.com/wp-admin/edit.php?post_type=fe_book (wp-admin page listing fe_book posts)

Bonus Points for Plugin Authors Filtering the Slug

If you are going to be distributing your code, I strongly recommend you add a filter to the slug. This allows a developer to programmatically override your URLs, without modifying your code.

'slug' => 'books',

becomes

'slug' => apply_filters( 'fe_rad_book_plugin_slug', 'books' ),

where fe_rad_book_plugin_slug is a name that uniquely identifies your plugin (and ends in slug). If two custom post types both try to use the same slug, they won’t work properly. However, with this filter, we can easily change the slug and correct the collision.

Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit

Filed Under: Programming Tagged With: CPT, WordPress

Reader Interactions

Comments

  1. Mark Tenney says

    March 11, 2019 at 12:56 pm

    This is a great article! I’ve been building custom post types for the last year or so, and this article along with another article (https://salferrarello.com/cpt-best-practices/) were very helpful!

    Quick question:

    At the end of this post, you mention adding a filter to your CPT slug so it can be customized without modifying the plugin code. Do you have any other articles or resources that explain how to leverage that entirely? I’d love to add a field to the permalinks settings area where my client could change the slug of their CPT.

    Thanks!

    Reply
  2. Mwale says

    March 20, 2023 at 4:43 pm

    Fantastic article, thank you!

    Reply

Leave a Reply Cancel reply

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

Copyright © 2023 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in