• I have a page template at /blog that contains a "public" blog.
  • I have a page template at /members that is members area.

If a user enters the URL /members/blog I want to catch this in the template_redirect hook and load up a custom template that shows a "private" blog


Before template_redirect is called /members/blog is re-written to /blog so I can't load the private blog page.

There is nothing in the rewrite rules that says to do this.

  • is /members/blog a page? – Milo Aug 22 '15 at 15:58
  • No. I wrote this code a while ago so it's not best practice. But I normally catch it in template_direct and do a php include and turn 404 error off – ptimson Aug 22 '15 at 16:01
  • What's happening is that whenever WordPress encounters a 404, it tries to query for something close. You can see it in this function redirect_guess_404_permalink. It finds your blog page and redirects there. The simplest solution is to just add a page so it doesn't 404. – Milo Aug 22 '15 at 16:08
  • Cheers @Milo that's what I needed to know :) I guess the hacky solution would be to hook into that and stop it guessing if URL begins with /members/blog – ptimson Aug 22 '15 at 16:11
  • If you wanted to do that, I think conditionally disabling redirect_canonical is what you'd need to do. If you search around for that you might find something. The action is added in wp-includes/default-filters.php. – Milo Aug 22 '15 at 16:16

So the problem was redirect_guess_404_permalink was detecting a 404 error and 'guessed' /members/blog to be /blog

My hacky solution was to hook into the status error check (Stop Wordpress from "guessing" redirects for nonexistent URLs) and if URL parts match then unset the guessed solution

function blog_no_redirect_guess_404_permalink( $header ){
    global $wp_query;

    if( is_404() ) {
        // Get Request URL Parts
        $url = parse_url($_SERVER['REQUEST_URI']);
        $path = explode('/', $url['path']);
        $path = array_filter($path);
        $path = array_merge($path, array());
        // If matches /members/blog then unset 'guess'
        if (strtolower($path[0]) == 'members' && strtolower($path[1]) == 'blog') {
            unset( $wp_query->query_vars['name'] );

    return $header;
add_filter( 'status_header', 'blog_no_redirect_guess_404_permalink' );
| improve this answer | |
  • I had the same issue, but found what I needed to do was simply give a lower priority to my template_redirect action. – Nicolas Galler Jan 9 '16 at 21:46

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.