I can't believe how many sites miss this trick. I was looking for a radio programme 'Loose Ends' on the BBC website. I tried www.bbc.co.uk/radio/looseends and got a 404.

Why? How difficult would it be to put the non-matching part of the URL into a search and bring up 'Sorry, we couldn't find an exact match - did you mean...' then list trip_search results or something.

If anyone can figure this out, it should go into core Drupal functionality.

A good CMS has an excellent search facility.

A good site has this search facility on every page.

When I'm looking for something on a site, as soon as it renders I instantly judge it. If I can't quickly see a search box - I hate it. If there is a ton of content on the front page - I'm not a fan. If the search is slow, or doesn't yield coherent results - I'm dissapointed. If it's Flash - I'm not impressed.

This post is a bit of a whine. Sorry!

Comments

Steven’s picture

I have such a feature on my site. Put the following code in "i404.module" and then set your 404 page in Drupal to "i404".


function i404_menu() {
  $items[] = array('path' => 'i404',
    'title' => t('Page not found'),
    'callback' => 'i404_page',
    'access' => 1,
    'type' => MENU_CALLBACK);
  return $items;
}

function i404_page() {
  drupal_set_title(t("Page not found"));
  $output = t("<p>The page you requested was not found.</p>");

  // These are words that should be ignored in the URL
  $no = array("dump", "zip", "avi", "a");

  $uri = urldecode(request_uri());
  $keys = split("[^A-Za-z]+", $uri);
  $keys = array_diff($keys, $no);
  $keys = trim(implode(" ", $keys));

  if ($keys) {
    $results = search_data($keys);
    if ($results) {
      $output .= t("<p>For your convenience, a search was performed using the query '<i>%keys</i>':</p>", array("%keys" => $keys));
      $output .= $results;
    }
    else {
      $output .= t("<p>A search was performed for '<i>%keys</i>', but nothing was found.</p>", array("%keys" => $keys));
    }
  }

  print theme("page", $output);
}

Although I have to warn you that the Drupal 4.5 search is a bit lousy. Significant improvements have been made to search already for the next release.

sgtaw’s picture

Hi Steven,

Great tool!

I need some help on it though.

I copy and pasted the code into a txt file, uploaded it to the modules folder. Activiated it.

Then in the 404 section of configuration (I'm on 4.4.1), I erased everything and just put in i404.

It doesn't work and just goes to the default page not found deal.

I also put in http://www.domain.com/i404 and got the same problem.

Can you give me a hand?

I'm now to all this.

Thanks,

Ed

xand’s picture

I'm quite sure your problems are due to the fact that you're on 4.4

upgrade!

---
www.symplification.com

geokker’s picture

That looks promising, but I couldn't get it to work - but on the intended site, I'm not using clean URL's (it breaks the html-area image uploading for me) and prefer trip_search, which I find lightning quick. I think I'll just put an apology and a search box in the default 404 page. It's the poorer option, but it'll have to do.

lazydave21’s picture

i couldn't get it to work either, in 4.5

is there something missing

Stefan Nagtegaal’s picture

Goto '?q=admin/settings' and section 'Error handling'..
Then set your 'Default 404 (not found) page:' to 'i404'.. I'm almost certain that this is fixing your problem!

xand’s picture

Just to say that i'm using it, on drupal 4.5.0, and it works. Unfortunately durpal search sucks enough that it's not really useful.

It should work as pasted above, i did edit it a little, but only to suit my site better.

---
www.symplification.com

cfelix’s picture

I think this is a bug in common.inc / menu.inc 404 handling.

It sets the active menu handler to the path "i404" and then calls menu_execute_active_handler() which just fetches the path back out of _GET[q] again.

So it can't call the i404 callback: it tries again to find q, fails and then runs its backup simple "page not found" display.

I'm new to drupal, but I think that menu_execute_active_handler shouldn't get it from _GET but should check what has been set as the active handler.

Or it might be that this i404 module won't work under the new system ? Can't see where to do it anyway.

bertboerland’s picture

imo this functionality needs to hit core once the search function is usefull (4.6)?

--

groets


bertb

--
groets
bert boerland

robert castelo’s picture

I'm using this code on some of my sites, as a PHP page, and it works - but yes, it will be a lot more useful once the search function improves.

My ideal 404 module would search the site, but if it didn't find any results, show search options followed by a site map.

[MegaGrunt]

------------------------------------------
Drupal Specialists: Consulting, Development & Training

Robert Castelo, CTO
Code Positive
London, United Kingdom
----

bertboerland’s picture

there is a feature req regarding what a good 404 should do including these options summed by you. havent got url right now but will search

--

groets


bertb

--
groets
bert boerland

netceo’s picture

Thanks for this beautiful piece of information. I am migrating a site to Drupal and was afraid my traffic will get hit the day i shift the site. But using this i can recover atleast some part of my traffic.

I have already tried this on one of my other Drupal sites, www.livepunjab.com and am satisfied with the results.

One more thing.. Can anybody tell me how to pass on the refering terms to the code so i make better use of it?

thanks again!

heine’s picture

When you move a site to drupal, set you old URLs as URL aliases.
I find nothing more frustrating then following a link and getting a page more or less reading 'Sorry we changed all the links on our website, good luck finding the page you came for'

There's hardly any technical reason why 'old' urls should stop functioning.

--
Tips for posting to the forums

brevity’s picture

Nevertheless there might be 'page not found' errors. Instead of searching the content of nodes with the incoming URL pieces I suggest searching the URL aliases!

Here's my version of ii404:

function ii404_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Perform a search when a page is not found.');
  }
}
function ii404_menu() {
  $items[] = array('path' => 'ii404',
    'title' => t('Page not found'),
    'callback' => 'ii404_page',
    'access' => 1,
    'type' => MENU_CALLBACK);
  return $items;
}
function ii404_page() {
  drupal_set_header('HTTP/1.0 404 Not Found');  // needed esp. for gsitemap to work
  drupal_set_title(t("Page not found"));
  // These are words that should be ignored in the URL
  $no = array("dump", "zip", "avi", "a", "de", "en", "html");
  $uri = $_SERVER['SERVER_PROTOCOL'];
  $uri = strtolower(substr($uri, 0, strpos($uri, '/')));
  $uri .= "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  global $base_url;
  $uri = substr($uri, strlen($base_url) + 1);
  $uri = urldecode($uri);
  $output = "<p>".t("The page you requested was not found:")." $base_url/$uri</p>";
  $output.= "<p>".t("Maybe it is still available on the")." <a href=\"http://www.formerwebserver.url/$uri\">".t("former webserver")."</a>.</p>";

  
  $keys = split("[^A-Za-z]+", $uri);
  $keys = array_diff($keys, $no);
  //$keys = trim(implode(" ", $keys));

if ($keys) {
  $where = implode ('%\' or dst like \'%', $keys);
  $where = "dst like '%".$where."%'";
  $dstsql = "SELECT * FROM {url_alias} WHERE ".$where." ORDER BY dst ASC LIMIT 0,33";
  $result = db_query($dstsql);

    if ($result) {
//      $output .= t("<p>For your convenience, a search was performed using the query '<i>%keys</i>':</p>", array("%keys" => $keys));
	  while ($data = db_fetch_object($result)) {
		$list[] = (l($data->dst, $data->src));
	  }
	  $output.= theme('item_list', $list, "Similar links");

    }
    else {
//      $output.= t("<p>A search was performed for '<i>%keys</i>', but nothing was found.</p>", array("%keys" => $keys));
    }


  print theme('page', $output);
}

}
rickvug’s picture

Search404 Module

This module is based on a lot of the code floating around this thread and others. Please contribute feature request and patches to it so that we can all use a "best of the bread" solution. Thanks.

Here are some related form discussions and other related links that I have found that may help:
http://drupal.org/node/12668
http://drupal.org/node/7570
https://svn.bryght.com/dev/wiki/CustomPageNotFoundSearchPage
http://www.settingtheworldtorights.com/node/417
-------------------------------------------------------------------
Rick Vugteveen | Image X Media (work) | Blog (personal)

-------------------------------------------------------------------
Rick Vugteveen |rickvug.com @rickvug on Twitter

jjma’s picture

Does this module work for 4.73?

Jon