Remove category & tag base from WordPress url - without a plugin
WordpressCategoriesBaseWordpress Problem Overview
I would like to remove the category & tag base from WordPress URL. I have come across other posts and solutions which used plugins. I would like to stay away from plugins and have a solution from within functions.php. This would prevent any future plugin updates or WordPress default files from being changed.
Any help would be appreciated. Thanks!
I have tried these solutions so far:
- This htaccess solution did not work: http://mikepayne.co/2011/remove-category-base-from-url/
- These methods also failed: http://www.askapache.com/wordpress/remove-category-wordpress-urls.html
Wordpress Solutions
Solution 1 - Wordpress
If you want to remove /category/
from the url, follow these two steps:
- Go to Settings >> Permalinks and select Custom and enter:
/%category%/%postname%/
- Next set your Category Base to
.
Save it and you’ll see your URL changed to this format: http://yourblog.com/quotes/
(Source: http://premium.wpmudev.org/blog/daily-tip-quick-trick-to-remove-category-from-wordpress-url/)
Solution 2 - Wordpress
If you use Yoast SEO
plugin just go to:
Search Appearance > Taxonomies > Category URLs.
And select remove
from Strip the category base (usually /category/) from the category URL
.
Regarding the tag removal I did not found any solution yet.
Solution 3 - Wordpress
Whilst you dismiss it as a solution, the plugin is by far the easiest and most consistent method and they don't change any WordPress default files.
http://wordpress.org/plugins/wp-no-category-base/
It hasn't needed to be updated for a year, so it is not exactly creating any problems with updates.
There is no simple hand rolled solution that will do all of this that does not just replicate what the plugin does from within your own functions.php
- Better and logical permalinks like myblog.com/my-category/ and myblog.com/my-category/my-post/.
- Simple plugin - barely adds any overhead.
- Works out of the box - no setup needed. No need to modify WordPress files.
- Doesn't require other plugins to work.
- Compatible with sitemap plugins.
- Works with multiple sub-categories.
- Works with WordPress Multisite.
- Redirects old category permalinks to the new ones (301 redirect, good for SEO).
Plus you get the benefit that if WordPress does change, then the plugin will be updated to work whilst you would then have to figure out how to fix your own code on your own.
Solution 4 - Wordpress
-
Set Custom Structure: /%postname%/
-
Set Category base: . (dot not /)
-
Save. 100% work correctly.
Solution 5 - Wordpress
instead put this in your functions.php works fine, no redirect problems.
function fix_slash( $string, $type )
{
global $wp_rewrite;
if ( $wp_rewrite->use_trailing_slashes == false )
{
if ( $type != 'single' && $type != 'category' )
return trailingslashit( $string );
if ( $type == 'single' && ( strpos( $string, '.html/' ) !== false ) )
return trailingslashit( $string );
if ( $type == 'category' && ( strpos( $string, 'category' ) !== false ) )
{
$aa_g = str_replace( "/category/", "/", $string );
return trailingslashit( $aa_g );
}
if ( $type == 'category' )
return trailingslashit( $string );
}
return $string;
}
add_filter( 'user_trailingslashit', 'fix_slash', 55, 2 );
Solution 6 - Wordpress
The dot trick will likely ruin your rss feeds and/or pagination. These work, though:
add_filter('category_rewrite_rules', 'no_category_base_rewrite_rules');
function no_category_base_rewrite_rules($category_rewrite) {
$category_rewrite=array();
$categories=get_categories(array('hide_empty'=>false));
foreach($categories as $category) {
$category_nicename = $category->slug;
if ( $category->parent == $category->cat_ID )
$category->parent = 0;
elseif ($category->parent != 0 )
$category_nicename = get_category_parents( $category->parent, false, '/', true ) . $category_nicename;
$category_rewrite['('.$category_nicename.')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?category_name=$matches[1]&feed=$matches[2]';
$category_rewrite['('.$category_nicename.')/page/?([0-9]{1,})/?$'] = 'index.php?category_name=$matches[1]&paged=$matches[2]';
$category_rewrite['('.$category_nicename.')/?$'] = 'index.php?category_name=$matches[1]';
}
global $wp_rewrite;
$old_base = $wp_rewrite->get_category_permastruct();
$old_base = str_replace( '%category%', '(.+)', $old_base );
$old_base = trim($old_base, '/');
$category_rewrite[$old_base.'$'] = 'index.php?category_redirect=$matches[1]';
return $category_rewrite;
}
// remove tag base
add_filter('tag_rewrite_rules', 'no_tag_base_rewrite_rules');
function no_tag_base_rewrite_rules($tag_rewrite) {
$tag_rewrite=array();
$tags=get_tags(array('hide_empty'=>false));
foreach($tags as $tag) {
$tag_nicename = $tag->slug;
if ( $tag->parent == $tag->tag_ID )
$tag->parent = 0;
elseif ($tag->parent != 0 )
$tag_nicename = get_tag_parents( $tag->parent, false, '/', true ) . $tag_nicename;
$tag_rewrite['('.$tag_nicename.')/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$'] = 'index.php?tag=$matches[1]&feed=$matches[2]';
$tag_rewrite['('.$tag_nicename.')/page/?([0-9]{1,})/?$'] = 'index.php?tag=$matches[1]&paged=$matches[2]';
$tag_rewrite['('.$tag_nicename.')/?$'] = 'index.php?tag=$matches[1]';
}
global $wp_rewrite;
$old_base = $wp_rewrite->get_tag_permastruct();
$old_base = str_replace( '%tag%', '(.+)', $old_base );
$old_base = trim($old_base, '/');
$tag_rewrite[$old_base.'$'] = 'index.php?tag_redirect=$matches[1]';
return $tag_rewrite;
}
// remove author base
add_filter('author_rewrite_rules', 'no_author_base_rewrite_rules');
function no_author_base_rewrite_rules($author_rewrite) {
global $wpdb;
$author_rewrite = array();
$authors = $wpdb->get_results("SELECT user_nicename AS nicename from $wpdb->users");
foreach($authors as $author) {
$author_rewrite["({$author->nicename})/(?:feed/)?(feed|rdf|rss|rss2|atom)/?$"] = 'index.php?author_name=$matches[1]&feed=$matches[2]';
$author_rewrite["({$author->nicename})/page/?([0-9]+)/?$"] = 'index.php?author_name=$matches[1]&paged=$matches[2]';
$author_rewrite["({$author->nicename})/?$"] = 'index.php?author_name=$matches[1]';
}
return $author_rewrite;}
add_filter('author_link', 'no_author_base', 1000, 2);
function no_author_base($link, $author_id) {
$link_base = trailingslashit(get_option('home'));
$link = preg_replace("|^{$link_base}author/|", '', $link);
return $link_base . $link;
}
Solution 7 - Wordpress
The non-category plugin did not work for me.
For Multisite WordPress the following works:
- Go to network admin sites;
- Open site under
\
; - Go to settings;
- Under permalinks structure type
/%category%/%postname%/
. This will display your url aswww.domainname.com/categoryname/postname
; - Now go to your site dashboard (not network dashboard);
- Open settings;
- Open permalink. Do not save (the permalink will show uneditable field as
yourdoamainname/blog/
. Ignore it. If you save now the work you did in step 4 will be overwritten. This step of opening permalink page but not saving in needed to update the database.
Solution 8 - Wordpress
If you're still searching for the combination (tags, categories and pages on the url-base), you can do it like I did.
- Open the settings for permalinks and set a dot (
.
) for the category- and tag-base (https://premium.wpmudev.org/blog/removing-category-base-urls-wordpress/) - Install the plugin wp-no-tag-base
Tested using Wordpress 3.9.1
If you have pages, categories or tags having the same name, the system will take:
- tag
- page
- category
Solution 9 - Wordpress
https://wordpress.org/plugins/remove-category-url/ Use this plugin it does the job perfectly of hiding the category-base It does not require any setting just install and activate.
Solution 10 - Wordpress
Select Custom Structure in permalinks and add /%category%/%postname%/ after your domain. Adding "/" to the category base doesn't work, you have to add a period/dot. I wrote a tutorial for this here: remove category from URL tutorial
Solution 11 - Wordpress
I don´t know how to do it using code, but for those who don't mind using a plugin. This is a great one that works for me:
Solution 12 - Wordpress
updated answer:
other solution:
In wp-includes/rewrite.php file, you'll see the code:
$this->category_structure = $this->front . 'category/';
just copy whole function, put in your functions.php and hook it. just change the above line with:
$this->category_structure = $this->front . '/';
Solution 13 - Wordpress
add_action( 'init', 'remove_category_perma' );
function remove_category_perma() {
unset($GLOBALS['wp_rewrite']->extra_permastructs['category']);
}
Solution 14 - Wordpress
WordPress 5.0.2:
To remove category slug from existing posts, do this :
- Navigate to Settings > Permalinks and change Custom Structure from
/%category%/%postname%/
to:/%postname%/
- Keep Category and Tag bases empty (which is the default also)
- Save
All posts can now be directly accessed via domain.com/%postname%/
and all categories can be accessed via domain.com/category/xyz/
. WordPress will automatically add all the 301 redirects for the old urls. So, if someone accesses domain.com/%category%/%postname%/
, they will automatically get redirected to domain.com/%postname%/
.
Solution 15 - Wordpress
Adding "." or "/" won't work if you want a consolidated blog view. Also, I have know idea what that solutions would do for the RSS or XML feeds. I feel better sticking with the WP convention. However, I did come up with a more elegant approach.
First, I name the base category url "blog"
Then I created a category called "all". Finally, I but all my subcategories under "all". So I get a url structure like this.
/blog - 404 - recommend 301 redirect to /blog/all/
/blog/all/ - all posts combined.
/blog/all/category1/ - posts filtered by category1
/blog/all/category2/ - posts filterer by category2
I put a custom label on the menu item called "Blog", but it goes to blog/all. It would be a good idea to 301 redirect /blog to /blog/all in the .htaccess file to avoid the 404 on /blog.