網站新鮮度訊號別只加一個日期:SITE_UPDATED vs LASTMOD 拆分為什麼重要
先講重點
GEO(生成式引擎優化)audit 抓不到新鮮度通常是 schema 缺 dateModified。但全站只塞同一個 LASTMOD,會讓 19 篇沒改內文的文章 schema 假裝「今天更新」 — 這是 Google 不鼓勵的假新鮮度。拆站台部署日(SITE_UPDATED)跟文章內容日(LASTMOD)兩個常數,Perplexity 引用力從 62 升到 85。
1. 起點:audit 抓不到新鮮度,我第一個直覺是錯的
跑 GEO audit 看到 signals 拿 5/6,consistency 還掉兩分,提示寫得清楚:「No dateModified in schema」「Schema description differs from meta」。我第一個直覺很單純 — 把全站共用的 LASTMOD 常數 bump 成今天的日期,重 build,問題解決。
實際上跑完一輪之後,我看了一眼 19 篇 SEO 與 pitfall 文章的 HTML。每一篇的 Article schema 裡,dateModified 都變成今天。但我這天根本沒動那 19 篇的內容 — 我只是改了 build.py 的 head template 加新鮮度 meta。文章本身一個字都沒變。
那一刻我才意識到,我剛剛把整個站變成一個對 Google 撒謊的站。
照 Google Search Central 對 dateModified 的定義(官方文件),這個欄位應該反映「文章內容有實質修訂」的時間,不是部署時間、不是 mtime、不是「我今天有 push 過」。對沒改的文章宣稱「今天更新」,本質上跟在文末偷偷改一個日期字串騙 Google 來重爬一樣 — Google 對這種行為的判定通常是降低該頁面的新鮮度權重,因為它判斷不出來這個站「真的常更新」還是「只是 stamp 在動」。
SE Ranking 在 2025 年掃了 230 萬個被 AI 引用的頁面,結論是 3 個月內更新過的內容平均被引用 6 次、2 年以上未更新的只剩 3.9 次。新鮮度真的有用 — 但它的前提是「真的更新過」。不是日期字串。
2. 問題在於:站台跟文章是兩種不同的「東西」
我盯著 constants.py 那一行看了很久:
LASTMOD = "2026-05-29"
這個變數被用在三個位置:(1) website_schema 的 dateModified(首頁是 living page,每次部署都動)(2) page_shell 注入的 article:modified_time meta(套用在每一篇文章)(3) footer 可見的「最後更新」文字(出現在每一頁)。
問題在於這三個位置的「最後更新」不是同一個概念。首頁跟 hub 是 living page — 每次部署都會重新生成、列表更新、內鏈微調 — 它的「最後更新」就是「我最後一次 push 的時間」。但一篇 5 月 9 日寫的 PageSpeed 67→93 文章,「最後更新」應該是 5 月 9 日,不是今天。
我在 build_log 寫了一句留給自己:「LASTMOD 一個常數同時表達兩個語意,這是一個型別錯誤。」
3. 拆兩個常數,分別語意化
正解很單純:拆成兩個常數,分別表達兩個語意。
LASTMOD = "2026-05-28" # 內容基準日(文章 schema / article:modified_time)
SITE_UPDATED = "2026-05-29" # 站台部署日(首頁 / hub / footer)
接著把使用位置對齊語意:website_schema 的 dateModified → SITE_UPDATED(首頁是 living page,誠實);page_shell 的 article meta(只在 article 頁注入)→ 還是 LASTMOD(先暫用一個內容基準日,逐篇真實日期是 #19 重構);footer 可見的「站台更新」標籤 → SITE_UPDATED。og:updated_time 全站都注入,用 SITE_UPDATED,因為它本來就是「這個頁面什麼時候被重新部署的」。
footer 文案我從「最後更新」改成「站台更新」。原因是文章頁本身有自己的「最後更新:YYYY-MM-DD」(在 meta line),如果 footer 也叫「最後更新」、值卻不一樣,讀者會看到兩個日期都叫同一個名字、卻顯示不同的日子,這對信任是負分。改成「站台更新:YYYY-MM-DD」就清楚多了 — 一個是文章本身的、一個是整個站台的最後一次部署。
4. 套完之後,audit 跟 AI 引擎怎麼反應
部署完重跑 GEO audit:
| 指標 | 改前 | 改後 |
|---|---|---|
| signals(freshness) | 5/6 False | 6/6 True |
| schema_desc_matches_meta | False | True |
| consistency 缺失 | 2 項 | 0 項 |
| brand_entity | 5/10 | 6/10 |
| Perplexity 引用力 | 62 | 85 |
| 總分 | 76 | 78 |
Perplexity 從 62 升到 85(+23)是這次最讓我意外的一塊。其他平台變化都小:ChatGPT 70 沒動、Google AI 80 沒動。但 Perplexity 對新鮮度訊號顯然有特別重的權重 — 這跟它的產品定位有關,Perplexity 主打「即時、引用最新來源」,所以它的 ranker 對 dateModified 跟 article:modified_time 比其他引擎更敏感。
Ahrefs 在 2025 的研究指出 AI 助手平均引用比傳統 organic search 結果新 25.7% 的內容。這個數字蓋過所有平台平均,但實際上是 Perplexity / ChatGPT 把均值拉上來、Google AI Overviews 對舊內容相對寬容。所以如果你寫的是 evergreen 主題、目標是被 Google AIO 引用,新鮮度沒那麼決定性;如果你目標是 Perplexity 跟 ChatGPT,新鮮度訊號是必修。
5. 還沒解的問題:文章 dateModified 還是統一的
這次重構解掉了「站台 vs 文章」的概念混淆,但沒解掉「19 篇文章共用 LASTMOD」這件事。pagespeed-67-to-93 可見的「最後更新」是 5 月 9 日,但它的 Article schema 還是抓 LASTMOD = 2026-05-28 — schema 跟可見不一致。
這個問題的乾淨解法不是再 bump LASTMOD,是把每一篇文章的真實日期當作一筆資料管理。下一篇(#19)會講我怎麼把這 41 篇文章拆出一個 article_dates.py registry、用單一注入點清掉嵌入舊日期、做 4-way 一致性驗證(可見 == Article schema == og meta == registry)。重構之後 LASTMOD 退回成「fallback 預設值」,文章用自己的真實日期。
▸ 常見問題
Q1:我可以只把 LASTMOD 改成 mtime 自動取嗎?
不能直接這樣做。mtime 反映檔案的最後修改時間,但 build pipeline 會在每次部署時動到所有 HTML 檔(即使你只改了 CSS),最終結果還是「每篇都今天」。要拿 mtime,至少要拿「source 端」的 mtime — 但即使這樣也有問題:你重構 build.py 的時候會動所有 builder 函式,文章內容沒變但 mtime 變了。最乾淨的還是手動 registry(下一篇 #19 完整講)。
Q2:拆兩個常數會不會讓我之後忘記哪個該動?
我用一句話約定:「我有沒有改某一篇文章的內文?沒有 → 只動 SITE_UPDATED。有 → 兩個都動,並且去 article_dates.py 把那一篇的 modified 也 bump。」這個約定可以寫進 build commit message template 提醒自己。比起記憶「今天該不該動 LASTMOD」,記憶「我改了什麼」更可靠。
Q3:Google 真的會懲罰假新鮮度嗎?
「懲罰」這個字太重。Google 不會主動降權重,但它的 freshness ranker 會學習「這個站 stamp 動但內容不動」的 pattern,逐漸把新鮮度訊號的權重在這個站身上調低。長期下來等於是「明明每次部署都標今天,但搜尋結果還是抓不到新鮮度紅利」。比起被「懲罰」,更精確的描述是「訊號失效」 — 你的 freshness 訊號被 Google 內部 normalize 掉了。
Q4:Perplexity 為什麼對新鮮度反應這麼大?
Perplexity 的產品定位是「即時 answer engine」,實務上對新鮮度反應比另外兩家大。至於它內部 retrieval 怎麼運作、是不是真的用 dateModified 設門檻過濾,Perplexity 沒公開,我無法驗證 — 我能講的只有 audit 工具給它的分數對新鮮度跳得最明顯(+23),真實引用率怎麼變我看不到。
新鮮度訊號別只加一個日期。站台跟文章是兩種不同的時間語意,LASTMOD 同時表達兩個語意是型別錯誤。拆 SITE_UPDATED 跟 LASTMOD 兩個常數,audit signals 5/6 → 6/6、Perplexity +23。但文章還共用一個 LASTMOD 是下一個尾巴 — 下篇 #19 講 41 篇 registry 怎麼做。
名詞解釋
- 部署(deploy)
- 把做好的網站或程式「推上線」讓所有人用得到的動作。
- GEO(生成式引擎優化)
- 讓 ChatGPT、Perplexity 這類 AI 在回答問題時引用你網站內容的優化方法,是 SEO 在 AI 時代的延伸戰場。
- 結構化資料(Schema / JSON-LD)
- 用機器看得懂的格式跟搜尋引擎說明「這頁是文章、作者是誰、何時更新」,有機會換到更豐富的搜尋結果外觀。
- 內部連結(internal link)
- 站內文章互相連的連結,幫讀者跟搜尋引擎理解「哪些內容相關、哪一頁重要」,是成本最低的 SEO 訊號。
- AI Overviews
- Google 搜尋結果頂部由 AI 生成的摘要區塊,會引用來源網站。被它引用是 GEO 的主要戰場之一。
- 自然流量(organic traffic)
- 從搜尋結果免費點進來的流量,相對於買廣告來的流量。
- ChatGPT
- OpenAI 的對話式 AI。本站常拿它跟 AI 代理對比:ChatGPT 給你答案、你自己動手;AI 代理直接幫你把事做完。
看完這篇之前先確認:
- 在意 GEO audit 分數、特別想被 Perplexity / ChatGPT 引用
- 站台架構是 living page + content article 混合(多數 blog / 紀錄站都是)
- 部署頻率比真正更新文章內容的頻率高
- 純 evergreen 內容站、幾乎不重新部署(你的 build mtime ≈ 內容變更時間,一個常數就夠)
- 用 CMS(WordPress / Ghost)每篇文章已經內建 published / updated 欄位,本來就分開
- 全站只有一頁(landing page)
- footer 跟文章 meta 都叫「最後更新」、值卻不一樣,讀者一看到立刻減分
- 改完 LASTMOD 沒同步改 SITE_UPDATED 的觸發時機(兩個常數要約定觸發時機)
- 把 dateModified 當「最後 mtime」用 — Google 在意的是內容語意變化,不是 file mtime
相關閱讀
- #14 把 /about 改造成 AI 看得懂的 entity:ProfilePage + FAQPage schema 實戰
- #17 workflow 圖書館分類落地:8 篇串成知識結構 + Pillar C 自動化日常
這篇背後的真實開發過程記錄在 Build Log。
搜尋標籤:geo、freshness、schema、datemodified、perplexity、build-in-public。
本篇為個人實驗紀錄。GEO audit 分數來自第三方工具,不同工具評分標準不同,本文做法不保證在你的網站產生相同結果,請依自身狀況驗證。教育研究用途,不構成投資建議。