function create_posttype() {
    register_post_type( 'events',
            'labels' => array(
                'name' => __( 'Events' ),
                'singular_name' => __( 'Event' )
            'public' => true,
            'has_archive' => true,
            'rewrite' => array('slug' => '%city%/events'),
add_action( 'init', 'create_posttype' );

register_taxonomy('cities', array('events'), array(
    'hierarchical' => true,
    'labels' => $labels,
    'show_ui' => true,
    'show_admin_column' => true,
    'query_var' => true,
    'rewrite' => array( 'slug' => 'city' ),

function wpa_permalinks( $post_link, $post ){
    if ( is_object( $post ) && $post->post_type == 'events' ){
        $terms = wp_get_object_terms( $post->ID, 'cities' );
        if( $terms ){
            return str_replace( '%city%' , $terms[0]->slug , $post_link );
    return $post_link;
add_filter( 'post_type_link', 'wpa_permalinks', 1, 2 );

The permalink are correctly structured (ex. http://www.example.org/new-york/events/event-name) but I have two issues:

  • The template single-events.php is not taken and it shows 404.
  • Same for the archive template. http://www.example.org/new-york/events should display the archive.

How to solve?

  • Have you flushed your rewrite rules? i.e. Settings > Permalinks > Save Jun 21, 2016 at 15:43
  • Yes I did. Doesn't work. Jun 21, 2016 at 15:50
  • 1
    Can you try replacing all instances of %city% with %cities% Jun 21, 2016 at 15:55
  • I did and it seems it works. Why is that? I thought that %city% was just a placeholder with a random name. Even the archive page seems working now! Why? Jun 21, 2016 at 16:08

1 Answer 1


You need to use %cities% (matching the name of the taxonomy).

I thought that %city% was just a placeholder with a random name.

Not quite - it's called a permalink structure (permastruct) and is used to map to a regular expression. When you call register_taxonomy, it automatically registers a new permastruct with the same name as the taxonomy.

Read up on WP_Rewrite::add_permastruct which hopefully gives a bit more insight.

Update: Let's clarify what we're aiming for:

  • /city/new-york/events/ - All events posts attached to new-york
  • /city/new-york/restaurants/ - All restaurants posts attached to new-york
  • /city/new-york/events/foobar/ - Single events "foobar"

And do you need hierarchical slugs for cities? i.e. england/london (answering "yes" is going to make things difficult). Or is london sufficient?

Update 2: How about?

  • /events/new-york/ - All events posts attached to new-york
  • /restaurants/new-york/ - All restaurants posts attached to new-york
  • /restaurants/new-york/foobar/ - Single events "foobar"
  • Thanks but there's a catch. The taxonomy "cities" is used for different types of custom post types, for example events and restaurants. If I go to /new-york/events o /new-york/restaurants, the results are the same and are all the posts associated at the taxonomy new-york. How can I fix? Jun 21, 2016 at 16:24
  • 1
    If I'm honest, I would advise you to rethink your permalink structure. The problem is outside the scope of this question, which is that you've got rules that are too vague/broad and are catching URLs intended for others. Ideally you want to swap %cities%/events to events/%cities%, which will probably go against everything you're aiming for, but means the CPT rules are now "namespaced" by events and won't get caught by your tax rules. Jun 21, 2016 at 16:29
  • Yes honestly I'm having lot of troubles doing this on WP. I'm doing something very simple but it seems that it's very hard if not impossible to do it with WP. Basically I want to achieve a permalink structure like this: /<city-name>/<custom-post-type>/<post-name>/. So I can have /new-york/events/, /chicago/restaurants/, etc. Do you think is it possible with WP? Jun 21, 2016 at 16:31
  • Let's clarify what you need (see updated answer). Jun 21, 2016 at 16:40
  • Nope, I don't need hierarchical slugs. london is sufficient. What you wrote in the list is right, I'm aiming exactly for that structure and if you'll help me achieving it, I'll be forever grateful, this is giving me such an hard time. PS: I would like to omit the part /city/ in the slug and start directly with the name of the city for example www.example.com/new-york/etc. Jun 21, 2016 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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