I have a custom post type 'news' and a taxonomy 'category-news'. I would like to get this permalinks:

    www.domain.com/news -------------> list of all news
    www.domain.com/news/sport -------> list of all sport news
    www.domain.com/news/sport/post --> the post
    www.domain.com/news/2014 --------> list of all news of year 2014
    www.domain.com/news/sport/2014 --> list of all sport news of year 2014
    www.domain.com/news/page/2 ------> second page of pagination news
    www.domain.com/news/sport/page/2 -> second page of pagination sport news

is it posible? How can I do it?


  • This is a common question here and no definite answers. This is the best post I found on it: wordpress.stackexchange.com/questions/39500/…
    – gdaniel
    Commented Mar 2, 2014 at 1:48
  • Is the year the publish date or a custom meta? Do you also want news from the month and day? Commented Mar 2, 2014 at 2:15
  • Hi, the year is the publish date. And yes, I would like news from the month and day. Commented Mar 2, 2014 at 11:18
  • Any ideas, please? Commented Mar 3, 2014 at 10:22
  • I'm working on a solution based on what I've done before, but its a bit tricky. Commented Mar 3, 2014 at 16:02

2 Answers 2


Here is some code I've cooked up based on some code I've already been working on. My original code works okay, however I haven't tested this code because I haven't seen your code. Here is what you need to do:

  1. on your post type definition, set the rewrite argument to false

  2. Put the following code after your post type code:

    //Create Permalink for news posts
    function wpse136458_create_permalink( $permalink, $post, $leavename, $sample ) {        
        $rewritecode = array(
            $leavename? '' : '%postname%',
            $leavename? '' : '%pagename%',
            //Add custom permalink tags here
        if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
            $unixtime = strtotime($post->post_date);
            $category = '';
            if ( strpos($permalink, '%category%') !== false ) {
                $cats = get_the_category($post->ID);
                if ( $cats ) {
                    usort($cats, '_usort_terms_by_ID'); // order by ID
                    $category = $cats[0]->slug;
                    if ( $parent = $cats[0]->parent )
                        $category = get_category_parents($parent, false, '/', true) . $category;
                // show default category in permalinks, without
                // having to assign it explicitly
                if ( empty($category) ) {
                    $default_category = get_category( get_option( 'default_category' ) );
                    $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
            $author = '';
            if ( strpos($permalink, '%author%') !== false ) {
                $authordata = get_userdata($post->post_author);
                $author = $authordata->user_nicename;
            $date = explode(" ",date('Y m d H i s', $unixtime));
            $cat_news = '';
            if ( strpos($permalink, '%category-news%') !== false ) {
                $news_terms = wp_get_object_terms( $post->ID, 'category-news' );
                if( $news_terms ) {
                    $cat_news = $news_terms[0]->slug;   
            //Enter permalink manipulations here            
            $rewritereplace = array(
                //Add custom tag replacements here
            $permalink = str_replace($rewritecode, $rewritereplace, $permalink);
        return $permalink;      
    add_filter( 'post_type_link', 'wpse136458_create_permalink', 10, 4 );
    //Helper functions
    function struct_to_query( $struct, $post_type_slug ) {
        global $wp_rewrite  ;
        $querycode = array_merge( $wp_rewrite->queryreplace, array( 'paged=', 'feed=' ) );
        $tagcode = array_merge( $wp_rewrite->rewritecode, array( '%paged%', '%feed%' ) );
        $num_toks = preg_match_all('/%.+?%/', $struct, $toks);
        $tokens = $toks[0];
        $query_result = str_replace( $tagcode, $querycode, $tokens );
        $query_string = '';
        foreach( $query_result as $index => $value ) $query_string .= '&' . $value . '$matches[' . (string)( (int) $index + 1 ). ']';
        return 'index.php?post_type=' . $post_type_slug . $query_string;
    function struct_to_regex( $struct ) {
        global $wp_rewrite  ;
        $regexcode = array_merge( $wp_rewrite->rewritereplace, array( '([0-9]{1,})', '(feed|rdf|rss|rss2|atom)' ) );
        $tagcode = array_merge( $wp_rewrite->rewritecode, array( '%paged%', '%feed%' ) );
        return rtrim( str_replace( $tagcode, $regexcode, $struct ), '/' ) . '?/?$';
    function wpse136458_tax_regex( $taxonomy ) {
        $terms = get_terms( $taxonomy, array( 'hide_empty' => false ) );
        $slugs = wp_list_pluck( $terms, 'slug' );
        return '(' . implode( '|', $slugs) . ')';   
    //Creates the complex rewrite rules 
    function wpse136458_rewrite_api() {
        add_rewrite_tag( '%category-news%', wpse136458_tax_regex( 'category-news' ) );
        $structs = array(
        foreach( $structs as $struct ) {
                struct_to_regex( $struct ),
                struct_to_query( $struct, 'news' ),
        //This creates permalinks for news posts
        add_permastruct( 'news', 'news/%category-news%/%postname%/', array( 'walk_dirs' => false, 'endpoints'=>false ) );   
    add_action( 'init', 'wpse136458_rewrite_api' );
    //Flush rewrite rules when adding, removing or deleting terms
    // Taxonomy created
    add_action( 'created_category-news', 'flush_rewrite_rules' );
    // Taxonomy edited
    add_action( 'edited_category-news', 'flush_rewrite_rules' );
    // Taxonomy Deleted
    add_action( 'delete_category-news', 'flush_rewrite_rules' );

I'll post an in depth explanation after work. Let me know if it works for you

EDIT: Okay, here is the basic rundown: wpse136458_rewrite_api is the heart of how this works. It basically creates an array of permalink structures made from rewrite tags that follow the rules you specified, then creates the rewrite rules from those structures, using the helper functions struct_to_query (creates the query string) and struct_to_regex (creates the regex). The first line of the function, which I just added, creates a rewrite tag for your category-news taxonomy and the last line that calls add_permastructcreates a permastruct that WP uses for specific news posts.

wpse136458_create_permalink is a callback to the post-type_link filter that takes that news permalink and fills it in with the right data, like the category and the postname

  • Wow, thanks for your answer. But now I have some problems. www.domain.com/news/2013 works but www.domain.com/news/sports/2013 does not work. Commented Mar 3, 2014 at 21:06
  • I added some code that should make it work now. WordPress doesn't create rewrite tags for taxonomy slugs, so I had to add them to make the permalinks that use category-news work. Commented Mar 4, 2014 at 4:50
  • Hi. Now everything fails: www.domain.com/news, www.domain.com/news/sports, etc Commented Mar 4, 2014 at 20:30
  • Try flushing you permalinks Commented Mar 4, 2014 at 20:54
  • I did it and it fails Commented Mar 4, 2014 at 22:15

You can do this permalink by simply getting a plugin or just using a sample theme which is created to explain about custom post permalink structure and parameters.

many sample codes i tried, but none helped me to solve the issue of setting s permalink for my custom post types, i just used the custom post type permalink plugin , later come to know the custom post type theme.


This may help you.

  • A link-only answer is a bad answer. Please edit your answer and add some details and then add the link to direct them to more details. Commented Mar 5, 2014 at 5:45

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.