I want to get this link structure mysite.com/sa/post-slug/post_id/ on my custom post-type.

This is the post_type:

// ex_article Post type
add_action( 'init', 'ex_article_init' );

function ex_article_init() {
    $args = array(
        'labels' => array(
            'name' => _x( 'Article', 'Post type general name', 'textdomain' ),
            'menu_name' => _x( 'Ex Article', 'Admin Menu text', 'textdomain' )
        'public' => true,
        'show_ui' => true,
        'hierarchical' => false,
        'rewrite' => array('slug' => 'sa', 'with_front'=>false ),
    register_post_type( 'ex_article', $args );

On permalink setting, I use Post Name : mysite.com/sample-post/. Using a custom structure is not an option for me, I need to avoid it, and also it does nothing to custom post type.


1 Answer 1


It's quite easy, actually:

  1. Change the generated permalink structure so that it ends with the post ID and not the post slug (but it still contains the post slug):

    // After you registered the post type:
    register_post_type( 'ex_article', $args );
    // .. run this code:
    global $wp_rewrite;
    $wp_rewrite->extra_permastructs['ex_article']['struct'] = 'sa/%ex_article%/%post_id%';
  2. Then replace the post ID placeholder (%post_id%) in the generated permalink URL with the correct post ID:

    add_filter( 'post_type_link', function ( $post_link, $post ) {
        if ( $post && 'ex_article' === $post->post_type ) {
            return str_replace( '%post_id%', $post->ID, $post_link );
        return $post_link;
    }, 10, 2 );

And don't forget to flush/regenerate the rewrite rules! Just visit the permalink settings page without having to click on the "save" button.

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.