Widgets de Website
Incorpore o seu agente de voz em qualquer site para que os visitantes possam iniciar uma conversa de voz diretamente do browser. A aba Widgets fornece códigos de incorporação, opções de personalização e definições de segurança de domínio.
O Widget de Callback funciona de forma muito diferente dos widgets nesta página — em vez de iniciar uma chamada de voz no browser, recolhe o número de telefone do visitante e faz o seu agente ligar-lhes de volta. Veja a página dedicada Widget de Callback.
Tipos de Widget
A Hanc.AI oferece quatro tipos de widget no browser, mais um Widget de Callback separado para callbacks telefónicos:
| Widget | Nome da Tag | Descrição | Melhor Para |
|---|---|---|---|
| Floating Widget | hanc-ai-floating-call | Botão orbe que flutua sobre a sua página | Call-to-action sempre visível |
| Pill Widget | hanc-ai-pill-call | Botão compacto em forma de pill colocado inline no seu conteúdo | Pegada mínima dentro de um layout existente |
| Pill Floating Widget | hanc-ai-pill-floating-call | Mesma forma compacta de pill que o Pill, mas flutua com a página como o widget Floating | Quando quer uma estética de pill que segue o visitante enquanto ele faz scroll |
| Inline Widget | hanc-ai-inline-call | Botão de chamada em tamanho completo incorporado no conteúdo da página | Secções dedicadas "Fale Connosco" |
| Callback Widget | hanc-ai-callback | Formulário de número de telefone; o agente liga de volta ao visitante | Páginas de geração de leads, landing pages de alta intenção — veja Widget de Callback |
Atributos Comuns
Todos os tipos de widget suportam estes atributos principais:
| Atributo | Obrigatório | Descrição | Padrão |
|---|---|---|---|
agent-id | Sim | O identificador único do seu agente | — |
voice-service-url | Não | Sobrepõe o URL do serviço de voz | Detetado automaticamente |
api-base-url | Não | Sobrepõe o URL base da API | Detetado automaticamente |
Atributos de Apresentação
| Atributo | Descrição | Valores | Padrão |
|---|---|---|---|
position | Posição do widget na página | bottom-right, bottom-left, top-right, top-left, static | bottom-right |
size | Tamanho do widget em píxeis | Número | 120 |
theme | Nome do tema de cor | Veja Temas de Cor | default |
Atributos de Texto do Botão
| Atributo | Descrição | Padrão |
|---|---|---|
button-start-text | Texto mostrado no botão inativo | "Call" |
button-connecting-text | Texto mostrado durante a ligação | "Connecting..." |
button-end-text | Texto mostrado durante uma chamada ativa | — |
Atributos de Termos
| Atributo | Descrição | Padrão |
|---|---|---|
terms-enabled | Ativar o diálogo de consentimento antes da chamada | false |
terms-content | Texto de consentimento formatado em Markdown | "" |
terms-url | Link para a sua página de Termos e Condições | "https://hanc.ai/terms" |
privacy-url | Link para a sua página de Política de Privacidade | "https://hanc.ai/privacy" |
Os atributos de termos definidos no elemento HTML são sobrepostos pelas definições de widget do agente obtidas da API, a menos que skip-fetch esteja definido como true.
Atributos de Som
| Atributo | Descrição | Padrão |
|---|---|---|
sound-enabled | Ativar sons de início/fim de chamada | true |
sound-volume | Volume do efeito sonoro | 0.25 |
sound-preset | Identificador do preset de som | "1" |
Temas de Cor
Personalize a aparência do widget com 11 temas de cor integrados:
| Tema | Valor |
|---|---|
| Default | default |
| Purple | purple |
| Blue | blue |
| Cyan | cyan |
| Emerald | emerald |
| Amber | amber |
| Tangerine | tangerine |
| Rose | rose |
| Ember | ember |
| Black | black |
| White | white |
Cada tema tem variantes escura e clara. Defina o tema através do atributo theme no código de incorporação, ou configure-o nas definições de widget do agente.
Exemplos de Incorporação
Floating Widget
<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>
Floating Widget com Tema e Posição
<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>
Pill Widget
<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>
Inline Widget
<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>
O URL do script acima carrega sempre o widget lançado mais recentemente — o seu site adota melhorias automaticamente, e @latest é o padrão quando nenhuma versão é especificada. Se precisar de fixar uma versão específica, faça-o explicitamente acrescentando a versão que quer, ex.: https://unpkg.com/hanc-webrtc-widgets@X.Y.Z.
Eventos do Widget
Os widgets emitem eventos que pode escutar em JavaScript:
| Evento | Descrição |
|---|---|
status-changed | Disparado quando o estado da chamada muda |
connecting | A chamada está a ser estabelecida |
connected | A chamada está ativa |
idle | Nenhuma chamada ativa |
error | Ocorreu um erro |
audio-track | Faixa de áudio remota recebida (para visualização) |
local-audio-track | Faixa de áudio do microfone local (para visualização) |
microphone-enabled | O microfone foi ativado |
microphone-disabled | O microfone foi desativado |
call-start | Disparado quando uma chamada inicia com sucesso |
call-end | Disparado quando a chamada termina |
Exemplo: Escutar Eventos
const widget = document.querySelector('hanc-ai-floating-call');
widget.addEventListener('call-start', () => {
console.log('Call started');
});
widget.addEventListener('call-end', () => {
console.log('Call ended');
});
Deixar o agente abrir páginas
Durante uma chamada pelo navegador, o agente pode pedir ao seu site que abra uma página — «deixe-me mostrar-lhe os preços» — e o visitante vê isso acontecer sem interromper a conversa.
Quem manda é a sua página. O agente envia um pedido; o seu código decide o que ele significa. Abrir um URL, mudar de separador, deslocar até uma secção e expandir um acordeão são todas respostas válidas.
São três passos, e nenhum funciona sozinho.
Passo 1 — Diga ao agente que páginas existem
O agente não vê o mapa do seu site. Só pede caminhos que lhe tenha dado — enumere-os no prompt do agente ou na base de conhecimento:
Páginas do nosso site:
/pricing — planos e preços
/contact — formulário de contacto e telefone
/product/crm — o CRM
Sem este passo o agente não tem o que pedir e nem sequer tenta.
Passo 2 — Trate o pedido na sua página
Acrescente isto uma vez, em qualquer ponto depois do script do widget. O evento sobe pela página, por isso document é um bom sítio para escutar:
<script>
document.addEventListener('agent-command', (event) => {
const { type, payload } = event.detail;
if (type === 'navigate') {
// SPA: navegar sem recarregar — a chamada continua.
router.push(payload.path);
// Site clássico: abrir um segundo separador; este (e a chamada) continua vivo.
// window.open(payload.path, '_blank');
event.preventDefault(); // ← é isto que diz ao agente «tratado»
}
});
</script>
A chamada vive nesta página. window.location.href = … descarrega o documento e a conversa vai com ele — o visitante é cortado a meio da frase. Se tiver um router, navegue do lado do cliente; caso contrário, abra a página num separador novo. Não há reconexão: nada sobrevive a um recarregamento.
preventDefault() não é opcionalÉ a única forma de dizer «tratei disto». Sem ele, o agente fica a saber que o site não suporta navegação: deixa de tentar durante o resto da chamada e volta a descrever onde clicar. Na consola não aparece nada — a página apenas parece ter ignorado o pedido, porque ignorou.
Passo 3 — Experimente
Ligue ao seu agente a partir do site e peça-lhe uma página pelo nome. Devem acontecer duas coisas: a página abre e o agente diz algo como «aqui estão os preços» em vez de «encontra-os no menu».
Responder ao agente com dados
Alguns comandos são perguntas, não instruções. Chegam da mesma maneira, mas responde-se com respond():
| Comando | O que o agente pergunta | Com o que responde |
|---|---|---|
navigate | «abre este caminho» | com nada — basta preventDefault() |
page_context | «o que está o visitante a ver?» | o que for útil: caminho, título, produto |
cart_state | «o que tem no carrinho?» | artigos, totais, moeda |
<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>
Depois de preventDefault() tem cerca de um segundo para responder: um await serve, uma chamada lenta a uma API não. Responda com o que já tem à mão.
O que o agente pode e não pode pedir
- Apenas caminhos do seu próprio site. O caminho tem de começar por
/. Tudo o que pudesse sair do seu domínio —//evil.com,https://…, barras invertidas — é recusado antes de chegar à sua página. Um agente não pode enviar os seus visitantes para outro lado. - Apenas chamadas pelo navegador. Numa chamada telefónica não há página para abrir, por isso ali estes comandos não existem.
- Uma recusa basta. Se a sua página não confirmar o primeiro pedido, o agente deixa de perguntar durante o resto da chamada. Não volta a tentar e — mais importante — não diz ao visitante que abriu algo que não abriu.
Registe cada comando antes de o filtrar: document.addEventListener('agent-command', e => console.log(e.detail)). Se vir navigate na consola, o agente fez a parte dele e o que falta é o preventDefault() ou o seu handler. Se não vir nada, nunca disseram ao agente que esse caminho existe — volte ao passo 1.
Requisitos Técnicos
Os widgets requerem que o browser do visitante suporte:
- WebGL 2.0 — para renderização
- Web Audio API — para processamento de áudio
- WebRTC — para comunicação de voz em tempo real
Todos os browsers modernos (Chrome, Firefox, Safari, Edge) suportam estas tecnologias.
Restrições de Domínio
Controle que sites podem incorporar o widget do seu agente.
Domínios Sempre Permitidos
Os seguintes domínios são sempre permitidos independentemente da configuração:
hanc.ai(e subdomínios)hanc.me(e subdomínios)localhost
Permitir Todos os Domínios
Por padrão, o seu widget pode ser incorporado em qualquer site. Ative "Allow all domains" nas definições de widget para restringir isto.
Restringir a Domínios Específicos
Quando restringido, adicione cada domínio que deve ser permitido:
- Introduza os nomes de domínio sem
https://(ex.:example.com) - Os subdomínios precisam de entradas separadas (ex.:
www.example.com,shop.example.com) - As portas podem ser especificadas (ex.:
localhost:3000) - No máximo 50 domínios podem ser autorizados
Para agentes em produção, restrinja os widgets aos seus próprios domínios para prevenir incorporação não autorizada.
Termos e Condições
Ative um diálogo de consentimento antes de os interlocutores poderem iniciar uma conversa.
Configuração
| Definição | Descrição |
|---|---|
| Enable Terms | Toggle do diálogo de termos on/off |
| Terms Content | Texto de consentimento formatado em Markdown mostrado aos utilizadores (máx. 5.000 caracteres) |
| Terms URL | Link para a sua página completa de Termos e Condições |
| Privacy URL | Link para a sua página de Política de Privacidade |
Quando ativado:
- Os utilizadores veem um diálogo de consentimento antes de iniciar uma chamada
- Têm de clicar em "Agree" para prosseguir
- O consentimento é armazenado localmente no browser
- O botão Reset Consent limpa o consentimento armazenado para testes
Formatação de Conteúdo
O conteúdo dos termos suporta formatação Markdown:
- Use
####para cabeçalhos - Use
**bold**para ênfase - Use quebras de linha para legibilidade
Relacionados
- Widget de Callback — Callbacks telefónicos para visitantes que preferem não falar no browser
- Visão Geral dos Agentes de Voz IA
- Definições — Definições do agente incluindo a configuração de widgets
- Integrações — Chaves de API e configuração de números de telefone