1. 我驗收 sitemap.xml 時,第一眼看的不是內容而是它還活著嗎
做 SEO 這二十多年,我看過太多團隊把 sitemap.xml 當成上線前隨手產出的附件,產完就沒人再看。實際上這份檔案是我對一個網站做技術稽核時,最先打開的三個檔案之一(另外兩個是 robots.txt 與首頁原始碼)。原因很單純:sitemap 是網站主動遞給搜尋引擎的地圖,如果地圖本身是壞的,後面再漂亮的內容,爬蟲都可能繞不進去。
比起頁面內容,sitemap 的驗收更像是在做健康檢查,而不是在評分作文。它不需要華麗,只需要誠實、可存取、與實際狀況一致。以下我把驗收拆成幾個層次,從最基礎的「它能不能被打開」開始,一路談到多語系的進階標註。
1.1 sitemap 到底幫搜尋引擎解決了什麼問題
搜尋引擎的爬取資源是有限的。一個網站每天能被分配到的抓取次數(業界常稱為抓取預算),不會因為你頁面很多就無限增加。sitemap 的作用是讓爬蟲不必完全依賴一層一層點連結去發現頁面,而是直接拿到一份「這些網址請你優先看」的清單。對於新站、深層頁面多的電商、或內部連結稀疏的網站,這份清單的價值特別高。
我的實務經驗是,對一個內容更新頻繁但內部連結結構鬆散的網站,補上一份正確的 sitemap 後,新頁面被索引的速度通常會明顯改善。sitemap 不保證頁面一定被收錄,但它會縮短「頁面存在」到「搜尋引擎知道頁面存在」之間的距離。
1.2 一份合格 sitemap 的六個驗收條件
在細談之前,我先把驗收標準攤開來,方便對照。這六點是我每次交付前一定會逐條打勾的:
| 驗收項目 | 合格標準 | 驗收方式 |
|---|---|---|
| HTTP 狀態碼 | 直接存取 sitemap 網址回傳 200 | 瀏覽器開啟或用工具查看回應標頭 |
| lastmod 標籤 | 存在且反映該頁真實最後更新時間 | 抽查數筆網址比對頁面實際更新日 |
| 網址數量 | 與網站實際可索引頁數相符 | 用爬蟲全站抓取後比對筆數 |
| 最終連結 | 每筆 loc 都連到真實頁面,非中繼檔 | 抽查是否為文章或頁面而非空節點 |
| GSC 提交 | 已提交且顯示成功、無法讀取的錯誤 | Search Console 的 Sitemap 報表 |
| 多語系標註 | 含 hreflang 的 xhtml:link 對應 | 檢查 loc 內的 alternate 標註 |
2. 狀態碼 200 與可存取性:別讓地圖自己就先迷路
這是最容易被忽略、卻最致命的一關。我遇過不只一次,團隊在文件裡寫著 sitemap 網址,但實際點進去回傳的是 404 或 500,甚至被重導到首頁。搜尋引擎抓不到這份檔案,等於整份地圖不存在。
2.1 為什麼一定要是 200,而不是 301 或 302
sitemap 的網址應該直接、乾淨地回傳 200。如果它是透過 301 或 302 重導才到最終位置,部分爬蟲會處理,但這中間多了一層不確定性,而且容易和你在 robots.txt 或 GSC 裡宣告的網址不一致。我的建議是,GSC 提交、robots.txt 裡的 Sitemap 指令、以及實際可存取的網址,三者要指向同一個回傳 200 的位置,不要繞路。
順帶提醒一個常被忽略的細節:sitemap 檔案本身不應該被 robots.txt 擋掉,也不應該設成 noindex(sitemap 是 XML 檔,談不上 index,但它所指向的頁面若被 noindex 就是另一個問題,後面會談)。
2.2 用最低成本確認狀態碼的方法
我通常不會只用瀏覽器打開看到內容就算過關,因為瀏覽器可能顯示的是重導後的結果。比較可靠的做法是直接看回應標頭。用命令列一行就能確認:
curl -I https://example.com/sitemap.xml
看回傳的第一行是不是 HTTP/2 200,同時留意 Content-Type 是否為 application/xml 或 text/xml。如果狀態碼正確但內容類型是 text/html,通常代表你其實被導到了一個錯誤頁,只是那個錯誤頁本身回 200,這種假性成功最難抓,一定要看內容類型交叉驗證。
3. lastmod 要誠實,它反映的是信任而不是新鮮感
lastmod 標籤標示每一個網址的最後修改時間。這個欄位我特別在意,因為它是網站對搜尋引擎的一種承諾,而承諾一旦被發現造假,代價是信任被折損。
3.1 最常見的 lastmod 錯誤:全站同一個時間
很多自動產生的 sitemap 會把所有網址的 lastmod 都寫成「今天」,每次重新產出就整批更新。這在搜尋引擎眼中是一種雜訊。當它發現你宣稱昨天全站三千頁都更新了,實際抓下來卻幾乎沒變,它會逐漸不再把你的 lastmod 當一回事。真正該做的是,lastmod 對應到該頁「內容本身」的最後實質變動時間,而不是程式重新產檔的時間。
我在稽核時會抽查幾筆:打開 sitemap 裡標示某頁 lastmod 是三個月前,再去看那頁實際上次改動的紀錄,兩者若對得上,這份 sitemap 的 lastmod 就是可信的。若整份檔案的 lastmod 全部一致,幾乎可以斷定它沒有反映真實更新。
3.2 lastmod 的正確格式
格式建議採用 W3C Datetime,也就是含時區的 ISO 8601。單純日期是可接受的,但若能帶上時間與時區會更精確:
<url>
<loc>https://example.com/blog/seo-structure-guide/</loc>
<lastmod>2026-08-10T09:30:00+08:00</lastmod>
</url>
我不建議在 sitemap 裡塞 priority 與 changefreq,主流搜尋引擎早已幾乎忽略這兩個欄位,寫了也是徒增維護負擔,把力氣放在 lastmod 的準確度上更實際。
4. 網址數量對不對得上,是我判斷索引健康的體溫計
sitemap 裡的網址數量,應該和網站實際「希望被索引」的頁數相符。這個「相符」不是要求數字一模一樣,而是要求兩邊差距是可以解釋的。
4.1 sitemap 數量與實際頁數的三種落差
我會把落差分成三類來處理,每一類的意義不同:
| 落差情況 | 可能原因 | 處理方向 |
|---|---|---|
| sitemap 頁數遠多於實際 | 含已刪除頁、參數頁、noindex 頁 | 清掉不該被索引的網址 |
| sitemap 頁數遠少於實際 | 產檔邏輯漏掉某些模板或分類 | 補上缺漏的頁面類型 |
| 數量接近但內容對不上 | 網址大小寫、結尾斜線不一致 | 統一 canonical 網址規則 |
其中最該優先處理的是第一類。sitemap 裡若混入了 noindex 頁面,會送出自相矛盾的訊號:你一邊在地圖上說「請索引這頁」,一邊在頁面標頭說「請不要索引」。搜尋引擎收到矛盾指令時,結果往往不如預期,而且會浪費本來就有限的抓取資源。
4.2 我實際比對數量的流程
我的做法是用爬蟲工具(例如 Screaming Frog 這類全站抓取器)把網站爬一遍,得到所有回傳 200、且未被 noindex 的頁面清單,再把這份清單和 sitemap 的網址做交集比對。三個問題會浮現:哪些頁面在網站上但不在 sitemap、哪些在 sitemap 但網站上已不存在、哪些兩邊都有但 canonical 指向不同版本。把這三個名單處理乾淨,sitemap 的數量準確度就到位了。
曾經有個內容量很大的網站,GSC 一直回報大量「已檢索但未收錄」。我一比對才發現,sitemap 是舊系統產的,裡面有近四成是早就下架的活動頁。清掉之後,搜尋引擎的抓取才重新集中到真正有價值的頁面上。這種問題不靠比對數量是抓不出來的。
5. 多層多檔案 sitemap:分層可以,但最後一定要落在真實頁面
當網站頁數很多,單一 sitemap 檔案會受到限制(單檔上限是五萬筆網址或未壓縮 50MB)。這時要改用 sitemap index,也就是一份索引檔指向多份子 sitemap。這種多層多檔案的結構完全合規,但我在驗收時會特別盯一件事:每一條路徑走到最後,都必須連到真實的文章或頁面,而不是又指向另一個中繼檔卻斷在半空。
5.1 sitemap index 的正確樣貌
索引檔用的是 <sitemapindex> 根節點,底下每個 <sitemap> 指向一份子檔:
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-posts-1.xml</loc>
<lastmod>2026-08-15T10:00:00+08:00</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-products.xml</loc>
<lastmod>2026-08-18T14:20:00+08:00</lastmod>
</sitemap>
</sitemapindex>
而每一份子檔內,才是真正列出頁面網址的 <urlset>。驗收的重點是:點開 sitemap-posts-1.xml,裡面的 loc 必須是像 https://example.com/blog/xxx/ 這種會渲染出內容的頁面,而不是又一個 .xml。索引檔只能有一層,不該出現索引檔再指向索引檔的多重巢狀。
5.2 分層的合理切法與常見陷阱
我通常會建議依內容類型切子檔,例如文章一份、產品一份、分類頁一份,這樣哪個區塊出問題一眼就能定位。要避免的陷阱有兩個:一是子檔之間網址重複,同一頁出現在多份子 sitemap 裡;二是索引檔列了子檔,但某份子檔實際回傳 404。搜尋引擎讀索引檔時若發現子檔抓不到,那整批頁面就一起被漏掉了。分層帶來彈性,但也把「單點故障」的風險放大,驗收時要逐份子檔確認狀態碼。
6. 多語系網站的 sitemap:hreflang 要寫進去而不是只放在 head
經營多語系網站時,很多人只在頁面的 <head> 裡放 hreflang 的 <link>,忘了 sitemap 本身也可以、也建議帶上語系對應。把 hreflang 標註進 sitemap 有個好處:搜尋引擎不必先抓每一頁才知道語系關係,在讀地圖的階段就能理解各語言版本之間的對應。
6.1 在 sitemap 裡標註 hreflang 的正確寫法
做法是在 <urlset> 加上 xhtml 命名空間,然後每一筆 <url> 內用 <xhtml:link> 列出所有語言版本,包含自己。以繁體中文與美式英文兩個版本為例:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://example.com/zh-tw/</loc>
<xhtml:link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-tw/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/en-us/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/"/>
</url>
<url>
<loc>https://example.com/en-us/</loc>
<xhtml:link rel="alternate" hreflang="zh-TW" href="https://example.com/zh-tw/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://example.com/en-us/"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/"/>
</url>
</urlset>
這裡有幾個我會逐一檢查的重點:每個語言版本都必須列出完整的對應關係,而且要包含指向自己的那一條;各版本之間必須互相指認,不能只有 zh-TW 指向 en-US 而 en-US 沒指回來;x-default 通常指向語言選擇頁或預設語系首頁。這種對應關係只要有一邊漏掉或指錯,整組 hreflang 就可能被搜尋引擎判定無效。
6.2 sitemap 的 hreflang 與頁面 head 的關係
常有人問我,既然 sitemap 裡標了 hreflang,頁面 <head> 裡還需要嗎。我的立場是,兩者擇一實作即可,不必重複,但無論選哪一種,標註的內容一定要一致。實務上我偏好放在 sitemap,因為多語系網站頁數多,集中在一份檔案裡維護,比散落在每一頁的 head 更好管理、也更不容易出現某幾頁忘了更新的情況。真正要避免的是最糟的那種做法:所有語系共用一個網址,只靠 JavaScript 切換文字,這樣搜尋引擎只會看到一份 HTML,其他語系內容形同不存在,hreflang 寫得再漂亮也救不回來。
7. 提交 GSC 之後,驗收才真正開始
把 sitemap 提交到 Google Search Console,對很多人來說是終點,對我來說是起點。因為 GSC 會回饋搜尋引擎實際讀取這份檔案時發生了什麼,那才是驗收最有價值的部分。
7.1 提交後要盯的三個訊號
提交後在 Sitemap 報表裡,我會確認狀態顯示為成功(而非「無法擷取」),再看已探索的網址數量是否接近你 sitemap 的實際筆數。如果提交了三千筆但只探索到幾十筆,通常代表檔案格式有問題或大量網址無法存取。接著轉到「網頁索引」報表,交叉看是否有大量「已檢索但未收錄」或「找到但目前未編入索引」,這些狀態往往能反推回 sitemap 或頁面品質的問題。
7.2 把 sitemap 位置也寫進 robots.txt
除了在 GSC 提交,我一定會在 robots.txt 裡加上一行,讓沒有透過 GSC 提交的其他搜尋引擎也能發現它:
Sitemap: https://example.com/sitemap.xml
這一行放在 robots.txt 的任何位置都可以,它是獨立指令,不受 User-agent 區塊影響。我把它視為 sitemap 驗收的最後一哩,確保這份地圖不只 Google 看得到,其他爬蟲也找得到入口。
8. 常見問題
8.1 sitemap.xml 一定要放在網站根目錄嗎
放在根目錄(如 https://example.com/sitemap.xml)是最單純、也最不會出錯的做法,因為 sitemap 只能宣告與它自己同一路徑層級或更深層的網址。如果你把 sitemap 放在子目錄,它就只能涵蓋該子目錄底下的頁面。若確實需要放在別處,記得透過 GSC 提交完整網址,並在 robots.txt 用 Sitemap 指令指明位置,搜尋引擎就能正確讀取。
8.2 sitemap 裡可以放被 noindex 的頁面嗎
不建議。sitemap 的語意是「我希望這些頁被索引」,放進 noindex 頁會送出互相矛盾的訊號,也會稀釋抓取資源。正確做法是 sitemap 只收錄希望被索引、且 canonical 指向自己的頁面。登入頁、購物車、後台這類本來就不該被收錄的頁面,直接排除在 sitemap 之外。
8.3 更新一篇文章後,多久 sitemap 才會反映
這取決於你的 sitemap 是如何產生的。如果是動態產出,理想狀況是頁面一更新,對應的 lastmod 就即時變動;如果是排程產檔,就會有時間差。我的建議是讓 sitemap 的產出綁在內容發布或更新的動作上,而不是固定每天重產一次,這樣 lastmod 才會準確反映真實變動,搜尋引擎也更願意信任它。
8.4 提交 sitemap 就能保證頁面被收錄嗎
不能。sitemap 的作用是幫助搜尋引擎「發現」頁面,收不收錄是另一回事,取決於頁面本身的內容品質、是否重複、是否有足夠的內部連結與價值。我看過很多人以為提交 sitemap 就萬事俱備,結果頁面遲遲不被收錄,問題往往出在內容太薄或與其他頁面高度重複,而不是 sitemap 有錯。sitemap 負責把門打開,能不能進得去要看內容。
8.5 我該把圖片和影片也放進 sitemap 嗎
如果圖片或影片是頁面重要的內容資產,而且你希望它們出現在圖片或影片搜尋結果,是可以用專屬的 image 或 video sitemap 擴充標註的。但對多數以文字內容為主的網站,我會先把基本的網頁 sitemap 做到正確、乾淨、與實際頁數相符,再視需求評估要不要加上媒體標註。基礎沒做好之前,先加進階標註只是把複雜度往上疊。
8.6 sitemap 需要壓縮成 .gz 嗎
當單一 sitemap 檔案很大時,壓縮成 gzip 格式(sitemap.xml.gz)可以縮短傳輸時間,主流搜尋引擎都支援讀取壓縮版。但壓縮不是必要的,對中小型網站來說,未壓縮的檔案反而方便你隨時打開檢查內容。我的判斷標準是:檔案大到影響抓取效率再壓縮,否則保持可讀性優先,驗收時也比較省事。
