Skip to content

BreadcrumbList 麵包屑標記:讓搜尋結果顯示網站路徑

BreadcrumbList 麵包屑標記:搜尋結果的網站路徑

BreadcrumbList 讓搜尋結果把 一長串網址換成可讀的網站路徑

✗  https://example.com/seo/schema-breadcrumb
✓  前端工程文件 › SEO › 結構化資料

這是投報率相當好的一個型別,實作簡單,而且它是 複合式搜尋結果 中少數仍然穩定顯示的。

本頁就是示範

這一頁的檔頭真的有這段標記

json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "name": "前端工程文件",
      "item": "https://docs.incode.tw/"
    },
    {
      "@type": "ListItem",
      "position": 2,
      "name": "SEO",
      "item": "https://docs.incode.tw/seo/what-is-seo"
    },
    {
      "@type": "ListItem",
      "position": 3,
      "name": "結構化資料",
      "item": "https://docs.incode.tw/seo/schema"
    },
    {
      "@type": "ListItem",
      "position": 4,
      "name": "麵包屑 BreadcrumbList 標記",
      "item": "https://docs.incode.tw/seo/schema-breadcrumb"
    }
  ]
}

用瀏覽器的「檢視網頁原始碼」搜尋 BreadcrumbList 就能看到它(網域會依環境替換)。

結構

欄位必要性說明
itemListElement必填ListItem 的陣列
ListItem.position必填第幾層,從 1 開始且連續
ListItem.name必填這一層顯示的名稱
ListItem.item建議這一層的網址,最後一項可省略

position 必須從 1 開始且連續

跳號或重複會讓整組標記無效

json
// 錯誤:從 0 開始
"position": 0

// 錯誤:跳號
[{ "position": 1 }, { "position": 3 }]

// 錯誤:重複
[{ "position": 1 }, { "position": 1 }]

這是最容易犯的錯誤,尤其在 插入新層級卻忘了重新編號 的時候。

用程式產生就不會有這個問題:

js
function buildBreadcrumb(trail, domain) {
  return {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: trail.map((node, index) => ({
      '@type': 'ListItem',
      position: index + 1, // 索引加一,永遠連續
      name: node.name,
      item: `${domain}${node.path}`,
    })),
  };
}

最後一項的網址

最後一項就是 目前所在的頁面,網址可以省略:

json
// 兩種寫法都合法
{ "@type": "ListItem", "position": 4, "name": "目前這一頁" }
{ "@type": "ListItem", "position": 4, "name": "目前這一頁", "item": "https://example.com/current" }

用程式產生時填上比較單純

省略最後一項的網址需要特別處理陣列的最後一個元素。直接全部填上,程式碼更乾淨,而且完全合法。

搭配看得見的麵包屑

只有標記也可能取得路徑呈現,但 建議兩者都做

html
<nav aria-label="麵包屑">
  <ol>
    <li><a href="/">前端工程文件</a></li>
    <li><a href="/seo/what-is-seo">SEO</a></li>
    <li><a href="/seo/schema">結構化資料</a></li>
    <li aria-current="page">麵包屑 BreadcrumbList 標記</li>
  </ol>
</nav>
為什麼兩者都做說明
對使用者有用知道自己在網站的哪個位置,也提供往上一層的捷徑
標記與內容一致符合 結構化資料必須對應真實內容 的原則
額外的內部連結每一層都是一個往上的 內部連結

用 ol 而不是 ul

麵包屑是 有順序 的,用 <ol> 才對。搭配 <nav aria-label> 讓螢幕閱讀器認得出這是麵包屑導覽。

最後一項不是連結(因為就是目前這一頁),用 aria-current="page" 標示。

樣式上用 CSS 加分隔符號,不要寫在 HTML 裡:

css
.breadcrumb li + li::before {
  content: "›";
  margin: 0 0.5em;
  color: var(--vp-c-text-3);
}

分隔符號不要放進標記

json
// 錯誤:分隔符號不是名稱的一部分
"name": "› 結構化資料"

與網址階層一致

三個地方應該說法相同:

位置本頁的內容
網址/seo/schema-breadcrumb
BreadcrumbList前端工程文件 › SEO › 結構化資料 › 麵包屑 BreadcrumbList 標記
看得見的麵包屑這個站沒有,見下方說明

這個站只做了三者中的兩個

版面上沒有麵包屑元件,側邊欄已經表達了同一份階層,再加一條麵包屑是重複的導覽。

這不會讓標記失效,如同前一節說的,只有標記也可能取得路徑呈現。但它確實少了一項對使用者的價值,也少了一組往上層的內部連結,屬於刻意的取捨而不是最佳解。

這也是全站採用前綴式檔名的理由之一

這個站每個主題都用同一套命名:schema.md 當分類總覽、schema-breadcrumb.md 當子頁,子頁的 slug 前綴與父頁完全相同(CSS 的 performance-*、Vue 的 component-* 也是同一套)。

這讓 網址階層、目錄排序、麵包屑 三者天然一致,不必額外維護一份對照表。

不一致時搜尋引擎會收到矛盾的資訊,也讓使用者困惑(網址看起來在 A 分類,麵包屑說在 B 分類)。

一頁多組麵包屑

同一個商品掛在多個分類下時,可以標記 多組路徑

html
<script type="application/ld+json">
  [
    {
      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement": [
        { "@type": "ListItem", "position": 1, "name": "鞋類", "item": "https://example.com/shoes" },
        { "@type": "ListItem", "position": 2, "name": "跑鞋" }
      ]
    },
    {
      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement": [
        { "@type": "ListItem", "position": 1, "name": "特價", "item": "https://example.com/sale" },
        { "@type": "ListItem", "position": 2, "name": "跑鞋" }
      ]
    }
  ]
</script>

搜尋引擎會自己挑一組顯示。

實務上單一路徑比較單純

多組路徑要面對「頁面上要顯示哪一條麵包屑」的設計問題。單一主要路徑加上 canonical 處理重複網址,通常是更好的選擇。

這個站的實作

SEO 系列的骨幹頁面(入口頁、各分類總覽頁與這一篇)都有 BreadcrumbList。層級對應 sidebar 的階層:

頁面類型麵包屑
入口頁前端工程文件 › SEO 是什麼
分類總覽頁前端工程文件 › SEO › 分類名
分類子頁前端工程文件 › SEO › 分類名 › 本篇

這是全站慣例的一個例外

其他主題的文章都只有 ArticleFAQPage 兩段標記。SEO 系列的骨幹頁多一段 BreadcrumbList 是刻意的,一個講 SEO 的主題,本身該是站內的最佳實踐示範。

檢查清單

項目標準
position 從 1 開始必備
position 連續不跳號必備
每一項都有 name必備
item 為絕對網址必備
分隔符號不在 name必備
頁面上有看得見的麵包屑建議
<ol> 而非 <ul>建議
與網址階層一致建議
由程式產生而非手寫建議
通過 複合式搜尋結果測試建議

常見問題

頁面上一定要有看得見的麵包屑嗎?

不是硬性規定,只有標記也可能取得路徑呈現。但建議兩者都做:看得見的麵包屑對使用者有用,也讓標記與頁面內容一致,符合結構化資料必須對應真實內容的原則。

position 要從 0 還是 1 開始?

從 1 開始,而且必須連續。中間跳號或重複會讓整組標記被判定無效。這是最容易犯的錯誤之一,尤其是在插入新層級卻忘了重新編號的時候。

最後一項要不要放網址?

可以省略。最後一項就是目前所在的頁面,省略網址是合法的寫法。不過填上自己的網址也完全沒問題,而且用程式產生時填上比較單純,不必特別處理最後一項。

麵包屑要跟網址階層一致嗎?

強烈建議一致。網址 、看得見的麵包屑、結構化資料三者說法相同時,位置訊號最清楚。不一致時搜尋引擎會收到互相矛盾的資訊,也讓使用者困惑。

一頁可以有多組麵包屑嗎?

可以。同一個商品掛在多個分類下時,標記多組路徑是合法的,搜尋引擎會自己挑一組顯示。但實務上單一路徑比較單純,也避免頁面上要顯示好幾條麵包屑的設計難題。

延伸閱讀

參考資料:Google 搜尋中心:導覽標記結構化資料