Custom Post Type and Permalink

Since WordPress 3.0 you can use Custom Post Types and you can define your own types of content – it’s more like pages than posts! Thereby you can use automatically the Permalink structure of your WordPress installation. That means, if you create a new post type, you can use Permalinks.

But the Permalinks only work if you recreate the Rewrite Rules of WordPress – that’s why many users initially have problems with it. If you create a new post type you probably get a 404 if you open this page because WordPress doesn’t know the URL-structure in your Permalinks since you didn’t create the Rewrite Rules again.

The easiest way is to safe the Permalink structure in your settings again. Alternatively you can include in your Plugin or Theme the function flush_rewrite_rules(). This enables to create the Rewrite Rules again. Important: Flush rules only on activation or deactivation. Don’t do it on any other hook.





21 responses to “Custom Post Type and Permalink”

  1. Galen Gidman Avatar

    Thanks for the info Frank. I’m going to have to try the custom post types one of these days.

  2. Hristo Avatar

    “The easiest way is to safe the Permalink structure in your settings again”

    Only visiting the Permalink page in the Admin Settings is enough, it flushes the rewrite rules.

    “Alternatively you can include in your Plugin or Theme the function flush_rewrite_rules().”

    Not a good idea because 1. It is too heavy to flush the rules each time a page is visited and 2. This may break other plug-ins’ permalink structure.

  3. Frank Avatar

    Please flush only after include the new custom post type!

  4. Andrew Nacin Avatar

    To clarify: Flush rules *only* on activation (and deactivation). Don’t do it on any other hook.

  5. Danilo Avatar

    Does this apply to custom taxonomies, too? Because I am having trouble with the permalinks of custom category-type taxonomies.

  6. Danilo Avatar

    Well, to answer myself here, yes, it does!
    I was already giving up. Thank you so much for this timely info.

  7. Ethan Avatar

    So to clarify if I wanted to flush after a theme is activated would that be the appropriate place to make the function call?


  8. Jauhari Avatar

    Can you give us real example custom post type?

  9. Jonathan Clarke Avatar

    Can you someone explain how to flush rules suitably from functions.php?

  10. Jonathan Clarke Avatar

    I think I’ve fixed the problem. You just need to add the following line after your register_post_type call:

    flush_rewrite_rules( false );

  11. Karl Haro von Mogel Avatar

    I just tried this out, and it worked beautifully to fix my permalink issues. In my blog theme, I have the custom post type initialized in my functions.php file. I added the flush_rewrite_rules(); function to the file, within the create_my_post_types() function that initializes my custom post type (self-named, not a wordpress function) , but after the register_post_type() function that defines the parameters of the custom post type. confused? Well here’s my code, hopefully this will display properly:

    add_action( 'init', 'create_my_post_types' );

    function create_my_post_types() {
    register_post_type( 'genera',
    'labels' => array(
    'name' => __( 'GENERA' ),
    'singular_name' => __( 'GENERA Entry' ),
    'add_new' => __( 'Add New' ),
    'add_new_item' => __( 'Add New GENERA Entry' ),
    'edit' => __( 'Edit' ),
    'edit_item' => __( 'Edit GENERA Entry' ),
    'new_item' => __( 'New GENERA Entry' ),
    'view' => __( 'View GENERA' ),
    'view_item' => __( 'View GENERA Entry' ),
    'search_items' => __( 'Search GENERA' ),
    'not_found' => __( 'No GENERA Entries found' ),
    'not_found_in_trash' => __( 'No GENERA Entries found in Trash' ),
    'parent' => __( 'Parent GENERA Entry' ),
    'public' => true,
    'show_ui' => true,
    'publicly_queryable' => true,
    'rewrite' => true,
    'exclude_from_search' => false,
    'menu_position' => 20,
    /* Global control over capabilities. */
    'capability_type' => 'post',
    'supports' => array( 'title', 'editor', 'comments', 'trackbacks', 'revisions', 'author', 'excerpt', 'custom-fields', 'thumbnail', 'page-attributes' ),

    in order to see the new permalink structure, you will of course have to have ‘rewrite’ set to => true

  12. Jonathan Clarke Avatar

    Ah, good idea to throw everything into init.

  13. […] you may need to “flush” them). The plugin does flush the rewrite rules on activation as recommended, however some websites seem to require a manual flush.  To do so, go to your admin menu settings […]

  14. Vered Avatar

    Thanx for the post.
    And special thanx to Karl for the example – that’s exactly what I was looking for!

  15. Jared Avatar

    holy crap….i’ve been looking for a solution to this for almost 2 hours and all i had to do was resave my permalink structure….lame-0 but at least I got it fixed! Thanks!

  16. Joe Avatar

    Hi there,

    I’m trying to use this method with custom date meta for my permalink rewrite. I can’t figure out for the life of me why I can’t get around the 404 issue. Ive even added in your flush_rewrite_rules into my code and nothing.

    Settings > Permalink Structure: /%category%/%postname%/

    Here is my function below- it’s working fine for creating the actual permalink but i cannot access the post without getting the 404.


    function calendar_link_filter( $post_link, $id = 0, $leavename = FALSE ) {
    $post = get_post($id);
    if($post->post_type != 'super_duper') {
    return $post_link;
    $date = get_post_meta($post->ID,'event_start_date',true);
    $date = strtotime($date);
    $str = $post_link;
    $str = str_replace('%cal_year%',date("Y",$date),$str);
    $str = str_replace('%cal_month%',date("m",$date),$str);
    $str = str_replace('%cal_day%',date("d",$date),$str);
    return $str;


    add_action( 'init', 'create_my_post_types' );

    function create_my_post_types() {
    register_post_type( 'super_duper',
    'labels' => array(
    'name' => __( 'Super Dupers' ),
    'singular_name' => __( 'Super Duper' )
    'hierarchical' => false,
    'show_ui' => true, // UI in admin panel
    'publicly_queryable' => true,
    'rewrite' => true,
    'public' => true,
    'rewrite' => array('slug' => 'events8/%cal_year%/%cal_month%/%cal_day%'),


  17. David F. Carr Avatar

    I’m looking for help with a similar problem here:

    My plugin code works fine on my site and those of some other users who are happy with it, but I’m also getting isolated reports of 404 errors when people try to use the permalinks.

  18. […] Deaktivierung tun. Mehr Infos zu Custom Posts Types und Permalinks fin­dest du auch im Artikel »Custom Post Types and Permalinks« auf […]

  19. Pippin Avatar

    Do you know why you shouldn’t put it in, say, a function called by an init hook? I’ve been testing it and it seems to work fine . . .

  20. Ken Avatar

    Don’t call flush after the register function. (Many examples above do this.)

    Instead, add two functions, one attached to the “register_activation_hook( __FILE__, ‘activate_cb’ );” which in turn adds an action to ‘init’ (priority 11 just to be sure) and that function in turn flushes the rewrite. Otherwise, you are flushing on every single page load (not good).