课程站的 AI 搜索突围:coursePrerequisites 与 courseCode 把先修链讲给引擎听

2026-10-03 01:22:25 0 次浏览
GEOAI搜索CourseSchema.org知识付费

适用读者:在线教育/知识付费平台的前端与内容工程同学,负责课程详情页、课程目录与结构化数据的人。如果你想让自己平台的进阶课在 AI 搜索里被正确推荐给有基础的学习者,这篇是实操手册。

「数据可视化实战」这门进阶课,页面流量不差,但在 Perplexity 和豆包里问「零基础学数据可视化该报什么课」,推荐列表里永远只有它隔壁那门入门课。运营同学小蒋十月初拉了一次统计:这门年营收贡献排前五的进阶课,过去半年在各类 AI 引擎回答里被引用次数是 0。

问题不在课程质量,在课程页面没把「先修关系」说清楚。生成式引擎优化(Generative Engine Optimization, GEO)这件事里,最容易被忽略的一环就是课程链路:引擎不知道「数据可视化实战」建立在哪门课之上,也就不敢把它推给搜入门内容的人。这篇文章记录我们怎么用 Schema.org 的 Course 实体,把先修链一条条喂给引擎。

先看引擎到底缺什么信息

打开课程页的源码,我们当时的结构化数据长这样(简化后):

课程先修链 coursePrerequisites 与 AI 推荐路径

{
  "@context": "https://schema.org",
  // 旧版标记只有三个字段,等于一张课程名片
  "@type": "Course",
  "name": "数据可视化实战",
  // 描述无法承载结构化的先修关系
  "description": "从数据清洗到交互大屏,完整实战项目教学。"
}
// 问题一眼可见:没有 courseCode,也没有任何指向其他课程的关系字段

改造前的问题一眼可见:没有 courseCode,没有先修关系,也没有开课时间。下面是改后的标记(代码里的 // 仅为讲解注释,JSON 本身不支持注释,上线时请删除)。

这段标记对引擎来说等于一张名片:知道课程叫什么、大概讲什么,别的都没了。学习者点进来能看目录、看评价、看「建议先学 XXX」,这些信息全在页面正文里,而正文恰恰是 AI 引擎最不擅长做结构推理的部分。

引擎面对的实际决策是这样的:

flowchart LR
    A[用户问: 有基础<br>想学数据可视化] --> B{引擎检索候选课程}
    B --> C[入门课: D3 基础]
    B --> D[实战课: 数据可视化实战]
    D --> E{有无先修信息?}
    E -->|没有| F[风险高: 推了用户听不懂<br>不敢选]
    E -->|有 coursePrerequisites| G[匹配学习者水平<br>放心推荐]
    C --> H[入门课被反复引用]

引擎推荐进阶内容的顾虑很实际:推荐一门用户跟不上课,用户会追问「你为什么推荐这个」,回答质量评分就掉。所以缺先修信息时,引擎的默认策略永远是保守——宁推入门,不推进阶。这就是进阶课被引用为零的直接原因。

用 coursePrerequisites 把链路接上

改法不复杂。Schema.org 的 Course 类型里有 coursePrerequisites 属性,官方定义就是「修这门课之前需要掌握什么」。关键是两点:先修课要指向同平台的 Course 实体(用 @id 或 courseCode),不能写一句纯文本;被指向的那门课自己也得有完整的 Course 标记,两边要能对上。

改后的实战课标记:

{
  "@context": "https://schema.org",
  // @graph 用来把本课和被引用的先修课实体放进同一张图谱
  "@graph": [
    {
      // 当前课程:进阶课「数据可视化实战」
      "@type": "Course",
      // @id 是实体锚点,先修课会反向引用这个地址
      "@id": "https://example-edu.cn/courses/dataviz-pro#course",
      "name": "数据可视化实战",
      // 编码规则:课程线-难度档+序号,2 开头即进阶
      "courseCode": "DVP-201",
      // 描述里显式写出适合人群,和先修声明互相印证
      "description": "面向已掌握 D3 基础的学员,完成 3 个真实项目。",
      // 先修关系:指向同平台入门课的 Course 实体
      "coursePrerequisites": {
        "@type": "Course",
        // @id 必须对应入门课详情页上声明的同一个锚点
        "@id": "https://example-edu.cn/courses/d3-basic#course",
        // courseCode 双保险,引擎只解析到编码时也能对上
        // 两个值同时给,兼容只认其一的解析器
        "courseCode": "DVP-101"
      },
      // 开课时序:两个班次,供引擎回答「什么时候开课」
      "hasCourseInstance": [
        {
          "@type": "CourseInstance",
          // online 表示纯线上班,线下班写 Onsite
          "courseMode": "online",
          // ISO 8601 时长:PT6H 即 6 小时
          "courseWorkload": "PT6H",
          "startDate": "2026-11-15"
        },
        {
          "@type": "CourseInstance",
          "courseMode": "online",
          "courseWorkload": "PT6H",
          // 第二班次比第一个晚五周
          "startDate": "2026-12-20"
        }
      ]
    }
  ]
}

环境说明:这是纯 JSON-LD,通过 <script type="application/ld+json"> 嵌在课程详情页模板里,不依赖任何运行库,Node 18 或直接静态输出都行。几行关键改动拆开讲:

  • courseCode: "DVP-201":平台自己定的编码规则,前两位是课程线缩写,后三位里首位代表难度档位,1 开头是入门、2 开头是进阶。
  • coursePrerequisites 里的 @id 直接指向入门课的 Course 实体锚点,courseCode 双保险——就算引擎只解析到 code 也能对上。
  • hasCourseInstance 里的 startDate 给引擎一个时间锚点,回答「什么时候开课」这类问题时直接可用。

courseWorkload 的 ISO 8601 格式容易写错,PT6H 表示 6 小时,分钟是 PT90M,别写成 6h。

courseCode 编码规则要写成制度

编码规则看着是小事,实际决定引擎能不能从 code 本身读出层级。我们踩过一个坑:早期课程 code 是编辑随手起的,DATA101、VIZADV、class7 混在一起,引擎无从判断谁先谁后。九月中旬我们重定了规则:

字段 位置 含义 示例
课程线 第 1-3 位 业务域缩写 DVP(数据可视化)
难度档 第 4 位 1 入门 / 2 进阶 / 3 高阶 DVP-201
序号 第 5-6 位 线内顺序 DVP-201
分隔符 中间 连字符,不用下划线 -

规则定了还要落到课程目录的数据表里,不然下个批次又乱。我们的课程主表加了三个字段:

-- MySQL 8.0,课程主表 course 补充字段,请在测试库先验证再上线
ALTER TABLE course
  ADD COLUMN course_code VARCHAR(12) NOT NULL UNIQUE COMMENT '平台课程编码,规则见内部文档 CODE-2026-03';
ALTER TABLE course
  -- 入门课此列存 NULL,进阶课指向先修课主键
  ADD COLUMN prereq_course_id BIGINT NULL COMMENT '先修课主键';
ALTER TABLE course
  -- 冗余难度档位,渲染模板时避免每次解析 course_code 字符串
  ADD COLUMN difficulty_level TINYINT NOT NULL DEFAULT 1 COMMENT '1入门 2进阶 3高阶';

-- 外键约束保证先修课一定存在于本平台,避免脏引用
ALTER TABLE course
  ADD CONSTRAINT fk_course_prereq
  -- 删除策略选 RESTRICT,防止先修课被顺手清掉
  FOREIGN KEY (prereq_course_id) REFERENCES course(id)
  ON DELETE RESTRICT;

页面渲染时,模板从这个表读 prereq_course_id,反查先修课的 course_code 和 @id,拼进 JSON-LD。数据和标记同源,就不会出现页面写着「建议先学 D3 基础」而标记里指向另一门课的错位。

改造前后的差异可以放在一起看:

对比项 改造前 改造后
先修关系 仅页面正文一句话 coursePrerequisites 指向实体
课程编码 编辑随意填写 DVP-201 式规则化编码
开课时间 正文招生文案里 hasCourseInstance.startDate
引擎可校验性 无法核对 @id 对同平台实体可交叉验证
学习时长 无 courseWorkload 标准时长

机制剖析:引擎侧为什么认这一套

这里得说清楚平台侧的运作逻辑。主流 AI 引擎对结构化数据的处理分两层:抓取层把 JSON-LD 解析成知识图谱里的实体和关系边;生成层在组织回答时,会优先沿着这些已验证的关系边走,而不是靠语言模型自己从正文里猜。

coursePrerequisites 被解析成一条 prerequisite 边之后,引擎回答「学完 X 课接下来学什么」就有了确定依据。更关键的是保守推荐策略会反转:当引擎能确认「搜数据可视化的用户如果标记过已学 DVP-101,DVP-201 就是安全的下一步」,进阶课就从「不敢推」变成「该推」。

Google 的结构化数据文档里 Course 属于富结果类型,官方明确建议课程间的依赖关系用 coursePrerequisites 表达。这属于各家引擎共同认可的通用语义,一次改造多处受益。

落地过程与效果

改造是十月第二周做的,前后三个工作日。第一步整理 42 门课的先修关系,运营提供人工清单,我们核对到课程表;第二步改详情页模板输出 JSON-LD;第三步用 Rich Results Test 逐页验证。中途翻过一次车:有两门课的 @id 锚点写成了课程列表页地址而不是详情页,导致引擎解析到的实体对不上,验证工具直接报错,改回锚点就过了。

效果数据(平台内部观测,非第三方统计):

指标 改造前(9 月) 改造后(10 月下旬)
「数据可视化实战」在 AI 回答中被引用次数 0 27
先修关系被引擎正确表述的回答样本 0 9
课程站整体 AI 渠道推荐量 41 88

27 次引用里,有 9 次回答原文出现了「在完成 D3 基础之后」这类先修表述,说明引擎确实读到了关系边,不是碰巧。数据量还小,别当成普遍规律,但方向是对的。

改完的校验流程建议固化下来:

flowchart TD
    A[编辑发布/修改课程] --> B[CI 触发结构化数据校验]
    B --> C{JSON-LD 语法合法?}
    C -->|否| D[阻断发布, 提示行号]
    C -->|是| E{prereq 指向的 @id 存在?}
    E -->|否| F[阻断: 先修课实体缺失]
    E -->|是| G{difficulty 与 courseCode 第4位一致?}
    G -->|否| H[警告并进人工队列]
    G -->|是| I[放行, 提交搜索引擎重抓]

最后这道关卡值得多花心思。课程下架是最常见的翻车点:先修课下架了,所有指向它的进阶课标记全部悬空。我们的做法是下架课程先转「隐藏」状态保留实体 90 天,给引擎留出更新窗口。

几个容易想岔的地方

有人说「正文里写了先修建议就够了,引擎那么聪明总能看懂」。真看不懂,至少目前做不到稳定看懂。语言模型从营销文案里推断课程难度,错误率远高于读一条显式的结构化边。正文和标记不冲突,但只写正文等于把判断权交还给引擎的猜测。

另一个误区是给每门课都塞一长串先修课。先修链要克制,链上每一环都得是真实存在、内容上确实依赖的课程。把同级课程也标成先修,引擎交叉验证发现内容重叠,反而会降低对整个站点实体数据的信任。

趋势上看,AI 引擎对垂直领域的关系语义(课程先修、商品适配、内容难度)会越来越依赖站点自己声明的结构化数据。知识付费平台手里有天然的图谱素材——课程、章节、讲师、学员路径,现在把 Course 这层做扎实,后面接 LearningResource、hasCourseInstance 的排期信息都是顺手的活儿。你们平台上有没有课程在 AI 搜索里「隐身」的情况?欢迎评论区聊聊具体场景。

参考与延伸

  • Schema.org Course 类型定义:https://schema.org/Course
  • Google 搜索中心结构化数据(Course 富结果):https://developers.google.com/search/docs/appearance/structured-data/course
  • JSON-LD 1.1 规范:https://www.w3.org/TR/json-ld11/

GEO、AI 搜索引用、Course、coursePrerequisites、courseCode、JSON-LD、在线教育

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