I apologize if this is a difficult question to understand, but really it's a template hierarchy / rewrites question.

I have set up a few rewrite rules that are successful, but I'm hoping that I can manipulate them to call different template files in the hierarchy, so I can control archive pages more logically. I have a team-news custom post type, and a sport taxonomy. My goal is to have a team-news archive of posts only from a specific sport, and a separate sport archive for all posts and pages associated with that taxonomy. Unfortunately, I'm only able to access the sport taxonomy archive with my current rewrites, not the team-news CPT archive.

Here are my rewrite rules and an explanation of what I think happens:

add_rewrite_rule('^athletics/team/([^/]*)/news/?','index.php?post_type=team-news&sport=$matches[1]', 'top');

This one brings up taxonomy-sport.php, although I was hoping it would bring up archive-team-news.php. I need the sport= part, because I only want to show team-news posts for that sport.

add_rewrite_rule('^athletics/sport/([^/]*)/?','index.php?sport=$matches[1]', 'top');

This one rightly brings up taxonomy-sport.php as I had hoped.

According to the Query Monitor plugin, the template hierarchy when requesting the url /athletics/team/varsity-football/news/ is this:

  1. taxonomy-sport-varsity-football.php
  2. taxonomy-sport.php --- The one it's using
  3. taxonomy.php
  4. archive-team-news.php --- The one I want it to be
  5. archive.php
  6. index.php

Is there any way to make archive-team-news.php work for that URL? Would I need to filter the hierarchy? I'm pretty new to WP, so I don't want to change up too much...

EDIT 1: To simplify my goal --

?post_type=[1]&taxonomy=[2] will always pull up a taxonomy archive page, as far as I can tell. Can I make it pull up the post-type archive page instead?

EDIT 2: I've changed the 2nd parameter of the first rewrite rule to 'index.php?post_type=team-news', and now the correct archive page is being displayed (archive-team-news.php) but I still need to filter further by taxonomy somehow.

NOTE: the taxonomy slug is in the URL as athletics/team/[taxonomy]/news/, so now I'm trying to parse the URL for that value in PHP, but I'd prefer a WP solution (less hacky).

  • if you change the order in URL, does it change something index.php?sport=$matches[1]&post_type=team-news ?
    – mmm
    Nov 16, 2017 at 22:29
  • Good idea, but no. That's what I had at first, so I thought if I "prioritized" the post type by putting it first, it might work, but it didn't. :/ Nov 16, 2017 at 22:41
  • One thing you can try is to use a custom query var to pass the tax slug, then hook pre_get_posts to manually add the tax query. Another possible solution is to hook parse_query and force a post type archive. You could filter the hierarchy as you mention, but it’ll still be identified as a tax archive in things like body_class.
    – Milo
    Nov 17, 2017 at 2:34

1 Answer 1


I handled this with a pre_get_posts hook (thanks, @Milo), passing in the URL part that corresponds to the slug I need. Hope this helps someone down the road. Improvements are welcome. Thanks.

function filter_team_news_archives_by_sport_taxonomy($query) {

    if (is_post_type_archive('team-news') && $query->is_main_query()){

            // Get $sport_slug from URL  --  https://stackoverflow.com/a/36002190/4107296
            $url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
            $parsed = parse_url( $url );
            $chunks = explode( '/', trim($parsed['path'],'/') );
            // if the URL is in this format: /athletics/team/[sport-slug]/news 
            if ($chunks[0] === 'athletics' && $chunks[1] === 'team' && $chunks[3] === 'news') {
                $sport_slug = $chunks[2];
                $query->set('tax_query', array(array(
                    'taxonomy' => 'sport',
                    'field'    => 'slug',
                    'terms'    => $sport_slug,

add_action('pre_get_posts', 'filter_team_news_archives_by_sport_taxonomy');

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.