Sunday 26 January 2014

How to build effective 404-error pages in WordPress

The greatest sites out there are always notable for their attention to detail. One often underestimated detail is the existence of a useful and user-friendly 404-error page. WordPress provides an easy way to create and customise the 404-error page, but unfortunately, the simplicity in customization does not automatically mean effectiveness.
The well-known WordPress SEO expert Joost de Valk (aka yoast) reports his recent findings from several years of website SEO audits. According to this report a significant number of the websites audited had problems with optimising their 404-error page. The default WordPress theme (currently TwentyTwelve) has a very basic template for this case and not so many site owners go beyond that.

Why is it important?

Let’s look at this from the common sense point of view. When does a 404 error occur? When someone clicks on a link that should point to content on your site, but for whatever reason there is no corresponding page: maybe you have changed a permalink or removed the page, maybe you have changed the tags or category slug, maybe the link was just wrong. There are any number of reasons for the error, but one important fact cannot be denied: the visitor is already on your site, s/he is already interested in something, s/he has already made an effort to find it, so this effort should be rewarded.
One of the fundamental rules of UI is not to leave users in dead-ends without guidance. There is always a back button in the browser, but do you really want your visitor to have to use it?
Apple 404
Apple provides a sitemap on their 404-error page accompanied with a simple and clear message.

37 Signals 404
37signals use the extra opportunity to present their products, and provides contact information to solve the problem.

Zurb 404
Zurb‘s 404-error page emphasises the option to contact them with a problem. Designers should solve problems, right?

Problogger 404
Problogger presents a wide range of various content to dive into reading.

Justin Tadlock's 404
Justin Tadlock‘s Blog uses breadcrumbs to present a homepage link.

Creating custom 404 error page in WordPress

What can be done to improve this situation? How can the mistake be turned into an opportunity?
In search of ideas and guidelines we can consult WordPress Codex or Google Webmaster Guidelines as perfect starting points. Actually, our main task is quite simple: explain why a page can’t be located and offer suggestions for getting to the right screen. From this point of view we can derive a list of possible components that creates a “perfect” 404-error page:
  • a clear error message in a simple and friendly manner, with apologies for the inconvenience;
  • the look and feel of the rest of the site with clear branding and navigation options;
  • possible alternatives and hints on how to find the desired information. A search form, links to relevant and/or popular content and the homepage are all possible solutions for this part;
  • a way to report an error if the user wants to; you can provide a contact email or other contact information.
From this list we can determine useful tips and ideas for what to include in a 404-error template:
  • recent and/or popular posts, or alternatively random posts;
  • subscription options (like RSS) in addition to contact details;
  • sitemap, especially in the case of small sites;
  • promotions or information about your offers and services;
  • branding materials to easily identify your site and your industry;
  • information about the requested URL and most relevant content;
  • tagcloud as a quick way to place the visitor into the context of your site;
  • a notification and/or tracking system to be aware of any 404 errors on your site.
One important thing about a 404-error page is a proper 404 HTTP status that should be served by the server. Fortunately, WordPress handles this for us automatically, so that we can focus our efforts on creating the page itself. We need the active theme to have a separate template for the page named 404.php. The bare bones structure of the template is quite simple:
<?php
/**
The template for displaying 404 pages (Not Found).
**/
get_header(); ?>
<div id="content" class="not-found-page">
<!-- page content goes here -->
</div>
<?php get_footer(); ?>
The markup that creates the page structure should correspond with what’s used by the active theme. Alternatively, some additional styling can be provided to imitate that structure. By including the standard calls get_header and get_footer we ensure that the page has all the branding elements and navigation options and all scripts and styles are loaded properly.
Now, when we have made the initial preparations, let’s fill in the page. The best thing we could do for the visitor on the 404 page is to guess what’s actually requested and provide the closest possible match. Information about the requested URL is stored by WordPress in the $wp->request property. We can parse that string and try to find similar content based on post_name data, which stores information about post and page slugs. If such a search does not return anything meaningful we can try a regular search through post content. If these efforts do not produce any positive results we can always provide a list of recent posts as a fallback.
Of course, we also include the friendly message, the search form and a link to the homepage.
First we are going to create some auxiliary functions to handle some template routines; they could be included in functions.php of your theme or directly in the beginning of 404.php file.
function frl_get_requested_slug(){
  global $wp;
  $q = $wp->request;
  $q = preg_replace("/(\.*)(html|htm|php|asp|aspx)$/","",$q);
  $parts = explode('/', $q);
  $q = end($parts);
  return $q;
}
frl_get_requested_slug function tries to obtain the requested page slug using the global$wp object and regular expressions. The code assumes that the site uses permalinks and the request goes in the appropriate form.
function frl_list_posts($posts){
  if(empty($posts))
  return '';
  $list = array();
  foreach($posts as $cpost) {
    $title = apply_filters('the_title', $cpost->post_title);
    $url = get_permalink($cpost);
    $list[] = "<li><a href='{$url}'>{$title}</a></li>"; 
  }
  return implode('', $list);
}
frl_list_posts helps to quickly output a list of post links, accepting an array of WP_Post objects as arguments.
function frl_load_error_style(){
  if(!is_404())
  return;
  $src = get_template_directory_uri().'/css/error-style.css';
  wp_enqueue_style('error-style', $src);
}
frl_load_error_style loads custom styles with the 404 template, assuming that the appropriate .css file is located in the /css folder inside the active theme’s directory.
The template code as we planned includes four parts: the friendly message; the search; the recent posts list; the last chance.
The friendly message:
<!-- Message -->
<h2>404: Page not found</h2>
<div class="message not-found">
<p>Sorry, unfortunately, we could not find the requested page.</p>
<p>Let's find the information you need.</p>
</div>
The search for the requested content:
<!-- Did you mean -->
<?php 
$q = frl_get_requested_slug();
$args = array(
  'post_type' => 'any',
  'post_status' => 'publish',
  'name' => $q,
  'posts_per_page' => 5
);
$query = new WP_Query($args); //query posts by slug
if(empty($query->posts)){ //search for posts
  $q = str_replace('-', ' ', $q);
  $args = array(
    'post_type' => 'any',
    'post_status' => 'publish',
    's' => $q,
    'posts_per_page' => 5
  );
  $query->query($args); 
}
if(!empty($query->posts)):
  ?>
  <h4>Were you looking for the one of the following pages?</h4>
  <ul class="posts-list">
  <?php echo frl_list_posts($query->posts);?>
  </ul>
<?php endif;?>
First of all, we perform a WordPress query with an initial set of arguments which looks for the requested slug in a post/page name field. If we don’t get any results after that, we replace dashes in the requested string with spaces and perform another query that searches for the requested words in the posts/pages content. If we’ve obtained any results we then output them with the help of the previously created frl_list_posts function.
Recent posts list:
<!-- Recent content -->
<?php 
$args = array(
  'post_type' => 'post',
  'post_status' => 'publish',
  'posts_per_page' => 5
);
$query->query($args);
if(!empty($query->posts)):
  ?>
  <h4>Why not take a look through the most recent posts?</h4>
  <ul class="posts-list">
  <?php echo frl_list_posts($query->posts);?>
  </ul>
<?php endif;?>
In this part we perform a query for the 5 most recent posts in the blog and output them in the same manner as previously.
The last chance:
<!-- Search options -->
<?php $home_link = home_url(); ?>
<h4>No good?</h4>
<p>Please use the search form to try again or start browsing from the <a href='<?php echo $home_link;?>'>Homepage</a>.</p>
<p>If you need further assistance please don't hesitate to contact at <em>info@domain.com</em>.</p>
<?php get_search_form();?>
Finally, if none of the above options satisfy the user, we offer a link to the homepage and provide a search form.

Preventing 404 errors on your site

It seems that we have done our best to help the visitor on the 404-error page. Actually, the best help there is to prevent the 404 page ever being used. In particular, we can:
  • set up well-structured permalinks from the start of project, so it is less likely there will be any need to change them in the future;
  • monitor incoming links that are incorrect, contact owners of the websites where such links appear, with a request to correct them;
  • take care of the old content, don’t remove it until it’s absolutely necessary, and set up proper redirection on page migration.
There’s no real excuse why your site or blog should not have a helpful and user-friendly 404-error page. I hope, that this guide has given you some helpful tips.

No comments:

Post a Comment