Remove custom post type slug from URL

Haven’t found a useful answer for this. I am aware of the conflict issues and all the problems this may cause, I’m curious if it’s POSSIBLE not SUGGESTED. This will require WP rewrites, I know this much.

Basically, let’s say we have a CPT of “events”. I want to have a single event’s page have the URL http://domain.com/single-event-name and NOT http://domain.com/events/single-event-name. Any ideas on how to go about it?

Related posts

Leave a Reply

4 comments

  1. That’s how you can do first part of the job – get rid o CPT slug in post link (eg. news post type).

    function df_custom_post_type_link( $post_link, $id = 0 ) {  
    
        $post = get_post($id);  
    
        if ( is_wp_error($post) || 'news' != $post->post_type || empty($post->post_name) )  
            return $post_link;  
    
        return home_url(user_trailingslashit( "$post->post_name" ));  
    }
    add_filter( 'post_type_link', 'df_custom_post_type_link' , 10, 2 );
    

    Now there should go a a rewrite rules for ‘news’, because you will get a 404 error.

    Add the rewrite rule like this:

    function df_custom_rewrite_rule() {
        add_rewrite_rule('(.*?)$', 'index.php?news=$matches[1]', 'top');
    }
    add_action('init', 'df_custom_rewrite_rule');
    

    Then we’ll need to flush rewrite rules, so go to Settings – Permalinks and save changes.

  2. function register_cpt_type() {
        register_post_type('cpt', array(
            'rewrite' => array("slug" => "/cpt", "with_front" => false),
        ));
    }
    add_action('init', 'register_cpt_type')
    
    function cpt_rewrite_rule() {
        add_rewrite_rule('(.*?)$', 'index.php?cpt=$matches[1]', 'top');
    }
    add_action('after_theme_setup', 'cpt_rewrite_rule');
    

    flush/recycle url rewrites, then edit .htaccess

    RewriteRule ^cpt/(.+)$ /$1 [R=301,L]
    
  3. You could always hook into “parse_request” to perform a check to see if a custom type with the name requested exists and then modify the query_vars appropriately. You’ll need something along the lines of @Bartosz’s response to generate the permalink in addition:

     add_filter('parse_request', "t21_parse_request" , 1, 1);
    
     function t21_parse_request($wpobj)
     {
          $query_vars = $wpobj->query_vars;
          $slug = $query_vars['pagename'];
    
          $posts = get_posts(array(
               "post_type" => "event",
               "post_name" => $slug
          ));
    
          if($posts)
          {
               //we know your "event" entry exists so we now amend the query_vars
               //first unset the 'page' and 'pagename'
               unset($query_vars['page']);
               unset($query_vars['pagename']);
    
               //now rebuild the query_vars
               $query_vars['post_type'] = "event"; //CPT name
               $query_vars['name'] = $slug;
               $query_vars['event'] = $slug; //again - this constructs the "event=myevent" query string
          }
          else
          {
               //just return $wpobj since we know that there is no "event"
               return $wpobj;
          }
     }
    

    This does assume however that you won’t have any post names with the same name as a postname otherwise, the post will never appear as it matches with an event type first.