BreadcrumbList 麵包屑標記:讓搜尋結果顯示網站路徑
BreadcrumbList 讓搜尋結果把 一長串網址換成可讀的網站路徑:
✗ https://example.com/seo/schema-breadcrumb
✓ 前端工程文件 › SEO › 結構化資料2
這是投報率相當好的一個型別,實作簡單,而且它是 複合式搜尋結果 中少數仍然穩定顯示的。
本頁就是示範
這一頁的檔頭真的有這段標記
{
"@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"
}
]
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
用瀏覽器的「檢視網頁原始碼」搜尋 BreadcrumbList 就能看到它(網域會依環境替換)。
結構
| 欄位 | 必要性 | 說明 |
|---|---|---|
itemListElement | 必填 | ListItem 的陣列 |
ListItem.position | 必填 | 第幾層,從 1 開始且連續 |
ListItem.name | 必填 | 這一層顯示的名稱 |
ListItem.item | 建議 | 這一層的網址,最後一項可省略 |
position 必須從 1 開始且連續
跳號或重複會讓整組標記無效
// 錯誤:從 0 開始
"position": 0
// 錯誤:跳號
[{ "position": 1 }, { "position": 3 }]
// 錯誤:重複
[{ "position": 1 }, { "position": 1 }]2
3
4
5
6
7
8
這是最容易犯的錯誤,尤其在 插入新層級卻忘了重新編號 的時候。
用程式產生就不會有這個問題:
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}`,
})),
};
}2
3
4
5
6
7
8
9
10
11
12
最後一項的網址
最後一項就是 目前所在的頁面,網址可以省略:
// 兩種寫法都合法
{ "@type": "ListItem", "position": 4, "name": "目前這一頁" }
{ "@type": "ListItem", "position": 4, "name": "目前這一頁", "item": "https://example.com/current" }2
3
用程式產生時填上比較單純
省略最後一項的網址需要特別處理陣列的最後一個元素。直接全部填上,程式碼更乾淨,而且完全合法。
搭配看得見的麵包屑
只有標記也可能取得路徑呈現,但 建議兩者都做:
<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>2
3
4
5
6
7
8
| 為什麼兩者都做 | 說明 |
|---|---|
| 對使用者有用 | 知道自己在網站的哪個位置,也提供往上一層的捷徑 |
| 標記與內容一致 | 符合 結構化資料必須對應真實內容 的原則 |
| 額外的內部連結 | 每一層都是一個往上的 內部連結 |
用 ol 而不是 ul
麵包屑是 有順序 的,用 <ol> 才對。搭配 <nav aria-label> 讓螢幕閱讀器認得出這是麵包屑導覽。
最後一項不是連結(因為就是目前這一頁),用 aria-current="page" 標示。
樣式上用 CSS 加分隔符號,不要寫在 HTML 裡:
.breadcrumb li + li::before {
content: "›";
margin: 0 0.5em;
color: var(--vp-c-text-3);
}2
3
4
5
分隔符號不要放進標記
// 錯誤:分隔符號不是名稱的一部分
"name": "› 結構化資料"2
與網址階層一致
三個地方應該說法相同:
| 位置 | 本頁的內容 |
|---|---|
| 網址 | /seo/schema-breadcrumb |
BreadcrumbList | 前端工程文件 › SEO › 結構化資料 › 麵包屑 BreadcrumbList 標記 |
| 看得見的麵包屑 | 這個站沒有,見下方說明 |
這個站只做了三者中的兩個
版面上沒有麵包屑元件,側邊欄已經表達了同一份階層,再加一條麵包屑是重複的導覽。
這不會讓標記失效,如同前一節說的,只有標記也可能取得路徑呈現。但它確實少了一項對使用者的價值,也少了一組往上層的內部連結,屬於刻意的取捨而不是最佳解。
這也是全站採用前綴式檔名的理由之一
這個站每個主題都用同一套命名:schema.md 當分類總覽、schema-breadcrumb.md 當子頁,子頁的 slug 前綴與父頁完全相同(CSS 的 performance-*、Vue 的 component-* 也是同一套)。
這讓 網址階層、目錄排序、麵包屑 三者天然一致,不必額外維護一份對照表。
不一致時搜尋引擎會收到矛盾的資訊,也讓使用者困惑(網址看起來在 A 分類,麵包屑說在 B 分類)。
一頁多組麵包屑
同一個商品掛在多個分類下時,可以標記 多組路徑:
<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>2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
搜尋引擎會自己挑一組顯示。
實務上單一路徑比較單純
多組路徑要面對「頁面上要顯示哪一條麵包屑」的設計問題。單一主要路徑加上 canonical 處理重複網址,通常是更好的選擇。
這個站的實作
SEO 系列的骨幹頁面(入口頁、各分類總覽頁與這一篇)都有 BreadcrumbList。層級對應 sidebar 的階層:
| 頁面類型 | 麵包屑 |
|---|---|
| 入口頁 | 前端工程文件 › SEO 是什麼 |
| 分類總覽頁 | 前端工程文件 › SEO › 分類名 |
| 分類子頁 | 前端工程文件 › SEO › 分類名 › 本篇 |
這是全站慣例的一個例外
其他主題的文章都只有 Article 與 FAQPage 兩段標記。SEO 系列的骨幹頁多一段 BreadcrumbList 是刻意的,一個講 SEO 的主題,本身該是站內的最佳實踐示範。
檢查清單
| 項目 | 標準 |
|---|---|
position 從 1 開始 | 必備 |
position 連續不跳號 | 必備 |
每一項都有 name | 必備 |
item 為絕對網址 | 必備 |
分隔符號不在 name 裡 | 必備 |
| 頁面上有看得見的麵包屑 | 建議 |
用 <ol> 而非 <ul> | 建議 |
| 與網址階層一致 | 建議 |
| 由程式產生而非手寫 | 建議 |
| 通過 複合式搜尋結果測試 | 建議 |
常見問題
頁面上一定要有看得見的麵包屑嗎?
不是硬性規定,只有標記也可能取得路徑呈現。但建議兩者都做:看得見的麵包屑對使用者有用,也讓標記與頁面內容一致,符合結構化資料必須對應真實內容的原則。
position 要從 0 還是 1 開始?
從 1 開始,而且必須連續。中間跳號或重複會讓整組標記被判定無效。這是最容易犯的錯誤之一,尤其是在插入新層級卻忘了重新編號的時候。
最後一項要不要放網址?
可以省略。最後一項就是目前所在的頁面,省略網址是合法的寫法。不過填上自己的網址也完全沒問題,而且用程式產生時填上比較單純,不必特別處理最後一項。
麵包屑要跟網址階層一致嗎?
強烈建議一致。網址 、看得見的麵包屑、結構化資料三者說法相同時,位置訊號最清楚。不一致時搜尋引擎會收到互相矛盾的資訊,也讓使用者困惑。
一頁可以有多組麵包屑嗎?
可以。同一個商品掛在多個分類下時,標記多組路徑是合法的,搜尋引擎會自己挑一組顯示。但實務上單一路徑比較單純,也避免頁面上要顯示好幾條麵包屑的設計難題。