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/xmltext/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 裡塞 prioritychangefreq,主流搜尋引擎早已幾乎忽略這兩個欄位,寫了也是徒增維護負擔,把力氣放在 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)可以縮短傳輸時間,主流搜尋引擎都支援讀取壓縮版。但壓縮不是必要的,對中小型網站來說,未壓縮的檔案反而方便你隨時打開檢查內容。我的判斷標準是:檔案大到影響抓取效率再壓縮,否則保持可讀性優先,驗收時也比較省事。