How do you create %post_type%/%postname%/ permalink structure?

This is what is not working:

eg. ( domain.com/blog/ ) -> "click on post" -> ( domain.com/post-name )

How do I make "blog post" permalinks work like this...

eg. ( domain.com/blog/ ) -> "click on post" -> ( domain.com/blog/post-name )

Although other custom post types work?...

eg. ( domain.com/portfolio/ ) -> "click on portfolio piece" -> ( domain.com/portfolio/project )

Also, should I reflush the Permalinks?

Here is the Custom Post Types code & Taxonomies code in my functions.php file:

  // Add Custom Post Type "Portfolio"
register_post_type('portfolio', array(  'label' => 'Portfolio',
'description' => '',
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array('slug' => 'portfolio'),
'query_var' => true,
'supports' => array('title',
'taxonomies' => array('Portfolio Category',),
'labels' => array (
  'name' => 'Portfolio',
  'singular_name' => 'Project',
  'menu_name' => 'Portfolio',
  'add_new' => 'Add Project',
  'add_new_item' => 'Add New Project',
  'edit' => 'Edit',
  'edit_item' => 'Edit Project',
  'new_item' => 'New Project',
  'view' => 'View',
  'view_item' => 'View Portfolio Piece',
  'search_items' => 'Search Portfolio',
  'not_found' => 'No Portfolio Pieces Found',
  'not_found_in_trash' => 'No Portfolio Pieces found in Trash',
  'parent' => 'Parent Project',
),) );

// Add Custom Post Type "Testimonials"
register_post_type('testimonials', array(   
'label' => 'Testimonials',
'description' => '',
'public' => true,'show_ui' => true,
'show_in_menu' => true,
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array('slug' => ''),
'query_var' => true,
'supports' => array('title',
'labels' => array (
  'name' => 'Testimonials',
  'singular_name' => 'Testimonial',
  'menu_name' => 'Testimonials',
  'add_new' => 'Add New',
  'add_new_item' => 'Add New Testimonial',
  'edit' => 'Edit',
  'edit_item' => 'Edit Testimonial',
  'new_item' => 'New Testimonial',
  'view' => 'View',
  'view_item' => 'View Testimonial',
  'search_items' => 'Search Testimonials',
  'not_found' => 'No Testimonials Found',
  'not_found_in_trash' => 'No Testimonials Found in Trash',
  'parent' => 'Parent Testimonial',
),) );

//Add Taxonomy for Portfolio Category
add_action( 'init', 'portfolio_create_taxonomies', 0 );

function portfolio_create_taxonomies()
    //Porfolio Category
    $portfolio_labels = array(
        'name' => _x( 'Portfolio Category', 'taxonomy general name' ),
        'singular_name' => _x( 'Portfolio Category', 'taxonomy singular name' ),
        'search_items' =>  __( 'Search in portfolio category' ),
        'all_items' => __( 'All portfolio categories' ),
        'most_used_items' => null,
        'parent_item' => null,
        'parent_item_colon' => null,
        'edit_item' => __( 'Edit portfolio category' ),
        'update_item' => __( 'Update portfolio category' ),
        'add_new_item' => __( 'Add new portfolio category' ),
        'new_item_name' => __( 'New portfolio category' ),
        'menu_name' => __( 'Portfolio Categories' ),
        'hierarchical' => true,
        'labels' => $portfolio_labels,
        'show_ui' => true,
        'query_var' => true,
        'rewrite' => array('slug' => 'portfolio-category')

EDIT: I think this problem is occuring because of a template heirachy issue the blog page is using "index.php" when it should be using "template-blog.php" file.

  • Just select the %postname% permalink structure, and when you're on a post within that custom post type, it will display both in the url.
    – chris_s
    May 3, 2012 at 16:13
  • Unfortunately that is not the case. I just tried that "%postname% permalink stucture however. As I'm finding when I click on a blog post it goes from domain.com/blog to domain.com/hello-world ?
    – Josh
    May 3, 2012 at 16:23
  • I'm not sure I'm following you then. Do you already have a custom post type registered in your functions.php? or are you referring to just a category? I have a custom post type registered for contributors, and have an author as a post under that custom post type. So my URL reads www.example.com/contributor/author. That's how permalinks are setup when using custom post types with the permalink structure set to just %postname%
    – chris_s
    May 3, 2012 at 16:39

3 Answers 3


Beyond the fact that disabling 'pretty' permalinks in the Settings > Permalink page disables pretty permalinks for all post types and taxonomies, the options do not effect custom post types or taxonomies.

If you set the permalinks to blog/%postname% then your posts will have the structure: www.yoursite.com/blog/hello-world.

On the other hand, when a post type is registered (by default) it will set the permalink to www.yoursite.com/post-type/newpost (assuming you have pretty permalinks enabled, and the post type is post-type).

The same goes for custom taxonomies: A custom taxonomy will display as www.yoursite.com/custom-taxonomy/ and a custom taxonomy term will display as www.yoursite.com/custom-taxonomy/custom-taxonomy-term/.

There are a couple of things that have to be in place for this to happen though.

In register_posttype() of the post type the following must be set:

'rewrite' => true,
'has_archive' => 'post-type-name', // "post-type-name" is replaced with your post type name

Rewrite simply allows WordPress to rewrite the URL. It is set to true by default. has_archive defines the name of the archive (index) page for this post type. If this value is not set the post type has no index page.

The same is true for custom taxonomies. In register_taxonomy():

'rewrite' => array('slug' => 'hierarchical-taxonomy' ),

From the Codex:

rewrite (boolean or array) (optional) Set to false to prevent automatic URL rewriting a.k.a. "pretty permalinks". Pass an $args array to override default URL settings for permalinks as outlined below.

$args array

  • 'slug' - Used as pretty permalink text (i.e. /tag/) - defaults to $taxonomy (taxonomy's name slug)
  • 'with_front' - allowing permalinks to be prepended with front base - defaults to true 'hierarchical' - true or false allow hierarchical
  • urls (implemented in Version 3.1)

Note: You may need to flush the rewrite rules after changing this. You can do it manually by going to the Permalink Settings page and re-saving the rules -- you don't need to change them -- or by calling $wp_rewrite->flush_rules(). You should only flush the rules once after the taxonomy has been created, not every time the plugin/theme loads.

  • Thanks mor10 for the lengthy explanation, I knew you would know the answer to this question from all the Custom Post Type tutorials on Lynda.com. I'm currently looking into the problem now, I'm finding that this works for custom post types eg. ( domain.com/portfolio/new-website ) however ( domain.com/blog/new-website ) doesn't seem to be working correctly. I have also included the code of the Custom Post Types and Taxonomies.
    – Josh
    May 4, 2012 at 8:21
  • I've looked into it furthur and found that those fixes didn't resolve the problem. When clicking on a blog post permalink appears like ( localhost/mysite/new-site-launched/ ), When I want it to appear like ( localhost/mysite/blog/new-site-launched/ )
    – Josh
    May 4, 2012 at 8:44
  • Hope you don't mind the edit :). Just want to clarify the role of Settings > Permalinks options. May 4, 2012 at 21:38
  • Thanks Steven for the edited answer. Here is another question that also answers my question. wordpress.stackexchange.com/questions/13411/…
    – Josh
    May 7, 2012 at 2:38

The easiest way is to login into wp-admin, go to settings and click permalink options. From there you can change the structure of permalinks to a custom style.

For instance, mine is setup this way /blog/%postname%/. You can also tinker with .htaccess code if you want but that gets a little messy.

The other way you can do it is kind of a cheat way, but if you create custom page templates in .php in the head name your template name whatever you want, and then link it up.

 * Template Name: About
 * Description: A full-width for About
get_header(); ?>

Then create a new page, select the page template, and then make sure the permalink matches up. Most of the time this will work. You just have to have both ends in sync.

Hope this helps.

http://codex.wordpress.org/Post_Types ^This may aid you as well on Post Types.

  • Thanks for your answer, I have re-edited the question. I'm finding that when I click on my blog page it takes me to mysite.com/blog however this is using the index.php file but its not using the template-blog.php files. I will have to look into why the template heirachy is not working the way I want it too.
    – Josh
    May 4, 2012 at 10:01
  • Aw, okay. Well maybe this will help. Sometimes the index.php is written as the main blog but sometimes you don't want the index.php doing that. Just go to settings and click reading, and change the reading section to a static page and set the pages you want there. This may help.
    – Monstr92
    May 4, 2012 at 10:10
  • I just created a home.php file that replaces the template-blog.php file and index.php file. But I'm still having this problem. Also turned the static page for blog on and off. eg. blog = -select-. When that is done, it creates a page however the posts aren't listed only a entry for blog. I may need to look at other wordpress themes and see how they have set up the blog page to work with home.php
    – Josh
    May 4, 2012 at 10:25
  • The correct answer was set it to /blog/%postname%/ I honestly thought that would not work correctly but it did. :)
    – Josh
    May 4, 2012 at 11:10
  • Is there any WordPress documentation on this /blog/%postname%/ ???
    – Josh
    May 4, 2012 at 11:14

Very easy, NO NEED ANY hacks. Just leave your code as it is and go to Settings-Permalinks Select Custom structure and paste this: /%category%/%postname%/

and save it, and it will make urls like POSTYPE/POSTNAME

i use this and it works.

  • Not in my case with a Custom theme built from scratch. This is the answer to my dilemma. wordpress.stackexchange.com/questions/13411/…
    – Josh
    May 4, 2012 at 13:08
  • Well my answer have to work for you too, just in my case in post type i also used: 'with_front' => false you seems don't use it.
    – Tommixoft
    May 4, 2012 at 13:19
  • No, That's obviously why I'm on here asking the question.
    – Josh
    May 4, 2012 at 13:21

Your Answer

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

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