URI returns a post when it should return a 404

Morning All

I have a question and I think I have a solution as well, but I wanted to ask to see if my thinking is correct.

I have wp site live at http://www.phmotorcycles.co.uk and I have just found an anomaly that could be a potential SEO disaster.

The site uses the plugin Toolset Types and I have a custom post type of BIKES.

So we have a customer URL structure which follows this pattern:

domain/new-bikes/%manufacturer%/%category%/%model%

This is working just fine, however I have now found that a bike can be returned with the wrong manufacturer and category of bike eg:

http://www.phmotorcycles.co.uk/new-bikes/ktm/duke/ktm-690-duke-2012/ (CORRECT)

The same bike can be returned if you swap ktm for yamaha. Basically any incorrect combination of manufacturer or category with the bike at the end will return a page, which is not correct.

both links call a customised singles.php page which uses the global $post variable to return the information from the WP database.

My Solution:

  1. Capture the url and split it into separate parts to represent manufacturer, category and model.
  2. Query the $post variable for each piece of information and compare
  3. If they match great, if they don’t match then force a 404

This seems pretty clear but being new to WordPress I am not sure if there is a simpler way to ensure that WordPress does this for me?

Any advise, tips or tricks would be greatly appreciated.

Solutions Collecting From Web of "URI returns a post when it should return a 404"

WordPress tries to guess what post the user want to see by post name. That is what is making both example.com/new-bikes/ktm/duke/ktm-690-duke-2012/ and example.com/new-bikes/ktm/yamaha/ktm-690-duke-2012/ return the same and “correct” content.

What is important is that, if you see at the source code of example.com/new-bikes/ktm/yamaha/ktm-690-duke-2012/, you can see the canonical URL correctly set to example.com/new-bikes/ktm/duke/ktm-690-duke-2012/. User gets what he is looking for and search engines knows the canonical URL, so every one wins.

So, I don’t recommend to force a 404 error on example.com/new-bikes/ktm/yamaha/ktm-690-duke-2012/ and I think you should not worried about this.

Anyway, if you really want to avoid that URL, I would redirect the user to the canonical URL with a 301 status code instead of forcing a 404:

add_action( 'template_redirect', 'cyb_canonical_redirect' );
function cyb_canonical_redirect() {
    global $wp;
    if( is_singular() ) {
        $id = get_queried_object_id();
        $canonical_url = get_permalink( $id );
        $current_request = site_url( $wp->request );
        // Compare current request and canonical url
        if( $canonical_url !=  $current_request) {
            wp_redirect( $canonical_url, 301 );
            exit();
        }
    }
}