官网就是 GEO 的样板间:这个站是怎么搭的
做 GEO 服务的公司,自己的官网得先站得住。所以这个站是我们的第一个案例 —— 你现在看到的每一屏,都是拿来验证一件事的:给人看的观感,和给 AI 读的结构,能不能在同一个页面里同时成立。
结论是能,而且冲突比想象的小。下面是具体怎么做的,以及你可以怎么当场验我们。
两种读法,要的东西不一样
人打开一个页面,要的是节奏:一屏一个意思,滚下去有推进,字大小得体,图别糊。
抓取端要的是结构:标签有语义,正文在初始 HTML 里,标题层级对得上,关键事实有结构化标注。
这两套需求平时不打架。真正会打架的是一种偷懒的实现方式 —— 视觉效果全靠一堆没有语义的 div、文字做进图片里、正文等 JavaScript 跑完才插进页面。做完之后人看着挺酷,抓取端拿到的是一个空壳。大部分「视觉和 GEO 不可兼得」的说法,是把工程习惯的问题算到了设计头上。
三个具体的决定
一、纵向 fullpage,但不开虚拟滚动
首页是一屏一翻的纵向 fullpage,用 Swiper 实现。Swiper 有个叫 Virtual Slides 的功能,只挂载当前可见的那一屏,其余从 DOM 里移走 —— 屏数多的时候省内存,是个正经优化。
我们把它关掉了。
原因很直接:对人来说,移不移出 DOM 没有任何区别,反正看不见;但对抓取端来说,整页就只剩一屏的内容。首页恰好是品牌事实最密集的地方 —— 公司是什么、做哪四件事、凭什么可信 —— 全在后面几屏。为了省一点内存,把事实层砍掉九成,这笔账怎么算都不划算。
代价是首屏的 DOM 比开虚拟滚动时大一些。在一个只有几屏的营销站上,这个代价可以忽略。
二、正文由服务端渲染,不等 JavaScript
页面编排放在 server component 里,交互组件(轮播、跑马灯、筛选)虽然是客户端组件,但在 App Router 里它们同样会被服务端渲染进初始 HTML。也就是说:滚动、翻页、hover 这些行为需要 JS,而文字不需要。
这个决定的好处是可以被验证,不需要相信我们:
# 只取服务端返回的初始 HTML,数一数正文里的关键词还在不在
curl -s <页面地址> | grep -o "GEO" | wc -l
更直观的办法是在浏览器里关掉 JavaScript,再打开任意一页,看还剩多少字。如果剩一片空白,这个站的 GEO 就是假的 —— 抓取端看到的就是那片空白。
这个测试对任何官网都成立,包括你自己的,现在就可以跑一遍。
三、结构化数据不手写第二份
JSON-LD 最常见的坏味道是:页面上写一套文案,JSON-LD 里手抄一套。改文案的时候只改了页面,结构化数据就开始漂 —— 而漂掉的那一份,恰好是机器唯一认真读的那一份。
这个站的做法是让两边取同一个数据源。服务页的四项服务写在一个数据文件里,页面渲染它,页面的 OfferCatalog 结构化数据也从它生成:
{
"@type": "OfferCatalog",
"name": "云浪科技服务体系",
"itemListElement": [
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "GEO 优化服务",
"provider": { "@type": "Organization", "name": "云浪科技" }
}
}
]
}
常见问题页同理:问答内容写一份,喂给页面的折叠面板,也喂给 FAQPage。改口径只需要动一个文件,两边不可能不一致 —— 靠的不是纪律,是结构上不给写第二份的机会。
我们怎么验收
三件事,都能拿出数:
- 关掉 JS 看剩多少字。每次改完页面跑一遍,防止有人不小心把正文挪进了只在客户端执行的分支。
- 结构化数据校验。JSON-LD 过一遍 schema 校验,类型写错、字段拼错这类问题机器直接告诉你。
- 拿真实问题去问模型。这条最慢也最重要 —— 前两条只证明「机器能读到」,这条才证明「模型愿意用」。怎么问才算一次有效的诊断,拆在《同一个问题,四个大模型给了四种品牌印象》里。
一个不太好听的补充
这个站上还有占位内容。部分数字、部分引语、部分配图是先撑版面用的,标注在代码里等着替换。写出来是因为它正好说明了 GEO 里最麻的一件事:技术层可以在一周内做对,事实层要靠公司自己攒。
语义 HTML、结构化数据、服务端渲染,这些都是工程问题,有标准答案。但「你到底做过什么、服务过谁、结果是多少」没有捷径 —— 没有的东西编不出来,编出来的迟早会被交叉验证戳穿。
同一个页面,两种读法。
