关于页不该只是公司简介:AboutPage 与 mainEntity 给企业实体一个锚点
适用读者:在做企业官网改版的前端、SEO 和内容运营;已经给首页铺了 WebSite 和 Organization,却发现 AI 搜索答不出「这家公司做什么、哪年成立、有哪些资质」的人。 需要你能改页面模板里的
<head>,看得懂 JSON-LD,不需要购买任何付费工具。 文中所有校验都用公开规范和免费校验器完成。
上个月接手一家工业传感器厂家的官网改版,他们的「关于我们」页面有一千八百字、六张车间照片、一段创始人致辞,排版相当讲究。可在 AI 搜索里问「这家公司主要做什么」,回答里混进了同城另一家同名公司的经营范围,成立时间还错了四年。问题不在文案,在于那一页对机器来说只是一段富文本——它从来没有被声明成「这个页面讲的就是这家公司」。
生成式引擎优化(Generative Engine Optimization, GEO)里有个容易被忽略的事实:AI 引擎做实体识别时先找结构化声明,读长段落是兜底手段。关于页恰好是全站最适合放这个声明的地方,可惜多数站点只给它配了 <title> 和 og 标签。
关于页在 AI 回答里是怎么掉链子的
富文本关于页对机器有三处不友好。

- 主营业务散在叙述句里。「我们专注于……同时提供……」这类句式,AI 要从中抽出 knowsAbout 候选词,抽出来的常常是一堆形容词。
- 时间和数字没有可比对格式。「成立于 2015 年」「员工规模三百余人」读起来清楚,机器没法直接当字段用,因为「三百余人」不是数值,也没有单位。
- 缺消歧线索。同名企业很多,页面里没有 sameAs、identifier 这类指向,AI 只能靠上下文猜,猜错就成了别人的经营范围。
这三处补不上,靠把文案写长是白费劲,得给页面加一个实体锚点。
AboutPage 声明的只是页面身份
在 Schema.org 里 AboutPage 是 WebPage 的子类型,它做的事很单一:告诉解析器这是一个关于页。它本身不携带公司信息,真正承载企业属性的是挂在它下面的 mainEntity。
不少站点的做法是加一行 @type: AboutPage 就收工了,其实那一行只解决了页面分类。分类对了,实体没挂上去,AI 拿到的是一个「这是关于页」的空壳。这也是为什么有些站点结构化数据校验全绿,AI 搜索里依然答非所问。
关键结论:AboutPage 负责「这是个什么页面」,mainEntity 负责「这页讲的是谁」,两者缺一个,关于页就退回了普通富文本。
mainEntity 与 about 的机制差异,别再混着用
这两个字段是同一层级里最容易混的一对,规范原文对它们的措辞差别很细。
about 的类型是 Thing,语义是「这个页面的主题与什么有关」,宽松、可以出现多个、也能指向抽象概念。一篇讲行业趋势的文章,about 可以填「智能制造」,这不代表页面主体就是某个机构。
mainEntity 同样是 Thing,但语义是「页面主要内容所指的那个实体」。规范里它是强指针,一个页面语义上只应有一个,解析器拿它来做页面到实体的收敛。用在关于页上,就是明明白白地讲:这页的主角是这家公司。
机制上的差别在图谱合并时才看得清。抓取方拿到若干页面的结构化数据后,会把同一 @id 的实体节点合并,属性取并集、冲突时按来源可信度取舍。about 指向的对象不会被当成页面的主体节点,它更像是给文章打了个标签;mainEntity 指向的对象会被提升成页面级主节点,页面的文本证据(正文里那些成立时间、资质名称)会被归到这个节点下面。这就是为什么同样写了成立时间,有的站点被 AI 引用,有的没有——差别在它挂没挂在主节点上。
还有个反向属性 mainEntityOfPage,写在 Organization 一侧,等价于「这个实体是那个页面的 mainEntity」。两个方向写一个就够,同时写要保证 @id 完全一致,否则图谱里会分裂出两个公司节点。
| 维度 | mainEntity | about |
|---|---|---|
| 语义 | 页面主要内容所指的实体 | 页面主题与什么有关 |
| 数量 | 语义上一个 | 可以多个 |
| 可否指向抽象概念 | 不推荐 | 可以 |
| 解析器的处理 | 提升为页面级主节点,正文证据归入该节点 | 视为主题标签,不建立主体关系 |
| 典型误用 | 填成关键词字符串 | 拿它代替 mainEntity 挂 Organization |
Organization 该填哪些字段,按优先级排
字段不用一次全上,先补对 AI 回答影响最大的那批。下面这张表按我们改版时的落地顺序排。
| 字段 | 作用 | 常见错误 |
|---|---|---|
| name / legalName / alternateName | 名称消歧,alternateName 收简称和曾用名 | 只填 name,简称缺失导致品牌词召回失败 |
| url / logo / image | 确认官网归属与视觉标识 | logo 用了带水印的压缩图 |
| foundingDate | 成立时间,回答「哪年成立」的直接来源 | 写成「2015年」,应为 ISO 8601 的 2015-04-08 |
| foundingLocation | 注册地,配合消歧 | 与办公地址混成一个字段 |
| numberOfEmployees | 规模,用 QuantitativeValue 包数值区间 | 填「三百余人」这种字符串 |
| knowsAbout | 主营领域的词组列表,AI 抽主营业务的主来源 | 堆二十个泛词,噪声过大 |
| hasOfferCatalog | 服务或产品目录摘要 | 把全部 SKU 塞进去,节点膨胀 |
| award | 资质与获奖,回答「有哪些资质」 | 只写奖项名,缺 awardingDate |
| identifier | 统一社会信用代码、DUNS 等外部标识 | 用错 PropertyValue 的 name/value 顺序 |
| sameAs | 指向百科、官方社媒等第三方页面 | 填了已失效的跳转链接 |
knowsAbout 值得单独说一句。它是少数能直接影响 AI 表述的字段,但也最容易被写坏。我们的做法是控制在五到八个词,全部来自正文里真实出现过的业务名词,不写「解决方案」「一站式服务」这类空词。写了八个之后,AI 回答里对主营业务的表述明显贴近官网口径。
首页、关于页、联系页怎么分工
三个页面都碰得到 Organization,但绝不该复制同一份完整节点塞三遍。重复节点一旦字段有出入,图谱合并时就会打架。
flowchart TD
A["首页 /"] --> A1["WebSite + Organization 精简版"]
B["关于我们 /about"] --> B1["AboutPage + mainEntity 指向 Organization 完整版"]
C["联系我们 /contact"] --> C1["ContactPage + 只声明 contactPoint 与 address"]
D["产品页 /product/x"] --> D1["Product + brand 引用 Organization 的 @id"]
A1 --> E["实体图谱:以 Organization 的 @id 为共用锚点"]
B1 --> E
C1 --> E
D1 --> E
E --> F["AI 引擎回答公司类问题时取并集"]
分工的原则是:完整节点只在关于页写一次,其他页面用 @id 引用它。首页放精简版只是为了确认站点与主体的关系,联系页只补充联系方式,产品页通过 brand 反向指回公司。这样字段冲突的可能性被压到最小。
一段能直接用的构建脚本
把节点写成脚本生成,好处是字段能复用、改一次全站生效。下面这段在 Node.js 18 上跑过,无第三方依赖,输出的 JSON 直接贴进 <script type="application/ld+json">。
// 环境:Node.js 18.20,无第三方依赖
// 用途:生成关于页的 AboutPage + Organization 节点,输出可直接贴进页面
// 约定:Organization 的完整定义只在这里出现一次,其他页面用 @id 引用
const ORG_ID = "https://example.com/#organization";
// 站点根地址,末尾不带斜杠,@id 与 url 必须保持同一形态
const SITE = "https://example.com";
const organization = {
"@type": "Organization",
// 用 #organization 片段做锚点,全站共用这一个
"@id": ORG_ID,
// 对外称呼,与页面 <title> 里的品牌部分保持一致
name: "示例科技有限公司",
// 营业执照上的全称,用于与第三方数据源对齐
legalName: "示例科技有限公司",
// 简称、曾用名都收进来,品牌词召回靠它
alternateName: ["示例科技", "示例"],
// 官网根地址,用于确认站点与主体的归属关系
url: SITE,
// 方形 logo,最小边不低于 112px,别用带水印的压缩图
logo: `${SITE}/static/logo-600.png`,
// ISO 8601,只写到日即可,不要写「2015年」
foundingDate: "2015-04-08",
// 注册地,与办公地址分开写,同名企业消歧时是硬线索
foundingLocation: {
"@type": "Place",
name: "示例市示例区"
},
// 办公地址,PostalAddress 的字段顺序不影响解析
address: {
"@type": "PostalAddress",
// 街道门牌,写到能投递的粒度
streetAddress: "示例路 100 号 3 幢",
// 城市
addressLocality: "示例市",
// 省份
addressRegion: "示例省",
// 国家用两位 ISO 3166 代码
addressCountry: "CN"
},
// 人数必须用 QuantitativeValue 包成区间,不能写字符串
numberOfEmployees: {
"@type": "QuantitativeValue",
minValue: 260,
maxValue: 320
},
// 五到八个词,全部取自正文里真实出现的业务名词
knowsAbout: [
"工业传感器",
"压力变送器",
"温度仪表",
"自动化校准"
],
// 资质与获奖,AI 回答「有哪些资质」时读这里
award: [
// 管理体系认证,写全称不要写缩写
"ISO 9001 质量管理体系认证",
// 资质类荣誉,有效期信息建议另配 awardingDate
"国家高新技术企业"
],
// 统一社会信用代码,name 写标识类型、value 写号码
identifier: {
"@type": "PropertyValue",
// name 是标识类型名称,不是公司名
name: "统一社会信用代码",
// value 是号码本体,18 位
value: "91350000XXXXXXXXXX"
},
// 指向第三方页面,用于同名企业消歧
sameAs: [
// 官方微博主页,必须是能直接访问的最终地址
"https://example.com/official-weibo",
// 官方 LinkedIn 主页,失效链接要及时清掉
"https://example.com/official-linkedin"
]
};
const aboutPage = {
// 固定写 https://schema.org,不要写成 http
"@context": "https://schema.org",
// 页面类型:关于页,不要用 WebPage 顶替
"@type": "AboutPage",
// 页面自身的地址,与 canonical 保持一致
url: `${SITE}/about`,
// 页面标题,与 <h1> 对齐
name: "关于我们",
// 语言标记,中文站写 zh-CN
inLanguage: "zh-CN",
// 关键:把公司实体挂成这页的主实体
mainEntity: organization,
// about 只做主题补充,不承担主体声明
about: { "@type": "Thing", name: "工业自动化仪表制造" },
// 反向声明,两个方向写一个即可,@id 必须完全一致
mainEntityOfPage: { "@type": "AboutPage", "@id": `${SITE}/about#webpage` }
};
// 缩进两格输出,方便直接贴进 <script> 标签
console.log(JSON.stringify(aboutPage, null, 2));
输出贴进页面时,脚本本身不上线,只上 JSON.stringify 的结果。我们是在构建阶段跑这个脚本,把结果写进模板变量,避免运行时拼字符串出错。
上线前的校验与排查
先过语法,再查语义
结构化数据最常见的失败不是语法错,而是「校验器全绿、AI 还是不认」。我们按下面这条流水线排查,第二轮才定位到问题:首页和关于页各写了一份 Organization,foundingDate 一个写 2015、一个写 2016,图谱合并时取了首页那份。
flowchart TD
A["跑 validator.schema.org 看语法"] --> B{"有报错?"}
B -->|是| C["按行号修 JSON,多为逗号与引号"]
B -->|否| D["grep 全站模板,统计 Organization 出现次数"]
D --> E{"大于 1 处完整定义?"}
E -->|是| F["只保留关于页的 mainEntity 定义,其余改 @id 引用"]
E -->|否| G["核对 foundingDate 是否为 ISO 8601"]
F --> G
G --> H{"字段值一致?"}
H -->|否| I["统一取值来源,改完重跑构建脚本"]
H -->|是| J["用品牌词加主营业务在 AI 搜索里实测"]
用脚本批量扫重复定义
下面这段 Python 用来批量扫模板产物,把重复定义和格式问题一次揪出来。Python 3.11,只用标准库。
# 环境:Python 3.11.4,仅用标准库
# 用途:扫描构建产物里的 JSON-LD,找出 Organization 重复定义与格式问题
import json
import re
import pathlib
# 构建产物目录,改成你自己的输出路径
ROOT = pathlib.Path("./dist")
# 匹配页面里的 ld+json 脚本块,re.S 让点号匹配换行
PATTERN = re.compile(
r'<script[^>]+application/ld\+json[^>]*>(.*?)</script>',
re.S
)
# 成立时间只认 YYYY-MM-DD 这一种形态
ISO_DATE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
full_defs = [] # 完整定义了 Organization 的页面
id_refs = [] # 只用 @id 引用的页面
bad_dates = [] # foundingDate 格式不对的页面
for html_file in ROOT.rglob("*.html"):
raw = html_file.read_text(encoding="utf-8")
for block in PATTERN.findall(raw):
try:
# 页面里可能有多个块,逐个尝试解析
data = json.loads(block)
except json.JSONDecodeError:
# 语法错的块先跳过,交给校验器处理
continue
# @graph 写法会把节点装成数组,统一成列表再遍历
nodes = data if isinstance(data, list) else [data]
for node in nodes:
if not isinstance(node, dict):
continue
# 找主实体,mainEntity 可能嵌在 WebPage 里
entity = node.get("mainEntity") or node
if not isinstance(entity, dict):
continue
# 只关心 Organization,其他类型跳过
if entity.get("@type") != "Organization":
continue
# 有 name 说明是完整定义,只有 @id 说明是引用
if "name" in entity:
full_defs.append(str(html_file))
elif "@id" in entity:
id_refs.append(str(html_file))
# 格式不对的成立时间单独记一条
date = entity.get("foundingDate")
if date and not ISO_DATE.match(str(date)):
bad_dates.append((str(html_file), date))
# 完整定义多于一处就要合并,否则图谱会取错值
print("完整定义页面:", full_defs)
print("仅引用页面:", len(id_refs))
print("日期格式异常:", bad_dates)
扫完之后再看命令行这一步,用 curl 把线上页面抓下来直接过一遍,能发现模板变量没渲染这类低级错误。
# 环境:bash + curl 8.4,仅演示取值校验
# -s 静默模式,不输出进度条,方便管道后续处理
# 抓取线上关于页,抽出 foundingDate 看是否被模板正确渲染
curl -s https://example.com/about \
| grep -o '"foundingDate":[^,]*' \
| head -n 3
# 抽出 @id,确认全站引用的是同一个锚点
# sort -u 去重后应只剩一行
curl -s https://example.com/about \
| grep -o '"@id":"[^"]*#organization"' \
| sort -u
第二条命令应该只输出一行。输出多行说明锚点分裂了,得回去合并。
改造前后对比
同一家站点,改版前后各观察了六周,品牌词相关问题的 AI 回答采样 40 条。数字是内部采样,只作趋势参考。
| 观察项 | 改造前 | 改造后 |
|---|---|---|
| 回答中提到成立时间的比例 | 5/40 | 31/40 |
| 主营业务表述与官网一致的比例 | 12/40 | 34/40 |
| 混入同名公司信息的条数 | 9/40 | 1/40 |
| 关于页结构化数据报错数 | 0 | 0 |
| Organization 完整定义处数 | 3 | 1 |
| knowsAbout 平均用词数 | 0(无该字段) | 6 |
报错数前后都是 0 这一栏值得留意:它说明校验器通过和 AI 认得出是两件事,别拿校验器当验收标准。
还容易踩的几个坑
把 Organization 的完整定义塞进每个页面,是最普遍的一个。字段稍有出入,合并结果就不确定,AI 可能取到任何一个版本。
award 只写名称不写时间,AI 回答时会把过期资质当成现行的。补上 awardingDate 之后,表述就准了。
hasOfferCatalog 里塞全量 SKU 也很常见。关于页放的是摘要,控制在三到五个品类,细节留在产品页,否则节点体积上去、加载变慢,收益却没增加。
至于趋势,实体类的声明正在从「有没有」转向「一不一致」。站点内部、百科、招聘平台、工商信息这几处对同一家公司的描述如果不一致,AI 会倾向采信它认为更可靠的那个源。关于页能做的,是提供一份格式规范、可对齐的官方版本。
你们在改关于页时有没有遇到过同名企业混淆的情况,评论区说说是怎么消歧的。
参考与延伸
- AboutPage 官方定义:https://schema.org/AboutPage
- mainEntity 官方定义:https://schema.org/mainEntity
- Organization 类型与全部字段:https://schema.org/Organization
- 结构化数据校验工具:https://validator.schema.org/
关键词:GEO、AI优化AIO、AboutPage、mainEntity、Organization、结构化数据、AI搜索