I have a website that lists businesses in different cities (this is a niche site, so all businesses have the same "classification").

For starters I created a CPT for locations and a taxonomy called "Cities," which 150 or so cities as terms.

All 300+ locations have been tagged with a city.

I was able to modify the CPT links so that they appear like so: example.com/cityname/business-name

What I'd love to have (and not been able to accomplish yet) are urls like example.com/cityname which would list all businesses from that city.

My understanding is that by default WP attempts to find a page with "cityname" as the name.

What would be the easiest way to reroute this request to use a taxonomy template? Or as an alternative, what would the easiest way be to have the page template detect the city name and pull posts tagged with that taxonomy term?

I suppose I could create rewrite rules in htaccess for all cities, but I'd prefer where the redirects were automatically added when a new city name is added to the taxonomy.

  • 3
    you might get an idea of how to do this by looking at the no category base plugin. it works by adding a new rewrite rule for each term when the term is added to the database.
    – Milo
    Commented Mar 28, 2013 at 16:29

1 Answer 1


Here is some code that should do the trick:

//Creates special permastruct that turns all terms of cities into slugs
add_action( 'init', 'set_rewrite' );

function set_rewrite() {
    //Get terms
    $terms = get_terms( 'cities', array( 'hide_empty' => false ) );
    //return if no terms
    if( count( $terms ) < 1 ) return;
    $slugs = wp_list_pluck( $terms, 'slug' );
    //create term regex
    $termregex = '(' . implode( '|', $slugs) . ')';
    //New query var
    add_rewrite_tag( '%cityname%', $termregex );
    //Add permastruct
    add_permastruct( 'cities_struct', '%cityname%/' );
    //refresh if new term added
    if( get_option( 'update_cities_struct' ) ) {
        global $wp_rewrite;
        $wp_rewrite -> flush_rules();
        update_option( 'update_cities_struct', 0 );

//action to refresh rewrite rules when a new term is saved
add_action( 'created_cities', 'refresh_cities' );
add_action( 'edited_cities', 'refresh_cities' );
add_action( 'delete_cities', 'refresh_cities' );

function refresh_cities() {
    update_option( 'update_cities_struct', 1 );

//set city name to the taxonomy cities
add_filter( 'parse_query', 'parse_cities_query' );

function parse_cities_query( $query ) {
    if( !empty( $query->query_vars['cityname'] ) ) $query->set( 'cities', $query->query_vars['cityname'] )

Basically this creates a special permastruct that uses the slugs of the taxonomy cities as its base. It creates a query variable called cityname, which only accepts the slugs of the taxonomy and then sends the result to the proper taxonomy query variable.

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.