2010/9/25

完美的 404

原文 The Perfect 404 by Ian Lloyd

Translated with the permission of A List Apart Magazine and the author[s]. 授權採 CC:BY-NC-SA 3.0(因為 ALA 不給商業利用。)

Bob: 我譯得很隨性,就原有的句子的意思、在描述上自由發揮了。也就是說,我不會變更作者的意思,但如果發現原意用中文不好體會,就會改用容易體會的方法換句話說。所以總之,相當程度上,我在改寫。但,翻譯原本就是改寫了,我並不真的是信達雅的信徒。

又,原文程式碼部份採「對讀者友善」的方式用了折行標記等東西,我這邊改採「對剪貼簿友善」的作法、把原文折行的部份又併回一行了。這樣比較好複製,至於如果你要印出來… well…

如果您發現哪些部份翻譯有誤,請留言指教。

糟,好像有什麼出了問題,但你也不確定是什麼 — 是你的問題、還是網站的問題?接下來又該怎麼辦?

歡迎來到 404 錯誤頁的世界。你直接輸入網址、也或許是點了某個已經年久失修的連結,向伺服器要求一份網頁,隨即發現自己身處虛擬世界中的飄渺之處。對訪客好一點的網站還會提供幫助,但大部分則就什麼事也不做、單純仰賴瀏覽器內建的功能向訪客描述目前狀況。我們當然能做得更好點,不是嗎?

對於在伺服器上設定自訂 404 頁的方法,我就不提了,建議你可以讀這些文章:

然而,我在此將針對大部分造成這種錯誤的原因,提出打造自訂 404 網頁的策略建議。

要開始著手設計,我們得先看看大眾發現自己身處 404 網頁的常見理由:

  • 打錯網址、書籤過期未更新等
  • 搜尋引擎連往過期的網址
  • 網站管理員沒發現的站內錯誤連結

這些理由都會前往同樣的地方,但處理的方法卻應該稍有不同 — 404 網頁必須針對不同狀況分別量身訂作。有些小技巧可以用來處理上述的情境,但我的第一個建議卻非常簡單…

不要指責

無論如何,都要告知訪客情況有誤,但不要指責訪客、就算你知道真的是他們的錯也一樣!這邊可用「可能」、「或許」等詞彙,別弄壞與網站訪客的關係,一旦搞砸、搞不好再也沒機會彌補了。

404 必備

除了「出錯了」的文字外,請確保錯誤訊息網頁上包含這些:

  • 通往網站首頁及網站地圖(若有此頁)的連結:最容易解放訪客的方法,這個不花腦筋的作法用不到什麼奇技淫巧。
  • 搜尋欄位:如果你的網站有搜尋功能,就放到 404 網頁上。若網站沒有搜尋功能、又常常出現 404 問題,那麼或許該弄一個來。
  • 清楚簡約的外觀:避免把網站的標準導覽元素都放到 404 網頁上。一方面你應該避免讓使用者分心,二方面在 404 網頁上放導覽元素很可能造成更新不同步的問題。你的 404 網頁若非以程式動態更新,則更新狀況很容易就落後網站其他頁面。連 404 網頁上的導覽元素都失效絕對是你最不想發生的事,尷尬!

也請避免使用術語。我的意思是,因為我們算一掛的,所以在這裡可以討論 404;不過 60 歲的阿姨逛編織網站碰上錯誤連結,來到這頁後可能就完全不瞭「404」是什麼東西。如果你想使用「Error 404」這樣的詞,那便隱晦點 — 例如放在頁尾,留它向看得懂這些電腦黑話的網路咖打聲招呼。

接著,來看看怎麼打造 404 網頁可以讓它幫你一把、而非推你一下。

聰明點

到此,我得先說清楚,這邊的技巧需要用上不少 JavaScript(你不見得可以用伺服端的程式來解決這些問題,這端視伺服器設定)。所以,記得使用 <noscript> 標籤,讓關掉 JavaScript 的訪客也能獲得妥當的訊息。如果你用伺服端程式,那便最好,可以無視瀏覽器跟網頁無障礙等等的問題,下面這些程式碼就斟酌參考。

首先,要設定一些變數:

var strReferrer=document.referrer.toLowerCase();
var blnSearchReferral = false;
var blnInsiteReferral = false;
var str="";
var strSite = "";

接著,要拿這些變數做什麼呢?

打錯的網址

網址打錯,或從過期書籤來的訪客不會有 HTTP referrer,所以要處理這種狀況的程式如下:

if (strReferrer.length==0)
{
  str+='我們猜想下列連結對您可能有用:<\/p>';
  str+='<a href="\/home.php"><img src="/images/home.gif" alt="Home Page" width="100" height="30"\/> <\/a>';
  str+='<a href="\/site-map.php"><img src="/images/site-map.gif" alt="Site Map" width="100" height="30" \/><\/a>';
  str+='<hr \/>';
  str+='<p><strong>您找不到這個網頁,或許是因為:<\/strong><\/p>';
  str+='<ol type="a">';
  str+=' <li><strong>書籤\/我的最愛過期了<\/strong><\/li>';
  str+=' <li>搜尋引擎上<strong>關於我們網站的連結過期了</strong><\/li>';
  str+=' <li><strong>打錯網址</strong><\/li>';
  str+='<\/ol>';
  document.write(str);
}

搜尋引擎連結過期

如果訪客有 referrer 值,我們可以先辨識出幾個特定的搜尋引擎(你可以依據自己的喜好調整辨識清單)。辨識後,我們拆解搜尋參數,看是否有與此次搜尋相關的頁面:

if (strReferrer.length!=0)
  {
  if ((strReferrer.indexOf(".looksmart.co")>0)||
  (strReferrer.indexOf(".ifind.freeserve")>0)||
  (strReferrer.indexOf(".ask.co")>0)||
  (strReferrer.indexOf("google.co")>0)||
  (strReferrer.indexOf("altavista.co")>0)||
  (strReferrer.indexOf("msn.co")>0)||
  (strReferrer.indexOf("yahoo.co")>0))
  {
  blnSearchReferral=true;
  //取得網址 — 切到第一個斜線為止
  var arrSite=strReferrer.split("/");
  //找出搜尋字串
  var arrParams=strReferrer.split("?"); 
  var strSearchTerms = arrParams[1];
  arrParams=strSearchTerms.split("&");
 
  strSite=arrSite[2];
  var sQryStr="";
 
  //定義不同引擎查詢關鍵字的方式
  var arrQueryStrings = new Array();
  arrQueryStrings[0]="q=";  //google, altavista, msn
  arrQueryStrings[1]="p=";  //yahoo
  arrQueryStrings[2]="ask=";  //ask jeeves
  arrQueryStrings[3]="key=";  //looksmart
 
  for (i=0;i<arrParams.length;i++)
  //跑 URL 中所有的參數
    {
    for (q=0;q<arrQueryStrings.length;q++)
    {
    sQryStr = arrQueryStrings[q];
    if (arrParams[i].indexOf(sQryStr)==0)
      {//找到搜尋關鍵字了!
      strSearchTerms = arrParams[i];
      strSearchTerms = strSearchTerms.split(sQryStr);
      strSearchTerms = strSearchTerms[1];
      strSearchTerms = strSearchTerms.replace("+", " ");
      }
    }
    }
  //告知訪客網站有誤,以及原先搜尋的詞彙
  document.write ("<p>您先前在 <a href='" + strReferrer + "' target='_blank'>" + strSite + "<\/a> <\/strong> 搜尋 「<strong>" + strSearchTerms + "<\/strong>」。然而,這個搜尋引擎可能有段時間沒來了,你找到的連結已經過期。<\/p><h2>放心,一切都好<\/h2><p>我們猜想下列連結對您可能有用:<\/p>");

接著,針對不想流失訪客的特定來源關鍵字詞,可以加上幾行識別程式。舉例來說,假如搜尋「電器」跟「設備」時你的網站排得蠻前面、但相關的網頁卻搬家了,這時你當然不想流失那些 Google 來的訪客,對吧?

if (
  (strSearchTerms.indexOf("widgets")>=0)||
  (strSearchTerms.indexOf("electronics")>=0)
  )
    {
    document.write("<a href='\/cool-widgets.htm'>我的電器設備大展<\/a><br \/>");
    }
  }
  }

當然,如果你的網站有站內搜尋功能,現在可以拿這個搜尋關鍵字來搜尋一次。站內搜尋或許能自動產生相同搜尋字詞的網頁連結,無須動用上述的工人智慧。但無論如何,建議採用工人智慧的方法,不然可能只是讓訪客多增加一次找不到網頁的機會而已。

站內失效連結

從搜尋引擎來的迷途羔羊們都關照過了,接下來就必須對付 referrer 不是從搜尋引擎來(或至少不是從你挑的那幾個引擎來)的情況。我們得再增加些條件:

if (!blnSearchReferral)
  {
  strSite = strReferrer;
  strSite = strSite.split("/");
  strSite = strSite[2];
  document.write("<p>從 <strong><a href='" + strReferrer + "'target='_blank'>" + strSite + "</a></strong> 來的這一頁已經不存在消失。<br/>建議您試試看下列連結:</p>");
  }

接著提供的連結就是首頁、網站地圖等等。

那如果你自己的網站有問題呢?

即使發現 referrer 是從自己的網站來,你也不好在 404 網頁上單單說「本網站有錯誤連結」。在這種情形下,你可能需要調整字詞,承認犯了小錯:

blnInsiteReferral =((strReferrer.indexOf("http://www.mysite.co.uk")>=0)||
    (strReferrer.indexOf("http://www.myothersite.com")>=0))
  if (blnInsiteReferral)
    {
    document.write("<p>這是我們的疏失!對您說聲抱歉,我們會揪出負責這條連結的人,在他修完錯誤後給他二十鞭。<\/p>");
    }

修正錯誤

這下我們已經提供逃離 404 黑洞的路,但真的修好了什麼東西嗎?沒有。既然已經知道訪客索求的文件網址及其來源(如果有來源),那確實還有一些事情可作。我們可以自動、或要求碰上 404 網頁的訪客按下「回報錯誤」鈕,接著把這些資訊存進資料庫裡。要求訪客手動回報可以減少雜音,確保你看到的都是最重要的錯誤連結。接著要怎麼處理這些錯誤連結,就看你了。

相關連結

想看上述建議實際運行的樣子,可以查閱下列放在 A List Apart 上的範例:

也可下載上面提的範例 404 網頁,將其依照需求修改。

沒有留言:

張貼留言

歡迎留下您的意見