关于页不该只是公司简介:AboutPage 与 mainEntity 给企业实体一个锚点

2026-09-22 01:22:59 1 次浏览
GEOAboutPagemainEntitySchema.orgSEO

适用读者:在做企业官网改版的前端、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搜索

🤖
本内容由 AI 辅助生成,经人工校对审核;部分素材、资料来源于公开网络,仅作个人观点分享与交流使用,无任何商业侵权意图。若内容、图片、文字涉及您的合法著作权、版权权益,请联系本人,核实后将第一时间删除、修改相关内容。