/aeo-geo-bestpractices — SEO + AEO + GEO + Lighthouse 100 操作手冊
完整工作流程,將任何網頁或 SPA 轉變為有機發現(SEO)、答案引擎(AEO)和生成式 AI 代理引擎(GEO)的機器,同時確保在 Google Lighthouse 13(桌面與行動裝置)的五大類別中獲得 98–100 分:效能、無障礙性、最佳做法、SEO 和 Agentic Browsing。
路徑:<skill> 是此 SKILL.md 所在的資料夾。
0. 執行前的快速對齊
0.1. 偵測技術堆疊並閱讀對應指南
此檔案中的規則適用於任何網站。不同框架之間的差異(<head> 的位置、公開資料夾、預先渲染方式、圖片最佳化與避免 TBT 的方法、預覽啟動指令)記錄在 references/frameworks/ 中。透過專案識別技術堆疊,並在應用步驟 1 到 5 之前閱讀指南:
| 專案中的線索 | 技術堆疊 | 指南 |
|---|---|---|
angular.json 或 @angular/core | Angular | references/frameworks/angular.md |
next.config.* 或 next | Next.js | references/frameworks/nextjs.md |
nuxt.config.* 或 nuxt / vite.config.* + vue | Nuxt / Vue + Vite | references/frameworks/vue-nuxt.md |
astro.config.* 或 astro | Astro | references/frameworks/astro.md |
vite.config.* + react | Vite + React | references/frameworks/vite-react.md |
index.html 無框架 | 靜態 HTML | references/frameworks/html-estatico.md |
如果技術堆疊未在列表中(例如 SvelteKit、Remix、Gatsby、WordPress),請套用此檔案中的通用規則,並使用最接近的指南作為參考:具有 SSR/SSG 的框架遵循 Next/Nuxt 的邏輯;SPA 遵循 Vite + React 的邏輯。
0.2. 與使用者確認
在修改程式碼之前,請確認(或從專案中提取,如果已明確指定):
- 正式網域名稱(例如
https://meusite.com.br/)。如果尚未定義網域,請詢問或使用明確的佔位符並通知使用者。 - 可見與不可見的 FAQ(僅限 AEO/GEO):
- 詢問使用者是否希望**常見問題(FAQ)**區塊顯示在頁面佈局中(
<details>/<summary>)還是僅在幕後隱藏(在@graphJSON-LD +llms.txt+<noscript>內)以避免更改視覺設計。
- 詢問使用者是否希望**常見問題(FAQ)**區塊顯示在頁面佈局中(
- 訓練用爬蟲偏好設定(建立或修改
robots.txt時):- 檢查網站是否已定義偏好。如果沒有明確選擇,請提供兩個選項:允許搜尋並封鎖 OpenAI 和 Anthropic 的訓練爬蟲;或也允許這些訓練爬蟲。保留網站的其他規則。
1. 完整技術 SEO(index.html、robots.txt、sitemap.xml)
請查閱 [references/templates.md](./references/templates.md) 中的現成模板。
<head>中的必要 Meta 標籤:<html lang="pt-BR">(或專案語言)。- 強而有力的
<title>(50–65 個字元),包含品牌/專家名稱 + 主要提案。 <meta name="description">(140–165 個字元),清楚回答「它是什麼」、「為誰而設」以及「包含什麼」。<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" /><link rel="canonical" href="https://dominio.com/" />+<link rel="alternate" hreflang="pt-BR" ... />和x-default。- 完整的 Open Graph(
og:type、og:locale、og:site_name、og:title、og:description、og:url、og:image、og:image:width、og:image:height、og:image:alt)和 Twitter Cards(summary_large_image)。
- 對搜尋引擎和 AI 友善的
public/robots.txt:- 為了維持出現在 ChatGPT 和 Claude 搜尋中的可能性,請允許
OAI-SearchBot和Claude-SearchBot。Claude-User可以根據使用者請求抓取頁面;ChatGPT-User也由使用者觸發,但無法控制是否包含在 ChatGPT 搜尋中。 GPTBot和ClaudeBot是記錄在案的可能用於訓練內容的機器人。如果使用者選擇封鎖此類抓取,請對兩者使用帶有Disallow: /的專用群組,而不封鎖搜尋機器人。如果選擇允許,請對兩者使用Allow: /。請參閱[references/templates.md](./references/templates.md) 中的兩個變體。- 分別處理其他提供者的控制項,例如
Google-Extended。允許搜尋機器人存取可提高資格,但不保證在回應中引用或出現。更新機器人列表時,請查閱 OpenAI 指南 和 Anthropic 指南。 - 指向
Sitemap: https://dominio.com/sitemap.xml。
- 為了維持出現在 ChatGPT 和 Claude 搜尋中的可能性,請允許
- 豐富的
public/sitemap.xml(圖片 + 影片):- 當有精選圖片和銷售/示範影片時,請包含命名空間
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"和xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"。
- 當有精選圖片和銷售/示範影片時,請包含命名空間
2. AEO — 答案引擎最佳化(精選摘要、語音和無 JS 爬蟲)
答案引擎需要連接的實體和無需執行 JavaScript 即可讀取的語意 HTML:
- Schema.org JSON-LD 中的連接圖
@graph:- 與其使用零散的 JSON-LD 腳本,不如建立一個包含
@graph的單一<script type="application/ld+json">,透過@id連接實體(請參閱[references/templates.md](./references/templates.md) 中的模型):WebSite(#website)Person或Organization(#person/#org),帶有官方社交媒體的sameAsWebPage(#webpage),帶有about和mainEntityProduct/SoftwareApplication/Service(#product),帶有offersCourse(#course),當有課程/培訓/教育獎勵時VideoObject(#video),當有 VSL 或簡報影片時FAQPage(#faq),包含 4 到 6 個高搜尋意圖的真實問題,以及直接且完整的答案(每個 40–70 個字)。
- 與其使用零散的 JSON-LD 腳本,不如建立一個包含
- SPA 的語意後備
<noscript>(React / Vue / Vite):- 僅適用於沒有預先渲染的 SPA。在 Next.js、Nuxt、Astro、具有 SSR/prerender 的 Angular 以及靜態 HTML 中,HTML 已完整送達,因此
<noscript>不是必需的(請參閱技術堆疊指南)。 - LLM 爬蟲(
GPTBot、ClaudeBot、PerplexityBot、OAI-SearchBot)通常僅擷取原始 HTML,不執行 JavaScript 套件組合。 - 在
<div id="root"></div>為空的 SPA 專案中,在index.html中加入<noscript><main>...</main></noscript>區塊,包含<h1>、提案摘要、可交付項目列表(<ul><li>)以及 CTA/結帳的直接連結。 - 對效能的影響:使用
<noscript>(而不是在createRoot().render()時放置在<div id="root">內的元素),因為在沒有 SSR 的情況下將 DOM 放入#root會導致 React 在 mount 時卸載並重新建立整個 DOM 樹,從而延遲 LCP 並產生 TBT。
- 僅適用於沒有預先渲染的 SPA。在 Next.js、Nuxt、Astro、具有 SSR/prerender 的 Angular 以及靜態 HTML 中,HTML 已完整送達,因此
3. GEO 與 Agentic Browsing(Lighthouse 13 獲得 100 分)
Google Lighthouse 13 引入了 Agentic Browsing 類別,該類別稽核頁面是否為自主代理和 LLM 做好準備(llms-txt 和 ard-schema)。
public/llms.txt+<head>中的連結:- 建立結構化 Markdown 的
public/llms.txt(請參閱[references/templates.md](./references/templates.md)),包含:# 產品 / 品牌名稱> 一行價值主張摘要- 清晰的區段:
## 關於、## 包含項目、## 獎勵 / 條件、## 常見問題(AEO / GEO)、## 官方連結。
- 在
index.html的<head>中,加入:<link rel="help" type="text/plain" href="/llms.txt" title="LLMs.txt — 為 AI 提供的結構化資訊" />
- 建立結構化 Markdown 的
public/.well-known/ard.json(Agent Resource Discovery v0.91):- 在 SPA(Vite、Next 等)中,不存在的路由(例如
/.well-known/ard.json)會因後備機制而回傳index.html(<!doctype html>),導致 Lighthouse 13 的ard-schema稽核因 JSON 解析錯誤而失敗。 - 請務必建立
public/.well-known/ard.json檔案,遵循官方 ARD v0.91 schema(確切模型在[references/templates.md](./references/templates.md) 中):- 必須包含
ardVersion: "0.91.0"以及包含identifier(格式為urn:air:<dominio>:<tipo>:<slug>)、displayName、type: "application/agent-skills+md"、指向/llms.txt的url、description和representativeQueries的entries。
- 必須包含
- 在 SPA(Vite、Next 等)中,不存在的路由(例如
4. Google Lighthouse 100/100:效能與無障礙性
為在行動裝置(模擬 4G + 4 倍 CPU 限制)上達到 98–100 分,以及在桌機上達到 100 分,請嚴格套用以下規則:
4.1. LCP(最大內容繪製,行動裝置 < 2.1 秒)
<head>頂部的預載:- 將
<link rel="preload" as="image" ... fetchpriority="high">放在<title>下方(index.html的前 15 行內),優先於數十個 Open Graph meta 標籤和 JSON-LD。
- 將
- 針對 Lighthouse 行動裝置的
1.75xDPR 校準srcSet和sizes:- Lighthouse 行動裝置模擬一台 Moto G Power(寬度
412px,devicePixelRatio: 1.75)。 - 如果圖片的
sizes="(max-width: 767px) 260px, 500px",Chrome 會計算260 * 1.75 = 455w。如果srcSet中的行動裝置版本被宣告為260w(小於455w),Chrome 會忽略行動裝置圖片,並下載重量級的桌機版本! - 黃金法則:在
srcSet中將行動裝置圖片的寬度宣告為>= ceil(largura_css_mobile * 1.8)(例如:240px的圖片為450w,或行動裝置全寬360px的圖片為680w),並壓縮為 WebP(< 30 KB)。
- Lighthouse 行動裝置模擬一台 Moto G Power(寬度
- 避免裝飾性背景圖片「劫持」LCP:
- 如果 Hero 區段具有透明度 (
opacity: 0.15) 且邊界框 (boundingRect) 大於主要肖像或<h1>的裝飾性背景照片,Chrome 會將其視為 LCP 元素。 - 在行動裝置上(
@media (max-width: 767px)),隱藏純裝飾性的大型背景照片(display: none),或縮小其尺寸,以便主要元素(使用fetchpriority="high"預載)成為唯一的 LCP 候選者。
- 如果 Hero 區段具有透明度 (
- 不要預載與 SPA 中關鍵 JS/CSS 競爭的字型:
- 在
@font-face中使用font-display: swap,讓瀏覽器在次要字型之前優先下載 CSS 和初始 JS 套件組合。
- 在
4.2. TBT 為零(0ms 總阻塞時間)
- 用 CSS 合成器 +
IntersectionObserver取代 JavaScript 持續動畫:- 初始套件組合中的完整動畫庫會增加
50–150 KB的 JS,並在 hydration 期間阻塞主執行緒。 - 對於滾動顯示,使用原生
IntersectionObserver切換.is-visible類別,搭配 GPU 加速的transition: opacity, transform(translate3d)。 - 對於粒子或持續旋轉,使用帶有
transform: translate3d(...)/rotate(...)和will-change: transform的 CSS@keyframes。
- 初始套件組合中的完整動畫庫會增加
- 注意載入時的 SVG 濾鏡(
<feTurbulence>、drop-shadow)和 SMIL<animate>:- 切勿在沒有固定尺寸的情況下全螢幕使用
<feTurbulence>(它會在 CPU 上為數百萬像素重新計算 Perlin 噪點,產生300ms+的 Long Tasks)。優先使用輕量級的 CSSradial-gradient。 - 切勿在父元素上組合使用
filter: drop-shadow(...),而其 SVG 子元素在初始載入時每幀都會改變幾何形狀。如果有透過<animate attributeName="d">進行的<path>morphing,請僅在使用者的第一次互動(pointermove、touchstart、wheel)或初始載入後(setTimeout為8000ms)才啟用 morphing,在載入期間僅保留 GPU 上的 CSS 旋轉。
- 切勿在沒有固定尺寸的情況下全螢幕使用
- 平滑滾動(
Lenis)的程式碼分割:- 僅在第一次
wheel、touchstart或keydown事件({ passive: true, once: true })時動態載入Lenis(await import("lenis"))。這樣它在初始載入時佔用0 KB和0ms的 CPU。
- 僅在第一次
- 將定時器(
setInterval/ 緊迫性計數器)隔離在葉子元件中:- 切勿將
useCountdownhook(setInterval為 1 秒)放在根元件<App />中。這會迫使 React 在 Lighthouse 測試期間每秒重新渲染整個頁面。將時鐘狀態隔離在一個小型<CountdownClock />元件中,該元件僅渲染數字。
- 切勿將
4.3. 無障礙性獲得 100 分(WCAG AA)
- 色彩對比(
color-contrast):- 深色背景(
#10100f/#171512)上的小文字需要對比度>= 4.5:1。對於次要文字(#c4beb4、#d6c5b2)使用淺色調,對於深色背景上的強調文字使用明亮的橙色(#ff9452、#ffa36b)。 - 具有鮮豔橙色背景(
#ff772f)的按鈕應使用深色文字(#140c06)以獲得最大對比度。
- 深色背景(
- 可見文字與可存取名稱之間的一致性(
label-content-name-mismatch):- 切勿在連結/按鈕上放置不包含其確切可見文字的
aria-label(例如:如果標誌顯示CF ZANELLA.,請不要放置aria-label="首頁")。
- 切勿在連結/按鈕上放置不包含其確切可見文字的
- 語意和鍵盤:
- 將
<a class="skip-link" href="#conteudo">跳到主要內容</a>作為<body>的第一個焦點。 - 使用嚴格的標題層級(
h1->h2->h3)、在所有<section>上使用aria-labelledby,以及在狀態選擇器上使用aria-pressed。
- 將
5. 使用 Google Lighthouse 自動驗證
始終通過執行技能的自動化腳本來驗證變更:
# 本地專案:偵測技術堆疊,執行 `npm run build`(如果存在)並在連接埠 4173 啟動預覽
node <skill>/scripts/run-lighthouse.mjs
# 跳過建置(當建置輸出已是最新狀態時)
…
(其餘內容已截斷以利翻譯)