I have the following permalink structure /%category%/blog/%postname%/.

I also have an archive at /blog which lists all blog posts.

I have one particular category for which I'd like the permalink structure to be /blog/%postname%/

This is the code I've tried :

add_filter( 'post_link', 'custom_permalink', 10, 3 );
function custom_permalink( $permalink, $post, $leavename ) {

$category = get_the_category($post->ID); 
if (  !empty($category) && $category[0]->cat_name == "hello" ) {
    $permalink = trailingslashit( home_url('/blog/'. $post->post_name 
.'/' ) );
return $permalink;

This first part works correctly and changes the url of the post with category 'hello' to https://example/blog/post-name - In the next part I'm trying to create a redirect for this url to the actual post.

add_action('generate_rewrite_rules', 'custom_rewrite_rules');
function custom_rewrite_rules( $wp_rewrite ) {

$feed_rules = array(

  '^blog/?' => 'index.php?name=$matches[1]',
$wp_rewrite->rules = $feed_rules + $wp_rewrite->rules;
return $wp_rewrite->rules;;

This also works and redirects the url to https://example/blog/post-name But! this url, instead of showing a single post - is showing my blog archive, so is rendering essentially the same as - https://example/blog/

My question - why is https://example/blog/post-name showing the same as https://example/blog/ rather than showing the post?

2 Answers 2


Your rewrite rule doesn't capture anything. Change:


to add the capture group you reference with $matches[1] in your rule:


visit the Settings > Permalinks page, which will flush rules, and your code should otherwise work.


First of all, I see a problem in your code you should know about, instead of using rewrite_rules_array which is final rewrite rules filter, or even something like post_rewrite_rules you using action generate_rewrite_rules to put your own rules accessing globally and changing $wp_rewrite. You better to use one of the suitable filters, like in this example.

add_filter( 'rewrite_rules_array', function( $rules ){
    $rule = [ '^blog/([^/]+)/?' => 'index.php?name=$matches[1]' ];
    return array_merge( $rule, $rules);

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.