Rewrite Jetpack’s Custom Taxonomies
On one of my WordPress-powered sites, I use a blog post URL prefix, or ‘front’. Essentially, all blog post URLs look like mysite.com/blog/year/month/and-so-on/
, and category and tag URLs are prefixed by blog
, too.
I wanted to also start using Jetpack’s Portfolio custom post type, though, and not have URLs for its custom ‘Project Type’ and ‘Project Tag’ taxonomies prefixed by the same front. A portfolio
prefix, I figured, would definitely make more sense!
So, I went ahead and tweaked the custom taxonomy definition:
function edit_project_taxonomies() {
$project_type = get_taxonomy( 'jetpack-portfolio-type' );
$project_type->rewrite['slug'] = 'portfolio/type';
$project_type->rewrite['with_front'] = false;
register_taxonomy( 'jetpack-portfolio-type', 'jetpack-portfolio', (array) $project_type );
$project_tag = get_taxonomy( 'jetpack-portfolio-tag' );
$project_tag->rewrite['slug'] = 'portfolio/tag';
$project_tag->rewrite['with_front'] = false;
register_taxonomy( 'jetpack-portfolio-tag', 'jetpack-portfolio', (array) $project_tag );
}
add_action( 'init', 'edit_project_taxonomies', 11 );
Note that you can very simply ‘re-register’ existing custom taxonomies, provided you first fetch all of their arguments. And two more things:
- The
'with_front' = false
argument is what actually disables having myblog
front added to the portfolio type and tag URLs. - It’s perfectly fine to use a forward slash in a taxonomy slug. (Still, if you find this leads to 404 or other errors: please read on!)
Also, normally this would suffice. In this case, however, the URL rewrite rules generated by the code above are preceded by a more general rule set—itself an effect of the ‘jetpack-portfolio’ custom post type using the same ‘portfolio’ in its automatically assigned URLs. At this point, WordPress will misinterpret any request for a portfolio taxonomy archive and return a 404 instead!
Luckily, we can bump our bespoke taxonomy rules’ priority up a bit, so that they become leading:
function modify_project_taxonomies( $wp_rewrite ) {
$rules = array(
'portfolio/type/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?jetpack-portfolio-type=$matches[1]&feed=$matches[2]',
'portfolio/type/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?jetpack-portfolio-type=$matches[1]&feed=$matches[2]',
'portfolio/type/([^/]+)/embed/?$' => 'index.php?jetpack-portfolio-type=$matches[1]&embed=true',
'portfolio/type/([^/]+)/page/?([0-9]{1,})/?$' => 'index.php?jetpack-portfolio-type=$matches[1]&paged=$matches[2]',
'portfolio/type/([^/]+)/?$' => 'index.php?jetpack-portfolio-type=$matches[1]',
'portfolio/tag/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?jetpack-portfolio-tag=$matches[1]&feed=$matches[2]',
'portfolio/tag/([^/]+)/(feed|rdf|rss|rss2|atom)/?$' => 'index.php?jetpack-portfolio-tag=$matches[1]&feed=$matches[2]',
'portfolio/tag/([^/]+)/embed/?$' => 'index.php?jetpack-portfolio-tag=$matches[1]&embed=true',
'portfolio/tag/([^/]+)/page/?([0-9]{1,})/?$' => 'index.php?jetpack-portfolio-tag=$matches[1]&paged=$matches[2]',
'portfolio/tag/([^/]+)/?$' => 'index.php?jetpack-portfolio-tag=$matches[1]',
);
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
}
add_filter( 'generate_rewrite_rules', 'modify_project_taxonomies' );
This (finally!) results in the proper routing scheme:
- /portfolio/: overall portfolio archive
- /portfolio/project-name/: single project page
- /portfolio/type/some-type/: project archive for ‘some type’
- /portfolio/tag/some-tag/: project archive for ‘some tag’
One final remark: I much prefer manually defining my application’s routes over WordPress’s automatic definition of literally all sorts of routes.