I have a child theme of Twenty Thirteen and I've setup Custom Post Types for several items. They are showing up in the Dashboard, I can create the Custom Posts and they show up in various categories because I called the $query->set() with the Custom Post Types. I've saved and re-saved Permalinks many times to flush the rewrites.

Here is how I registered one in functions.php...

$labels_successstories = array(
    // my various labels are in here
$args_successstories = array(
    'labels' => $labels_successstories,
    'public' => true,
    'menu_position' => 29,
    'supports' => array( 'title', 'editor', 'thumbnail' ),
    'taxonomies' => array( 'category' ),
    'has_archive' => 'success-stories',
    'rewrite' => array( 'slug' => 'success-stories' )
register_post_type( 'successstories', $args_successstories );

In Settings > Permalinks > Custom Structure >


Here is how I call $query->set() in functions.php

function get_custom_posts( $query ) {
    if ( ! is_admin() && empty($query->query_vars['suppress_filters']) ) { // is not in Dashboard (is_admin => Dashboard)       
        if ( is_home() ) {  // home page - show only animal posts
            return $query->set( 'post_type', array( 'post', 'successstories', 'another-post-type' ) );
        } else if ( is_search() ) {  // search page - show only posts, pages and custom post types
            return $query->set( 'post_type', array( 'post', 'page', 'successstories', 'another-post-type' ) );
        } else if ( ! is_single() ) { // everything else, EXCEPT for Singles, show everything
            return $query->set( 'post_type', array( 'post', 'page', 'attachment', 'successstories', 'another-post-type' ) );
add_filter( 'pre_get_posts', 'get_custom_posts' );

My goal is to remove as many Categories as I can since the Custom Post Types will effectively replace most of these Categories. However, one of my Custom Post Types will still need a few Categories.

Here are the questions/issues:

1) When I go to mysite.com/success-stories/, it's using the default archive.php template. However, I have created a template called archive-successstories.php and it's being totally ignored. (if it matters, the single-successstories.php template is working perfectly fine)

2) When I go to mysite.com/success-stories/, I see posts but they're coming from all posts, custom post types, and categories. I just want to see posts from the successstories Custom Post Type when I go there. I think I know how to fix this but if the archive template is being ignored, then my fix will not be seen.

3) Right now, Success Stories (Custom Post Types) are also in a Category named success-stories which can be accessed at mysite.com/category/success-stories and that shows the correct posts. However, my goal is to remove this Category since it's not needed. Once I get these Custom Post Types to show on their proper archive pages, the respective Categories will be superfluous.

  • You should be checking for $query->is_main_query() in your filter, otherwise it will apply to all queries, including secondary ones everywhere. It's hard to guess without rebuilding your setup completely, but having same slugs for different things in WP is typical to cause issues.
    – Rarst
    Commented Jan 16, 2014 at 20:08
  • @Rarst, thank-you for the suggestion. Now I have if ( ! is_admin() && $query->is_main_query() && empty($query->query_vars['suppress_filters']) ) { but the problems remain.
    – Sparky
    Commented Jan 16, 2014 at 20:39

3 Answers 3


Three questions per post is not typical; however, as they may all be inter-related I'll try to help step through each one in turn.

The first problem may be simple:

When I go to mysite.com/success-stories/, it's using the default archive.php template. However, I have created a template called archive-successstories.php and it's being totally ignored.

The use of the archive template is determined by the 'has_archve' parameter in your register_post_type() call, which you've added like so:

'has_archive' => 'success-stories'

However, per the Codex, 'has_archive' is expected to be string/boolean: i.e. true or false. Try this instead:

'has_archive' => true

Then, flush your rewrite rules by loading the Settings -> Permalinks page.

Important note: The URL to display the CPT archive using archive-successstories.php will be example.com/successstories, not example.com/success-stories. If you want to use the latter, you'll need to pass a valid 'rewrite' parameter to register_post_type(). Note that 'rewrite', if not boolean, must be an array, not a string.

  • 1
    Not true, has_archive does accept string slug for archive $archive_slug = $args->has_archive === true ? $args->rewrite['slug'] : $args->has_archive;
    – Rarst
    Commented Jan 16, 2014 at 20:11
  • Indeed, but only if you add the appropriate rewrite rules, if the string passed is different from the CPT slug. In this case: 'success-stories' != 'successstories'. By passing true to has_archive, example.com/successstories will properly display archive-successstories.php. Commented Jan 16, 2014 at 20:17
  • 1
    I am not sure what you mean by "only if you add", it's handled automatically. Saying that has_archive only accepts true/false is incorrect. It accepts true/false or archive's slug for rewrite. Also from quick look template hierarchy uses post type name for template file name, it doesn't look at rewrite settings.
    – Rarst
    Commented Jan 16, 2014 at 20:21
  • 1
    Ultimately, I think the issue lies somewhere in the conflation/mixture of successstories and success-stories. Making the slug consistent throughout will (probably) resolve the problem. Commented Jan 16, 2014 at 20:25
  • 1
    Yeah, but it's more likely clash with same slug category, CPT register doesn't look problematic to me here.
    – Rarst
    Commented Jan 16, 2014 at 20:26

The whole problem was in my filters. The last one was a catch-all for everything not already defined...

} else if ( ! is_single() ) { // everything else, EXCEPT for Singles, show everything
    return $query->set( 'post_type', array( 'post', 'page', 'attachment', 'successstories', 'another-post-type' ) );

I fixed all three issues by adding (! is_archive()) to this last conditional...

} else if ( (! is_single()) && (! is_archive()) ) {
    return $query->set( 'post_type', array( 'post', 'page', 'attachment', 'successstories', 'another-post-type' ) );
  • archive templates are now being found
  • only posts from the respective Custom Post Type are being displayed in the archive
  • there are no conflicts with any category sharing the same slug name. (although I'll still be removing these because they're now redundant and superfluous.)


Now that I've cleaned up the taxonomy, removed superfluous categories, that whole else if ( (! is_single()) && (! is_archive()) ) is not even needed. Thanks Chip for the suggestion!


Why don't you add support for registering custom taxonomy types rather than use categories with your CPT's?

Looks like you have issues because you're using exactly the same slugs for categories or something else which conflict with your CPT names.

You only need has_archive if you want to use a custom archive-cpt.php template otherwise WordPress generates a standard archive.

This is the line which you need to use a custom archive template for your CPT. Removed, an archive will still be generated for your CPT:

'has_archive'  => true,

You will need this line if using register_taxonomy with your CPT.

If your CPT is named portfolio, you add the above line to your code to register the CPT and the name of the CPT to the custom archive template which, in this case would be:

  • Thanks Brad but the whole problem was being caused by my filtering. You are allowed to have the same category slug as the custom post type slug. It worked fine after I fixed the filtering issue. However, I still removed those categories because they became redundant.
    – Sparky
    Commented Jan 17, 2014 at 16:57
  • Also, if you read the Codex, you will see that has_archive can also be a string and it must match the slug if you're also using the rewrite option as I am. This is what I've done and it's working now that I've fixed the filtering problem.
    – Sparky
    Commented Jan 17, 2014 at 18:53

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.