Paulund

How To Intercept 404 Errors In WordPress

When you go to a URL in WordPress it first needs to analyse this URL and decide what content it is going to show to the user. WordPress will take the requested URL and search the content for the correct information it has to search the posts, pages and taxonomies to find the right content. If WordPress can not find any content that it will throw a 404 Not Found error and redirect the template template to display the 404.php file in the current installed theme. This type of error will not only tell the user that this URL doesn't exist but will tell the search engines that this page no longer exists and to deindex from the search engine. WordPress does this template redirect to the 404.php file by using the action template_redirect.

do_action('template_redirect');

This action can be used to intercept the request and do some action when you know the intended content to be displayed. In this example we can use this to log a 404 error to keep track of any 404 page that the hits the website.

function log_404_error() 
{
    if( is_404() )
    {
        global $wp_query;

        // Custom permalinks by post name
        if(!empty($wp_query->query['name']))
        {
            $this->log_url( $wp_query->query['name'] );
        }
        // Search by post id
        else if (!empty($wp_query->query['p']))
        {
            $this->log_url( $wp_query->query['p'] )
        }
        // Search by category
        else if(!empty($wp_query->query['category_name']))
        {
            $this->log_url( $wp_query->query['category_name'] )
        } 
    }
}
add_action('template_redirect', array($this, 'log_404_error') );

To create a new log database table please read the tutorial for CRUD Queries For WordPress Custom Tables.

Loading A Different Template

If you want to load a different template depending on the request it's important to note that using the action template_redirect can cause errors if the priority is not setup correctly, for change the template displayed you should be using the filter template_include. This will be called after the template has been decided and you can edit what template is used.

add_filter( 'template_include', 'portfolio_page_template', 99 );

function portfolio_page_template( $template ) 
{
    if ( is_page( 'portfolio' )  ) 
    {
        $new_template = locate_template( array( 'portfolio-page-template.php' ) );
        if ( '' != $new_template ) 
        {
            return $new_template ;
        }
    }

    return $template;
}