4.2 网页挂件集成:一段代码把聊天窗放上官网

4.1 把接口上架到网关之后,下一步是让访客能在官网直接点开聊天窗。智能体平台一般会提供一段嵌入式挂件代码,但直接贴上去只能算跑通——真正上线还要处理会话、跨域和移动端三件事。本节按步骤清单、交互时序、适配定制、安全四块展开,结尾照例给踩坑记录。

这一节假设官网已经能访问、4.1 的网关地址已经备好。挂件本身的技术含量不高,难的是把它揉进既有网站的细节里——这大概是从 MVP 到上线之间最琐碎的一步,也是最容易背锅的一步:挂件有一点毛病,全公司第一个看到。

接入步骤:六步清单

步骤 动作 我的注意点
第一步 引代码 在官网页面引入挂件脚本 放在页面末尾,不阻塞首屏渲染
第二步 配地址 把挂件的请求地址指向 API 网关域名 用网关域名而非平台直连地址
第三步 初始化 配置访客身份,生成会话编号 未登录访客也要有稳定编号
第四步 收发消息 监听输入事件、展示流式返回 逐字渲染,别等整段才显示
第五步 配兜底 挂件常驻转人工按钮与异常提示 智能体出错时用户有路可退
第六步 验收灰度 三款真机过一遍,配好灰度开关 上线走 4.4 的灰度节奏

接入步骤里最容易被低估的是第一步:引代码听上去就是复制粘贴,但官网页面往往经过了构建打包,脚本标签要塞进模板文件而不是某个静态页里,否则每次新页面都漏掉挂件。我们官网是模板渲染的,最后改在公共尾模板里插一行,全站自动生效。

如果你的官网是前后端分离的工程,挂件脚本建议做成按需加载:用户滚动到页面下半部或停留超过十秒再加载,首屏性能几乎零损耗。这对 SEO 与性能评分都有好处,第三方测速工具的得分肉眼可见地涨了一截。

第二步是关键:挂件直连智能体平台就绕过了网关,等于 4.1 的鉴权和限流全白配。我特地在网关监控里看了一眼来源分布,确认所有请求都经过网关才放心。

会话编号这事容易被忽略:用户刷新页面后如果换新编号,多轮对话的上下文就断了,第二天回来变成失忆客服。我们的做法是编号写进浏览器本地存储,用户下次打开还能接着上一次聊;清浏览器缓存的极端情况就当新会话,别想着面面俱到。给客服组培训时我会特别强调这一点——用户说「我刚才问过你」却接不上时,多半是这个环节出了问题。

一条消息的完整旅程

前后端交互的时序我整理成表,给客服组解释流程时直接照着讲:

步骤 从 到 传的数据
1 提交 用户 挂件 问题文本,先做空内容校验
2 请求 挂件 API 网关 临时令牌加会话编号
3 转发 API 网关 智能体平台 校验通过后原文转发
4 检索 智能体 知识库或订单接口 命中的文档片段或订单数据
5 生成 智能体平台 挂件 流式逐字返回回复
6 落库 平台回调 日志服务 会话编号加本次问答记录

流式返回对体验影响很大:如果等智能体整段想完再显示,遇到复杂问题要十秒以上,用户会以为卡死了。逐字渲染至少让人觉得它在努力。这块渲染逻辑我没自己死磕,把挂件脚本的联调与改版交给 AI 编程工具验证,改一遍配置让它按预期跑一遍,效率高很多,具体走法见Claude Code 指南。第 6 步落库是 4.3 数据回流的入口,这里只需要知道回调存在即可。

还有个断线的坑:用户频繁切换网络时流式连接中断,页面会卡在半句话上。我们加了重连机制——中断后自动带着已收到的部分重新请求,用户体验上说不上无缝,但至少不用重打一遍问题。

会话设计:多轮上下文怎么管理

挂件跑起来后,第一个真正复杂的其实是会话管理。智能体的上下文不能无限长,对话超过十几轮后,早期的内容要么被截断要么稀释,模型的回答开始飘。我们的方案分三层:

层面 做法 目的
前端 页面只保留最近十轮渲染 用户回看不迷路
网关 每次请求带上历史消息 由平台侧管理上下文窗口
策略 超过八轮主动提示可转人工 避免无限循环兜圈子

真正难的是判断一句话算不算一轮——用户连发三条短消息补充同一个问题,是算三轮还是一轮?我们的处理是前端做一个输入合并窗口,五百毫秒内的连续发送合并成一条交给智能体,这个细节对减少调用消耗帮助不小,也为 4.3 的日志分析省了很多归类功夫。

另外一个经验之谈:别让挂件的输入区看起来像搜索框。早期版本是单行输入,用户习惯性地输完一句话就回车,上下文被切得稀碎;后来改成多行文本框加独立发送按钮,多轮对话的完整性肉眼可见地变好。

还有一个会话保活的问题:用户离开页面半小时后回来,会话上下文还要不要?我们的选择是要,但限制在两小时内——超过两小时自动开新会话,沿用旧的会话编号分组归档。智能体平台侧可以配上下文有效期,和前端的策略要对齐,不然前端显示的历史和模型实际看到的历史不一致,排查起来非常折磨人。这个坑我们踩过:用户明明说了订单号,回来追问时智能体一脸茫然,因为平台侧的上下文比前端先过期了。

移动端适配与样式定制

挂件一般提供主题色、位置、欢迎语的配置项,不用改代码就能调成官网同色系。移动端有两个要点:一是按钮别挡住输入框的提交键,用底部安全距离留白;二是输入框聚焦时页面会自动放大,样式里把字号设到不小于 16 像素就能规避。窄屏下我们干脆把挂件做成全屏弹层——小屏里半高浮窗聊天太憋屈,全屏反而干脆。

挂件按钮的位置也有讲究:桌面端放右下角是惯例,但如果官网右下角已经有「回到顶部」或客服QQ悬浮条,两个按钮会打架。我们的做法是挂件加载时先探测自家其他悬浮元素的位置,错开摆放——听上去过度设计,但悬浮按钮重叠是真实会被用户截图吐槽的事故。

欢迎语别用默认的「你好,请问有什么可以帮你」。我们写的是「产品、价格、售后、订单都能问,答不上来随时转人工」,直接告诉用户能力边界,能明显减少试探性提问。正式上线前我在三个手机型号上各点了一遍:有台旧安卓机渲染明显掉帧,最后把动画过渡关掉了事——挂件是工具不是炫技场,流畅比好看重要。

样式定制还有个暗坑:用平台默认皮肤时一切正常,自己改了主题色之后某些按钮的文字对比度不够,在阳光下的手机上根本看不清。改完样式务必找个亮光环境或者调低屏幕亮度看一眼,别只在办公室里验收——用户有一半是在户外和通勤路上看你的挂件。

安全:跨域与来源校验

挂件域名和网关域名通常不同,这里有两道防线:

  • 跨域配置:在网关侧开启跨域资源共享策略,只允许官网域名。图省事选允许所有来源就等于大门敞开,别这么干。
  • 来源校验:网关校验请求头里的来源字段,非官网域名直接拒绝。前端代码里放令牌不算秘密,真正的防线永远在网关。

还见过一种事故:同事做活动页也想要聊天窗,直接把官网那套来源配置抄过去,活动页域名没加进白名单,上线当天聊天窗点了没反应。教训是白名单要跟着页面走,新增页面先提单子加来源,别让安全策略变成排障现场。

再补一个细节:临时令牌放内存里就行,别写本地存储——存盘的令牌清不掉,等于把钥匙垫在门口。

还有一个小麻烦:挂件脚本更新后,用户浏览器可能还用旧版缓存,导致网关里看到莫名其妙的旧请求。我们给脚本引用加了版本号参数,每次更新顺带换号,强制刷新。

踩坑与解法

踩坑一:官网是纯静态页面,没有后端,临时令牌没地方签发。解法是加了一台轻量服务器专门跑签发接口,顺便承载后续的数据回流服务。静态官网怎么搭、托管在哪,可以看我另一本轻量建站实战,那里讲得比较细。

踩坑二:移动端把挂件放右下角,结果挡住了购买按钮,被产品同事念叨了两天,最后加安全距离解决。

踩坑三:挂件加载时机太早。页面首屏还没渲染完,脚本就先跑起来请求后端,拖慢了整页性能。解法是延迟初始化,等首屏加载完成再唤起挂件,反正用户不会在打开网站的第一秒就点开聊天。

踩坑四:HTTPS 混合内容。官网本身是 HTTPS 的,但一开始网关用的临时域名也是 HTTPS 没问题,坏在内部联调时切过一个 HTTP 的测试地址,浏览器直接静默拦截请求,挂件显示在线但消息发不出去,排查了半小时。记住:凡是要在正式页面里加载的地址,协议头必须与页面一致。这类问题的讨厌之处在于它不报错,只是静默失败:监控里一切正常、用户那边一片空白,排查全靠经验。

踩坑五:会话上下文对不齐。前端拉着整段历史展示,平台侧只按最近几条生成,用户追问时智能体却忘了上文。解法是前后端统一有效期,并把「开新会话」做成明确动作——用户长时间未活跃后回来,先给一句提示「对话已重新开始,可继续提问」,比让 AI 装作记得更体面。

延伸阅读