Vai al contenuto

Widget B2C — visitante convidado e empresa

Esta secção cobre as integrações em que o widget fica em sessão de convidado:

  • site público, visitante desconhecido: só o script e o formulário de contacto
  • site ou portal que já conhece a conta: init() com perfil e dados da empresa, formulário omitido quando os dados chegam, contacto ligado à empresa

O histórico pessoal noutro browser ou dispositivo é outra integração. Vê Widget B2B. Contrato completo dos campos, mudança de conta numa SPA, CSP e provisioning: Integração técnica.

Associar uma empresa não autoriza o histórico de outra pessoa. Um utilizador autenticado no site continua a ser um convidado do widget até enviares external_user_id juntamente com um restore_id válido.


O que obténs

  • Um botão flutuante, ou um chat incorporado num contentor da página
  • Um formulário inicial para quem é desconhecido, com as etiquetas Telefone e Nome. Em init() os campos são phone e name
  • Uma sessão de convidado guardada pelo loader no mesmo browser, separada por chave de widget. Se o localStorage estiver bloqueado, a continuidade pode ficar na página atual
  • Se envias external_id, a Quoting24 procura uma empresa com o mesmo web_code. Com company_name também, pode criar a empresa em falta e ligar o contacto
  • Tickets e respostas na Quoting24, como nos outros canais

A sessão de convidado relê a sua conversa mais recente mesmo depois de fechar o separador. Não segue a pessoa para outro browser.


1. Pré-requisitos na Quoting24

  1. Canal Widget ativo em Definições → Canais
  2. Logótipo, cor, posição, saudação, boas-vindas e fora de horário configurados
  3. Domínios permitidos atualizados, incluindo testes e localhost
  4. Código de incorporação copiado da configuração do canal: URL do script e chave pública

Usa o host e a chave do mesmo ambiente. Nos exemplos substitui HOST_WIDGET e CHAVE_PUBLICA_WIDGET.

Os domínios são nomes de host, sem https://, porta, caminho ou *.. example.com inclui os subdomínios. Lista vazia: nenhuma restrição. Em local serve a página por HTTP, não como file://.

O company_name de init() é a denominação social do cliente. Não é o título do widget e não se configura a partir deste payload.


2. Instalar o botão flutuante

Cola o script uma só vez, antes de </body>:

<script
  src="https://HOST_WIDGET/assets/widget/script.js?key=CHAVE_PUBLICA_WIDGET"
  async
></script>

O botão aparece depois de carregar as definições gráficas. Um visitante novo vê o formulário de contacto. Quem volta no mesmo browser retoma a sessão de convidado, se o armazenamento estiver disponível.

O script expõe um único window.Quoting24Widget.


3. Incorporar o chat na página

Cria o contentor antes do script e dá-lhe uma altura explícita:

<section aria-labelledby="titulo-assistencia">
  <h2 id="titulo-assistencia">Assistência</h2>
  <div id="chat-assistencia" style="width: 100%; height: 600px;"></div>
</section>

<script
  src="https://HOST_WIDGET/assets/widget/script.js?key=CHAVE_PUBLICA_WIDGET&amp;mode=embedded&amp;target=chat-assistencia"
  async
></script>
  • target é o ID do elemento, sem #
  • O iframe preenche o contentor
  • Não há botão flutuante
  • open(), close() e toggle() não têm efeito
  • Neste modo o site decide a altura e a largura. No modo flutuante, no telemóvel, o chat pode ocupar o viewport

O modo incorporado, por si só, não ativa o restauro do histórico.


4. Enviar o perfil do cliente

Quando o site conhece a conta, envia o perfil depois de carregar o loader. Os campos são cadeias. Omite os desconhecidos: não envies null, IDs numéricos nem um e-mail vazio.

window.Quoting24Widget.init({
  external_id: "52",
  company_name: "Ricambi Stella S.r.l.",
  name: "mario.rossi",
  phone: "+393331234567",
  email: "amministrazione@ricambi-stella.example",
});
Dado no site ou no ERP Campo Significado
Referência estável da empresa, o mesmo valor importado em web_code external_id Comparação exata com companies.web_code, na organização do widget
Denominação social company_name Usada se for preciso criar a empresa
Nome da pessoa ou do utilizador name Nome mostrado no contacto
E-mail da conta email Guardado na empresa só quando a empresa é criada
Telefone, se o conheceres phone Número do contacto. Prefere o formato internacional, por exemplo +393331234567

Este payload não envia external_user_id nem restore_id. Mantém name e company_name separados: não concatenes a denominação social ao nome de utilizador para obter a associação. O campo público é external_id. Não envies web_code, o UUID interno da Quoting24 nem companies.code.

O formulário mostra Nome e Telefone. Em init() esses campos chamam-se name e phone. O e-mail chama-se email. Nome, Telefone e Email não são chaves: o loader descarta-as, como descarta web_code no lugar de external_id.

Exemplos

Nome e telefone, os mesmos dados do formulário. O chat começa e não procura uma empresa.

widget.init({
  name: "Mario Rossi",
  phone: "+393331234567",
});

Perfil com empresa. name é a pessoa, phone o número do contacto e email fica na empresa só se esta chamada a criar.

widget.init({
  external_id: "52",
  company_name: "Ricambi Stella S.r.l.",
  name: "Mario Rossi",
  phone: "+393331234567",
  email: "mario.rossi@ricambi-stella.example",
});

Só e-mail. Um endereço válido em email chega para abrir a sessão.

widget.init({
  email: "mario.rossi@ricambi-stella.example",
});

Se um campo ultrapassar os limites ou o e-mail estiver mal formado, o pedido é rejeitado. Limites e comportamento de cada campo: Integração técnica.

Esperar pelo loader

Um script async pode ainda não ter corrido quando o código seguinte chama init(). Para dados pré-preenchidos usa um módulo de carga em vez da etiqueta estática, importado uma só vez no layout principal:

// /assets/quoting24-loader.js
const widgetScriptUrl =
  "https://HOST_WIDGET/assets/widget/script.js?key=CHAVE_PUBLICA_WIDGET";

let widgetPromise;

export function loadWidget() {
  if (window.Quoting24Widget) {
    return Promise.resolve(window.Quoting24Widget);
  }
  if (widgetPromise) return widgetPromise;

  widgetPromise = new Promise((resolve, reject) => {
    const script = document.createElement("script");
    script.id = "quoting24-widget-script";
    script.src = widgetScriptUrl;
    script.async = true;
    script.onload = () => {
      if (window.Quoting24Widget) resolve(window.Quoting24Widget);
      else {
        script.remove();
        reject(new Error("A API do widget não está disponível"));
      }
    };
    script.onerror = () => {
      script.remove();
      reject(new Error("Não foi possível carregar o widget"));
    };
    document.body.appendChild(script);
  }).catch((error) => {
    widgetPromise = undefined;
    throw error;
  });

  return widgetPromise;
}
import { loadWidget } from "/assets/quoting24-loader.js";

const widget = await loadWidget();
widget.init({
  external_id: "52",
  company_name: "Ricambi Stella S.r.l.",
  name: "mario.rossi",
  phone: "+393331234567",
  email: "amministrazione@ricambi-stella.example",
});

Importa o módulo a partir do bundler, ou carrega o ficheiro de entrada com <script type="module" src="/assets/assistencia.js"></script>. Para o modo incorporado acrescenta &mode=embedded&target=chat-assistencia ao URL e monta primeiro o contentor.

loadWidget() só indica que a API JavaScript está disponível. init() devolve void: põe o perfil em fila se o iframe não estiver pronto e não espera pela sessão. Para o resultado usa isReady() e hasSessionError().

init() substitui o perfil guardado. Não o funde com o anterior. Passa todos os campos que devam permanecer.

Uma mudança de página numa SPA não exige um script novo nem um reset(). Na mudança de pessoa ou de conta, e no logout, chama reset() antes do perfil novo: mudar só os campos não desliga a sessão de convidado anterior. Padrão completo: Login, logout e mudança de conta.


5. Como a empresa é associada ou criada

A Quoting24 executa este fluxo na inicialização, mesmo que o visitante ainda não tenha enviado uma mensagem:

  1. Com um external_id não vazio, procura uma empresa da mesma organização cujo web_code seja igual a esse valor
  2. Se a encontrar, liga o contacto. O nome e o e-mail da empresa existente não mudam
  3. Se não a encontrar e também houver um company_name não vazio, cria a empresa com name = company_name, web_code = external_id e o e-mail se existir, e depois liga o contacto
  4. Se não puder encontrar nem criar a empresa, continua com o perfil disponível. Se não chegar para um convidado novo, mostra o formulário. Erros de base de dados ou o limite de pedidos fazem falhar a inicialização
Dados enviados Situação na Quoting24 Resultado
external_id: "52", company_name: "Ricambi Stella S.r.l." Existe web_code = "52" Usa a empresa existente e não muda o nome
Os mesmos dados, mais um e-mail válido Não existe web_code = "52" Cria a empresa com código web 52, denominação social e e-mail, e associa o contacto
external_id: "52", name: "mario.rossi" Nenhuma correspondência Inicia o convidado sem uma associação de empresa nova
external_id: "52", sem outros dados Existe uma correspondência Inicia o convidado associado à empresa, com o nome predefinido Visitatore
external_id: "52", sem outros dados Nenhuma correspondência Mostra o formulário de contacto
company_name sem external_id, mais name Qualquer Inicia o visitante. Não procura nem cria uma empresa

A pesquisa não usa denominação social, e-mail, telefone, NIF nem companies.code. "052" e "52" são valores diferentes; os espaços de external_id não são retirados. Se importares o ficheiro antes, escreve em web_code o mesmo valor que o site vai enviar em external_id. Vê também Empresas → Código web.

Um convidado novo arranca se houver pelo menos um nome, um telefone, um e-mail válido ou um external_user_id, ou uma empresa encontrada ou criada através de external_id. init({}) e company_name sozinho não iniciam uma sessão.

Para um contacto já ligado, um código válido novo pode mudar a empresa. Omitir o código, ou enviar um que não se resolve, não apaga a associação anterior. A mudança de pessoa ou de conta exige reset().

Limites

web_code não é único. Com várias correspondências, a inicialização pública toma a primeira por data de criação crescente. Pedidos simultâneos que ainda não encontram a empresa podem criar mais do que uma: a criação não é atómica e não substitui uma importação ou uma sincronização a partir do ERP.

A criação implícita está limitada a 20 tentativas por janela de 60 segundos e endereço IP, no processo de backend que trata o pedido. Acima do limite a inicialização falha com TOO_MANY_REQUESTS: tenta de novo com espera, sem ciclos contínuos de init().

Os dados saem do browser e o visitante pode alterá-los. A ligação não prova a pertença à empresa e não concede o histórico da empresa. Envia company_name só se quiseres permitir esta criação pública. Para atualizar empresas já existentes usa as ferramentas da Quoting24 ou uma integração de ERP autorizada.

O e-mail da inicialização pública só fica na empresa nova. Não é escrito no contacto e não atualiza uma empresa já existente. Um telefone já usado por outro contacto não junta contactos nem chats.


6. Comportamento no site

Situação Comportamento esperado
Primeiro visitante, só script Botão, depois formulário, depois chat
init() com perfil suficiente Formulário omitido
external_id já presente como web_code Contacto associado; nome e e-mail da empresa inalterados
external_id novo com company_name Empresa criada e contacto associado
Código novo e nome, sem company_name Chat sem empresa nova
Só código novo Formulário de contacto
Só denominação social e nome Nenhuma pesquisa nem criação por nome
Recarregamento no mesmo browser Sessão de convidado retomada, se o armazenamento estiver disponível
Outro browser ou dispositivo Sessão de convidado nova
Fora de horário Banner fora de horário; a composição continua utilizável
Telemóvel, botão flutuante O chat pode ocupar o viewport

Anexos: PDF, DOC, DOCX, JPG/JPEG, PNG. Máximo de 10 MiB por ficheiro e 100 MiB de anexos referenciados por conversa.


7. Controlos úteis

Quando o botão flutuante está visível podes ligar um botão do site a window.Quoting24Widget?.open().

Método Uso
init(profile) Define ou substitui o perfil atual
open() / close() / toggle() Só widget flutuante. Fechar não é um logout
isReady() Sessão de visitante iniciada. Continua falso no formulário de contacto
hasSessionError() Erro de sessão assinalado pelo iframe
reset() Apaga perfil, sessão local, credencial de convidado guardada e não lidos desta instância
dispose() Desmonta a interface e os listeners. Não apaga a credencial de convidado guardada nem o objeto API global

Não esperes por isReady() para um convidado novo abrir o formulário. Não há um evento público de disponibilidade. Estes indicadores não descrevem todo o estado da rede.


Lista de verificação antes da entrada em produção

  • [ ] Host e chave do mesmo ambiente
  • [ ] Domínios do site e do staging na lista, só como nomes de host
  • [ ] Logótipo, cor, saudação, boas-vindas e fora de horário verificados
  • [ ] Browser novo, só script: formulário, mensagem, ticket na Quoting24
  • [ ] external_id já em web_code: associação, ficha da empresa inalterada
  • [ ] Código novo com company_name: empresa criada com esse código web
  • [ ] Código novo sem company_name: nenhuma empresa criada
  • [ ] E-mail vazio, ID numérico ou denominação social demasiado longa: payload rejeitado, a corrigir
  • [ ] Recarregamento e navegação SPA: uma só instância, sessão de convidado conservada
  • [ ] Mudança de conta: reset() de imediato, respostas tardias descartadas
  • [ ] Telemóvel: composição utilizável
  • [ ] Domínio não autorizado: widget rejeitado

Problemas frequentes: Resolução de problemas.