Trying to do something with the rewrite argument on custom post types.

I'm after 2 different things here for 2 different custom post types.

1: Slugs which look like this


So the URL will be something like


2: More or less the same but with the ID


So the URL will be something like


I'm sure this is pretty easy to do

1 Answer 1


Yes, it's not hard to do that.

  1. Just register your post type and enable rewriting for that post type, i.e. set rewrite to true.

  2. Once registered, modify its permalink structure like so:

    global $wp_rewrite;
    $wp_rewrite->extra_permastructs['<post type>']['struct'] = '<your structure here>';
  3. Use the post_type_link filter to replace rewrite tags like %post_id% in the permalink URL.

    If you need to use custom rewrite tags like %post_date% in the permalink structure, you can add the custom tags using add_rewrite_tag(), after you set the structure.

  4. Remember to flush the rewrite rules (i.e. re-save your permalinks) every time you changed the rewrite args, including when you simply set rewrite to true or false.

    You can programmatically flush the rules using flush_rewrite_rules(), however, it should only be used when necessary, e.g. upon plugin activation.

    As for the non-programmatic way, simply visit the Permalink Settings admin page without having to click the "save" button.

Working examples for you

  1. This is for the structure post-type-1-slug/post-name-year-month-day where a sample URL might look like https://example.com/type1/hello-world-2023-02-20/, and I'm using a custom rewrite tag %post_date% for the year-month-day part. (It's up to you if you'd rather use multiple tags, e.g. %year%, %monthnum%, and %day%)

    add_action( 'init', 'my_register_type1_cpt' );
    function my_register_type1_cpt() {
        register_post_type( 'type1', [
            'public'   => true,
            'label'    => 'Type 1',
            'rewrite'  => true,
            // other args
        ] );
        global $wp_rewrite;
        $wp_rewrite->extra_permastructs['type1']['struct'] = 'type1/%type1%-%post_date%';
        // Add a structure tag for dates in either of these form: 2023-02-20 or 2023-2-20.
        add_rewrite_tag( '%post_date%', '(\d{4}-\d{1,2}-\d{1,2})' );
        // If you use %year%, %monthnum%, %day% and/or %post_id%, then those are core
        // structure tags in WordPress, hence you do not need to add them manually.
        // However, you still need to manually replace them in the permalink URL!
    add_filter( 'post_type_link', 'my_type1_post_type_link', 10, 2 );
    function my_type1_post_type_link( $post_link, $post ) {
        if ( $post && 'type1' === $post->post_type ) {
            $post_date = wp_date( 'Y-m-d', strtotime( $post->post_date ) );
            return str_replace( '%post_date%', $post_date, $post_link );
        return $post_link;
  2. This is for the structure post-type-2-slug/post-name-id where a sample URL might look like https://example.com/type2/hello-world-123/ with 123 being the post ID.

    add_action( 'init', 'my_register_type2_cpt' );
    function my_register_type2_cpt() {
        register_post_type( 'type2', [
            'public'   => true,
            'label'    => 'Type 2',
            'rewrite'  => true,
            // other args
        ] );
        global $wp_rewrite;
        $wp_rewrite->extra_permastructs['type2']['struct'] = 'type2/%type2%-%post_id%';
    add_filter( 'post_type_link', 'my_type2_post_type_link', 10, 2 );
    function my_type2_post_type_link( $post_link, $post ) {
        if ( $post && 'type2' === $post->post_type ) {
            return str_replace( '%post_id%', $post->ID, $post_link );
        return $post_link;

Note: %type1% and %type2% are the post name/slug and you don't need to replace it manually, i.e. WordPress will do that for you.

  • 1
    Wonderful, thanks for that, works perfectly Feb 20, 2023 at 9:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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