网站小部件
将你的语音代理嵌入任何网站,让访客能够直接从浏览器开始语音对话。Widgets 标签页提供嵌入代码、自定义选项和域名安全设置。
回拨小部件的工作方式与本页的小部件截然不同——它不是开始浏览器语音通话,而是收集访客的电话号码并让你的代理回拨给他们。参见专门的回拨小部件页面。
小部件类型
Hanc.AI 提供四种浏览器内小部件类型,外加一个单独的用于电话回拨的回拨小部件:
| 小部件 | 标签名 | 描述 | 最适合 |
|---|---|---|---|
| 浮动小部件 | hanc-ai-floating-call | 悬浮在页面上方的球形按钮 | 始终可见的行动号召 |
| 胶囊小部件 | hanc-ai-pill-call | 内联放置在内容中的紧凑胶囊形按钮 | 在现有布局中占用极小空间 |
| 浮动胶囊小部件 | hanc-ai-pill-floating-call | 与胶囊相同的紧凑胶囊形状,但像浮动小部件那样随页面浮动 | 当你想要一个随访客滚动而跟随的胶囊外观时 |
| 内联小部件 | hanc-ai-inline-call | 嵌入页面内容的全尺寸通话按钮 | 专门的"与我们通话"版块 |
| 回拨小部件 | hanc-ai-callback | 电话号码表单;代理回拨给访客 | 获客页面、高意向落地页——参见回拨小部件 |
通用属性
所有小部件类型都支持这些核心属性:
| 属性 | 是否必需 | 描述 | 默认值 |
|---|---|---|---|
agent-id | 是 | 你的代理的唯一标识符 | — |
voice-service-url | 否 | 覆盖语音服务 URL | 自动检测 |
api-base-url | 否 | 覆盖 API 基础 URL | 自动检测 |
显示属性
| 属性 | 描述 | 取值 | 默认值 |
|---|---|---|---|
position | 小部件在页面上的位置 | bottom-right、bottom-left、top-right、top-left、static | bottom-right |
size | 小部件大小(以像素计) | 数字 | 120 |
theme | 颜色主题名称 | 参见颜色主题 | default |
按钮文本属性
| 属性 | 描述 | 默认值 |
|---|---|---|
button-start-text | 空闲按钮上显示的文本 | "Call" |
button-connecting-text | 连接时显示的文本 | "Connecting..." |
button-end-text | 通话进行中显示的文本 | — |
条款属性
| 属性 | 描述 | 默认值 |
|---|---|---|
terms-enabled | 在通话前启用同意对话框 | false |
terms-content | Markdown 格式的同意文本 | "" |
terms-url | 指向你的条款与条件页面的链接 | "https://hanc.ai/terms" |
privacy-url | 指向你的隐私政策页面的链接 | "https://hanc.ai/privacy" |
除非 skip-fetch 设置为 true,否则在 HTML 元素上设置的条款属性会被从 API 获取的代理小部件设置覆盖。
声音属性
| 属性 | 描述 | 默认值 |
|---|---|---|
sound-enabled | 启用通话开始/结束提示音 | true |
sound-volume | 音效音量 | 0.25 |
sound-preset | 声音预设标识符 | "1" |
颜色主题
用 11 种内置颜色主题自定义小部件外观:
| 主题 | 取值 |
|---|---|
| Default | default |
| Purple | purple |
| Blue | blue |
| Cyan | cyan |
| Emerald | emerald |
| Amber | amber |
| Tangerine | tangerine |
| Rose | rose |
| Ember | ember |
| Black | black |
| White | white |
每种主题都有深色和浅色两种变体。通过嵌入代码中的 theme 属性设置主题,或在代理的小部件设置中配置。
嵌入示例
浮动小部件
<hanc-ai-floating-call agent-id="YOUR_AGENT_ID"></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
带主题和位置的浮动小部件
<hanc-ai-floating-call
agent-id="YOUR_AGENT_ID"
theme="emerald"
position="bottom-left"
size="140"
></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
胶囊小部件
<hanc-ai-pill-call agent-id="YOUR_AGENT_ID"></hanc-ai-pill-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
内联小部件
<hanc-ai-inline-call agent-id="YOUR_AGENT_ID"></hanc-ai-inline-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
上面的脚本 URL 始终加载最新发布的小部件——你的网站会自动获得改进,未指定版本时 @latest 为默认值。如果你需要锁定到一个固定版本,请通过追加你想要的版本号来明确锁定,例如 https://unpkg.com/hanc-webrtc-widgets@X.Y.Z。
小部件事件
小部件会发出你可以在 JavaScript 中监听的事件:
| 事件 | 描述 |
|---|---|
status-changed | 当通话状态改变时触发 |
connecting | 通话正在建立 |
connected | 通话进行中 |
idle | 无进行中的通话 |
error | 发生错误 |
audio-track | 收到远端音频轨道(用于可视化) |
local-audio-track | 本地麦克风音频轨道(用于可视化) |
microphone-enabled | 麦克风已启用 |
microphone-disabled | 麦克风已禁用 |
call-start | 当通话成功开始时触发 |
call-end | 当通话结束时触发 |
示例:监听事件
const widget = document.querySelector('hanc-ai-floating-call');
widget.addEventListener('call-start', () => {
console.log('Call started');
});
widget.addEventListener('call-end', () => {
console.log('Call ended');
});
让智能体打开页面
在浏览器通话过程中,智能体可以请求您的网站打开某个页面——「我给您看一下价格」——访客在不中断对话的情况下就能看到。
决定权始终在您的页面。智能体发出请求,由您的代码决定它意味着什么。打开网址、切换标签页、滚动到某个区块、展开折叠面板,都是有效的处理方式。
一共三步,缺一不可。
第 1 步 — 告诉智能体有哪些页面
智能体看不到您的站点地图。它只会请求您给过它的路径,所以请在智能体的提示词或知识库中列出:
我们网站的页面:
/pricing — 套餐与价格
/contact — 联系表单和电话
/product/crm — CRM
跳过这一步,智能体就没有可请求的内容,也就不会尝试。
第 2 步 — 在页面上处理请求
在挂件脚本之后的任意位置添加一次即可。事件会沿页面向上冒泡,因此监听 document 就够了:
<script>
document.addEventListener('agent-command', (event) => {
const { type, payload } = event.detail;
if (type === 'navigate') {
// 单页应用:不刷新地路由——通话继续。
router.push(payload.path);
// 传统站点:另开一个标签页,当前这个(连同通话)得以保留。
// window.open(payload.path, '_blank');
event.preventDefault(); // ← 这一行才是在告诉智能体「已处理」
}
});
</script>
通话就活在这个页面里。window.location.href = … 会卸载文档,对话也随之消失——访客会在说到一半时被切断。有路由就在客户端跳转,否则请在新标签页中打开。没有重连机制:刷新之后什么都不会保留。
preventDefault() 不是可选项这是唯一表示「我处理了」的方式。缺少它,智能体会被告知该网站不支持导航:在本次通话剩余时间里不再尝试,转而口头描述该点哪里。控制台不会有任何提示——页面看上去只是忽略了请求,事实也确实如此。
第 3 步 — 试一试
从网站给您的智能体打电话,按名称索要某个页面。应当发生两件事:页面打开了,并且智能体会说「这是价格」,而不是「您可以在菜单里找到」。
用数据回应智能体
有些指令是提问而非命令。它们以同样的方式到达,但需要用 respond() 回答:
| 指令 | 智能体在问什么 | 您回什么 |
|---|---|---|
navigate | 「打开这个路径」 | 什么都不用——preventDefault() 即可 |
page_context | 「访客正在看什么?」 | 任何有用的信息:路径、标题、商品 |
cart_state | 「购物车里有什么?」 | 商品、合计、币种 |
<script>
document.addEventListener('agent-command', (event) => {
const { type, respond } = event.detail;
if (type === 'page_context') {
event.preventDefault();
respond({ path: location.pathname, title: document.title });
}
});
</script>
preventDefault() 之后约有一秒钟的回应时间:await 没问题,缓慢的 API 调用不行。用手头已有的数据回答即可。
智能体可以请求什么,不可以请求什么
- 只能是您自己站点内的路径。 路径必须以
/开头。任何可能离开您域名的写法——//evil.com、https://…、反斜杠——在到达页面之前就被拒绝。智能体无法把访客带到别处。 - 仅限浏览器通话。 电话通话中没有页面可开,因此那里不存在这些指令。
- 一次拒绝就够了。 如果页面没有确认第一次请求,智能体在本次通话剩余时间里不再询问。它不会反复尝试,更重要的是,不会告诉访客自己打开了其实没打开的东西。
在过滤之前先把每条指令打印出来:document.addEventListener('agent-command', e => console.log(e.detail))。如果控制台里出现了 navigate,说明智能体这一侧没问题,缺的是 preventDefault() 或您自己的处理逻辑。如果什么都没有,那就是从未告诉过智能体这个路径的存在——回到第 1 步。
技术要求
小部件要求访客的浏览器支持:
- WebGL 2.0 —— 用于渲染
- Web Audio API —— 用于音频处理
- WebRTC —— 用于实时语音通信
所有现代浏览器(Chrome、Firefox、Safari、Edge)都支持这些技术。
域名限制
控制哪些网站可以嵌入你的代理小部件。
始终允许的域名
以下域名无论如何配置都始终被允许:
hanc.ai(及其子域名)hanc.me(及其子域名)localhost
允许所有域名
默认情况下,你的小部件可以嵌入到任何网站。在小部件设置中切换 "Allow all domains" 来限制这一点。
限制到特定域名
限制时,添加每个应被允许的域名:
- 输入域名时不带
https://(例如example.com) - 子域名需要单独的条目(例如
www.example.com、shop.example.com) - 可以指定端口(例如
localhost:3000) - 最多可将 50 个域名加入白名单
对于生产环境的代理,将小部件限制到你自己的域名,以防止未经授权的嵌入。
条款与条件
在来电者能够开始对话之前启用同意对话框。
配置
| 设置 | 描述 |
|---|---|
| Enable Terms | 开/关切换条款对话框 |
| Terms Content | 向用户显示的 Markdown 格式同意文本(最多 5,000 字符) |
| Terms URL | 指向你完整条款与条件页面的链接 |
| Privacy URL | 指向你隐私政策页面的链接 |
启用时:
- 用户在开始通话前看到同意对话框
- 他们必须点击 "Agree" 才能继续
- 同意信息本地存储在浏览器中
- Reset Consent 按钮清除已存储的同意信息以便测试
内容格式
条款内容支持 Markdown 格式:
- 使用
####表示标题 - 使用
**bold**表示强调 - 使用换行提高可读性