中文 · English
又一個引擎優化。差別是:每條規則都附出處。
SEO → AEO → GEO → LLMO,縮寫每季都在增加。這個 repo 不打算再發明一個, 它只做一件事:把「網站對搜尋引擎與 AI 引擎的可見度」變成可以逐條檢查、 而且每條都查得到依據的東西。
Search Engine Optimization(SEO)、Answer Engine Optimization(AEO)、 Generative Engine Optimization(GEO)、Large Language Model Optimization(LLMO) ——四個縮寫講的是同一件事的不同切面:那台機器看不看得見你的內容、讀不讀得懂、 願不願意引用。 差別只在「那台機器」是搜尋引擎、問答引擎,還是語言模型。
市面上的 SEO skill 很多,但有兩個常見問題:
① 無來源的百分比宣稱。 「加上 FAQ schema 可提升 30% 點擊率」這類數字大量流傳, 往回追常常找不到任何原始研究。本 repo 的規則要嘛來自 Google 官方文件, 要嘛來自同行評審論文,要嘛明白標示「從業共識,證據弱」。 不確定的規則寧可標弱,不要加數字。
② 用英文的門檻檢查中文網站。 <title> 60 字元、description 160 字元
是英文的經驗值。套到中文會把一整批正常的標題判成過長——中文的資訊密度不同。
本檢核器偵測中日韓字元比例後切換門檻。
同一個「兩種語言的基準本來就不對稱」也用在別處。L1-LANG-CONTENT-MISMATCH
比對「宣告的語言」與「正文實際的語言」,而它的判準刻意單向:宣告英文卻整塊
中日韓可以報,宣告中文卻整塊拉丁不能報——中文頁出現品牌名、程式碼、縮寫
是常態,反向套用會整批誤判。
不是漏了。查過了(2026-08-17),結論是沒有可以當依據的實證。
① 同行評審文獻裡的 LLMO 是另一件事。 arXiv 上 LLMO 指的是 Large Language Model Optimizer,也就是「用 LLM 去做最佳化」的方法: 黑箱網路管理最佳化(2507.02689)、 對抗式強健性架構搜尋(2406.05433)。 跟網站可見度無關。
② 回顧 45 篇研究(2023-11~2026-07)的批判性綜述,全文沒有出現 LLMO (2607.14035)。一份回顧整個領域三年的綜述 完全不提這個詞,是相當強的反面證據。
③ 以「為 LLM 回答優化內容」這個意思使用 LLMO 的內容,目前全是廠商部落格, 而它們流傳的數字正好是本 repo 開頭反對的那一類:「原創統計數據可提升 30–40% 可見度」、「AI 搜尋來的訪客價值是自然搜尋的 4 倍」——往回追都找不到原始研究。
底層那個問題(內容怎麼被 LLM 撈到、讀懂、引用)確實有文獻,但它們一律歸在
GEO/AEO 之下,已經由 L3-GEO-* 與 SITE-* 涵蓋。
LLMO 不是一個缺口,是同一批研究的另一個行銷標籤。
所以規則按「看不看得見、讀不讀得懂、願不願意引用」來分,不按縮寫分。 再多幾個縮寫,這個分法也不用改。
完整查證紀錄(跑過的查詢、否決理由、要重看的條件)在
watch/investigated.json。 留紀錄的目的是不要重複搜:沒通過門檻的東西如果不寫下來,下一個人會把 同一輪搜尋再跑一次,而且看不到上次否決的理由。sources.json記的是通過門檻的出處,這一份記的是沒通過的。
| 路徑 | 是什麼 |
|---|---|
skills/seo-aeo-audit/ |
Claude Code skill:四層檢核 + 59 條規則(L1 13/L2 29/L3 4/SITE 13) |
skills/seo-aeo-audit/scripts/seo-check.mjs |
零相依的靜態檢核器(Node,不需 npm install) |
skills/seo-aeo-audit/scripts/psi-check.mjs |
PageSpeed Insights 包裝(需自己的 API key) |
skills/seo-aeo-audit/test/ |
回歸測試。只有判準出過問題的規則才有,理由見〈哪些規則值得寫測試〉 |
watch/ |
定期檢索:出處是否失效、爬蟲清單是否變動、生態是否有新縮寫 |
每一條規則的完整索引在
skills/seo-aeo-audit/SKILL.md的〈完整規則索引〉 ——代碼、級別、是什麼,一條不漏,不必去讀 45 KB 的腳本。「59」數的是不重複的規則代碼,而且由
test/rule-index.test.mjs守著—— 新增規則卻沒補進索引,測試會失敗並指名漏了哪幾條。⚠ 這個守衛是補的。索引第一版宣稱「一條不漏」卻漏了 4 條,因為當時的抽取腳本 只認
add('warn', 'CODE',把所有嚴重度隨條件變動的規則 (add(isNoindex ? 'info' : 'warn', 'CODE')整類漏掉——而驗證腳本共用同一個 假設,於是「雙向驗過」得到的通過毫無意義。用有相同盲點的工具驗證,等於沒驗。
| 層 | 內容 | 判定 |
|---|---|---|
| L1 技術基礎 | title/description/canonical/OG/lang/sitemap/robots | 全自動 |
| L2 內容結構 | 正文可見量、heading 階層、空標題、假標題、alt、內部連結、JSON-LD | 全自動 |
| L3 AI 可見度 | 站層級可達性(SITE-*)+ 頁層級可引用性(L3-*) |
半自動 |
| L4 YMYL/E-E-A-T | 作者資訊、專業佐證、共識一致性 | 人工判讀 |
先 build(檢核的是爬蟲看到的建置產物,不是原始碼):
npm run buildnode skills/seo-aeo-audit/scripts/seo-check.mjs --dir ./dist --site https://example.com在 Claude Code 裡則把 skills/seo-aeo-audit/ 放進 ~/.claude/skills/,
之後說「檢查這個網站的 SEO」就會自動觸發。
node skills/seo-aeo-audit/test/dead-link.test.mjs
node skills/seo-aeo-audit/test/bilingual-concat.test.mjs
node skills/seo-aeo-audit/test/lang-content-mismatch.test.mjs
node skills/seo-aeo-audit/test/rule-index.test.mjs
node skills/seo-aeo-audit/test/i18n-dict.test.mjs零相依、直接跑,輸出是給人看的(每個情境印出在測什麼)。
也可以用 Node 內建的 test runner 拿彙總數字(node --test <檔案>),
但別給目錄——node --test <目錄> 在 Node 24 實測會直接失敗,
而各支測試單獨跑都是通過的。症狀看起來像測試壞了,其實是呼叫方式。
① 檢核建置產物,不是原始碼。
兩者可以完全不同。實例:某頁的經歷描述用字串插值輸出,HTML 裡是
<a href=...> 的字面文字——使用者看得到正常的連結(JS 載入後重繪過),
但爬蟲拿到的是轉義後的純文字,9 個外連對它們等於不存在。
② 這支腳本不執行 JS——這是特性不是限制。 爬蟲與 LLM 多數也不執行。腳本看到空的,它們就看到空的。
③ 弱訊號不寫成 error。
L3-GEO-* 只報 info,而且不給目標數字——論文說的是「加了會提升可見度」,
不是「沒加就是錯」,也沒有提供閾值。
④ 誤判要回頭修腳本,不是把門檻調寬到不再觸發。
SITE-DEAD-INTERNAL-LINK 曾在採 clean URL 的靜態主機上誤判率 67%:連結寫
/gallery、輸出檔是 gallery.html,永遠對不上。Cloudflare Pages、Netlify、
GitHub Pages 全部預設支援 clean URL——而它是 error 級。
一條 error 整批誤判比漏報更糟:漏報只是少看到一個問題,整批誤判會讓使用者
不再相信整份報告。
它潛伏那麼久的原因值得記下來:開發時用的網站是 directory 輸出
(/a/b/index.html),那是唯一它本來就正確的模式。
在唯一測過的環境裡,它從第一版起就是對的。
一條規則能潛伏多久,取決於你只在一種環境測它。
改法是把方向倒過來:原本猜「連結該長什麼樣」(把 /gallery 正規化再比對),
改成先算出每個輸出檔實際到得了的所有網址形式,再看連結有沒有命中。
前者要窮舉使用者的寫法,後者只要窮舉主機的行為——後者的集合小得多,
而且是查得到的事實。
不是每條規則都有測試,判準是:它錯的時候,會不會讓人不再相信整份報告, 或把人導向錯誤的修法。 看的不是規則多複雜。
而且修「誤判」有一個假解法,長得和真解法一模一樣:把規則放寬到不再觸發, 報告上看起來就像修好了,誤判確實消失了。所以每個測試都在各情境埋一條真的 該報的,斷言「只報這一條」——少報和多報都會失敗。
目前有測試的五項,各自出過不同的事:
| 規則 | 出過什麼事 |
|---|---|
SITE-DEAD-INTERNAL-LINK |
在 clean URL 主機上整批誤判,而它是 error 級 |
L2-BILINGUAL-CONCAT |
數字一直是對的,但把兩種修法完全不同的狀況混在一起 |
L1-LANG-CONTENT-MISMATCH |
判準刻意不對稱,最容易被後人「順手改成對稱」 |
L2-I18N-DICT-* |
「英文欄位裡是中文」——任何「有沒有填」的檢查都會判它通過,只能比對值本身 |
| 〈完整規則索引〉與文件計數 | 宣稱「一條不漏」卻漏 4 條;之後小節標題、出處筆數也各漂過一次 |
L2-BILINGUAL-CONCAT 混在一起的是這兩種:
| 狀況 | 性質 | 怎麼辦 |
|---|---|---|
| 同一份內容的中英兩版同時在 DOM 裡 | 架構 | 改成獨立語言 URL |
| 英文頁上還沒翻譯的內容退回中文 | 內容進度 | 翻完自然消失 |
加判準時試錯兩次,兩次都是靠標記判斷——「有沒有 lang 屬性」會把第一種
一起消掉(常見雙語元件兩半都帶 lang);「兩邊都宣告且語言不同」會漏掉用
class="zh-only" 而不帶 lang 的手刻頁。最後改成靠內容:相鄰兩元素,
前者主要中日韓、後者主要拉丁。所以那個測試的重點不是數字對不對,
是三種不同的標記方式都要判對。
L1-LANG-CONTENT-MISMATCH 的測試有一半是反向斷言:機構名出現在英文頁的
連結裡、中文技術文章含大量程式碼與品牌名、通篇英文——這三種都必須保持安靜。
不對稱的判準沒有反向斷言守著,遲早會被改成對稱,然後整批誤判。
一份檢核報告最容易造成的誤解,是讓人以為「全綠=做完了」。所以這裡把 天花板寫清楚。三件事都有出處,而且都在這支腳本的視野之外。
① 大多數引用失敗是語意問題。 arXiv 2603.09296 把引用失敗分成四類, 在它的樣本裡:技術完整性 10.1%、語意對齊 62.2%、內容品質 27.1%、 系統性排除 0.6%。佔比最大的那一類——意圖分歧、脈絡缺口、資訊過時—— 需要知道使用者想搜什麼、競爭對手寫了什麼,都不在一份 HTML 裡。 (這些百分比是該篇樣本的分佈,不是普世常數。)
這和下面那個「結構欄位 +22%」不衝突:62.2% 說的是引用失敗的原因分佈, +22% 說的是優化結構欄位對被檢索到的效果。一份頁面可以順利被撈進候選集, 然後在生成答案時因為答錯了問題而沒被引用。兩個數字擺在一起容易讀成矛盾—— 先確認它們講的是管線的哪一段。
② 站外訊號,而且它可能比站內更重要。 arXiv 2509.08919(1,000 個查詢、四個引擎) 量到 AI 搜尋對第三方來源的壓倒性偏好:消費電子 92.1%、軟體 74.2%、 汽車 69.1%,而 social 內容在兩個領域是 0%。 另一篇發現有預測力的是 referring domains (+0.319)與社群聲量(+0.395),GEO 分數與被發現率零相關。
這份報告全過,仍然可能因為沒有第三方報導而不被引用。
那該怎麼辦?這一層的工作不是改頁面,是讓別人有東西可以引用你:原始數據、 可複製的方法、明確的立場。這支腳本能幫的是確保那些內容爬蟲讀得到、結構清楚、 有出處——別人想引用你的時候不會被技術問題擋住。剩下的是內容與關係的工作。
⛔ 不要用互連衝這個數字。 行銷公司常見的做法是讓手上客戶的網站互相連結, 把「有多少網站連到你」拉高。這不是「未來可能被罰」的灰色手法—— Google 垃圾內容政策 的〈Link spam〉一節已經明文列舉:
"Excessive link exchanges ("Link to me and I'll link to you") or partner pages exclusively for the sake of cross-linking"
而且對個人與小團隊來說這條路本來就走不通,它需要一批可控的網站。
③ 訓練語料圈。 arXiv 2601.00869 發現決定品牌能不能被推薦的是 訓練資料的地理來源,不是查詢語言:同樣的英文查詢,中文 LLM 品牌提及率 88.9%、國際模型 58.3%;案例品牌在中文 LLM 65.6%、國際模型 0%。 這給雙語一個 SEO 之外的理由——出英文版是進入另一個訓練語料圈—— 但語料收錄不在建置產物裡,檢核器看不到。
反過來說,站內這一段是有實測支持的。 arXiv 2602.12187(SAGEO Arena)把 title/description/H1–H6/JSON-LD 當成分開索引的欄位,比較「只優化結構欄位」 與「只優化正文」:前者 +22% Hit Rate、檢索排名 +2.72,後者一致退化 (其中一套自動改寫方法讓檢索掉 36%)。
這值得標出來,因為綜述說 GEO 的證據 碰不到「會不會被撈到」。這篇碰到了,而且量的正是 L1/L2 在檢查的東西。
市面上關於 GEO 的建議常常互相矛盾。把研究攤開看,矛盾大多來自沒有分清楚 改的是哪一層、影響的是哪一步:
| 你動的東西 | 影響哪個階段 | 效果 | 出處 |
|---|---|---|---|
| 換句話、調字詞、表層改寫 | 引用 | 極小,甚至有害(−14%、−36%) | 2605.25517、2602.12187 |
| title/description/H1–H6/JSON-LD | 被撈到 | +22% Hit Rate、排名 +2.72 | 2602.12187 |
| 統計數據、引用來源、獨特資訊 | 引用 | 顯著;消融中這兩項貢獻最大 | 2604.19113、2311.09735 |
這也是為什麼本檢核器分層而不是給一個總分:三層的證據強度不一樣,能做的
判定也不一樣。 L1/L2 敢報 error,L3 只報 info 且不給目標數字,
L4 交給人判讀。
一個實際的例子:有一類自動改寫工具的做法是讓語言模型解釋「引擎偏好什麼」, 再照那些解釋改寫正文。SAGEO Arena 實測那套做法讓檢索掉 36%—— 它優化的是第一層(表層改寫),代價卻付在第二層(被撈到)。
| 來源 | 用在哪 |
|---|---|
| Google Search Quality Rater Guidelines(2025-09-11 版) | L4 全部頁碼依據 |
| GEO: Generative Engine Optimization(Aggarwal et al., KDD 2024,現為 v3) | 五戰術與 L3-GEO-* |
| A Critical Survey of GEO (2023-2026)(回顧 45 篇) | L3-GEO-* 的證據強度限定 |
| What Gets Cited(252,000 次試驗) | L3-GEO-* 為何不給目標數字 |
| SAGEO Arena(結構欄位 +22% Hit Rate) | L1/L2 在檢索階段的實測支持 |
| FeatGEO(13 維特徵、有 ablation) | L3-GEO-* 三項訊號的逐特徵消融 |
| Diagnosing and Repairing Citation Failures | 靜態檢核的天花板;不執行 JS 的旁證 |
| The Discovery Gap(112 個新創、2,240 次查詢) | 四層的排序;LLMO 0 條的第四條證據 |
| How to Dominate AI Search(1,000 個查詢) | 站外訊號碰不到(earned media 69–92%) |
| The Existence Gap | 為什麼雙語不只是 SEO 問題 |
| Ahrefs llms.txt 研究(137,210 網域) | llms.txt 97% 零抓取;編碼代理是唯一明顯消費端 |
| Google Search Central 官方文件 | L1/L2 多數規則 |
只列主要的幾筆。watch/sources.json 有 23 筆完整紀錄,其中兩筆的
usedBy 刻意留空——geo-sfe-2026 與
e-geo-2026 記錄的是證據衝突,不是任何規則的依據。
查證過但沒通過門檻的主題另存在 watch/investigated.json
(目前 6 筆)。那份檔案的用途是不要重複搜:沒通過的東西如果不寫下來,
下一個人會把同一輪搜尋再跑一次,而且看不到上次否決的理由。
watch/sources.json 是機器可讀的完整清單,由 GitHub Actions 每月檢查是否失效。
規則會過期,而過期的症狀是靜默的——檢核器照跑、報告照出,只是依據已經不成立了。
所以 watch/ 每月做兩件事,結果開成 issue,只報告、不自動改規則
(要不要跟著改是需要讀原文判斷的事):
| 檢查 | 怎麼偵測 | |
|---|---|---|
| ① | 出處還在不在、有沒有悄悄改版 | 依來源性質分三種模式:PDF 比檔案大小、arXiv 比版本號、Google devsite 比頁面自帶的 Last updated |
| ② | AI 爬蟲清單有沒有變 | 正向:清單裡的名稱是否仍在官方文件裡;反向:文件裡有沒有清單外的新爬蟲 |
| ③ | 有沒有出現我們還不知道的東西 | 掃 Google Search Central 部落格與 arXiv 的 GEO/AEO 論文,交給模型篩出「值得回去讀原文」的項目 |
②的反向檢查在 2026-08 首跑時抓到三支清單外的爬蟲(OAI-AdsBot、
Google-CloudVertexBot、meta-externalads)。三支都經查證後刻意不納入規則——
前兩支只抓站長自己提交或要求的內容,第三支屬廣告生態,都不影響 AI 回答的引用
與訓練同意。理由逐支記在 watch/crawlers.json,這樣下個月不會再被當成新發現重報。
③是整個 repo 最危險的一步——讓語言模型讀部落格再吐結論,正好是這個 repo 反對的做法。所以它的產物明確定義為「線索」不是「規則」:只列出值得回去讀 原文的項目、一律附原始連結、不產生任何規則文字、不改任何檔案,並且在報告裡 標明是哪個型號判讀的——判讀要能追溯到判讀者。
型號也不寫死:CF_AI_MODEL 優先,沒設就查當下的型號清單自動挑,並印出實際
用了哪一個。寫死等於埋一個「供應商下架那天才會炸」的地雷。
需要的環境變數(都是選填,沒設時對應的檢查會標成「本次未檢查」而不是顯示綠燈):
| 變數 | 用途 |
|---|---|
CF_ACCOUNT_ID/CF_API_TOKEN |
Browser Rendering(Meta 的爬蟲文件對一般抓取回 400,要真瀏覽器)+ Workers AI(③的判讀) |
CF_AI_MODEL |
覆寫自動挑選。建議留空 |
Token 權限:Workers AI · Read+Workers AI · Edit+Browser Rendering · Edit。
MIT。規則的出處各有其授權,引用時請依原始來源標註。