Widget per il sito
Il widget è la chat del tuo bot direttamente sul sito: un pulsante rotondo nell'angolo della pagina da cui si apre una conversazione. Per il visitatore è un modo in più per scriverti; per il bot è un canale come gli altri, con le stesse reazioni e gli stessi dialoghi operatore dei messenger. Panoramica della multicanalità: Canali.
L'installazione è un solo frammento di codice incollato nel template del sito. Tutto il resto si configura nel pannello e viene applicato senza toccare più il sito.
Dove trovare il codice
Nel pannello apri Widget → blocco Installazione sul sito → campo Codice da inserire. Il pulsante Copia mette l'intero frammento negli appunti.
Il codice ha questo aspetto, con la tua chiave al posto dei puntini:
<script>
window.mybot = { key: "eu-1a2b3c4d-..." };
</script>
<script async src="https://getmybot.dev/loader.js"></script>
Se al posto del codice vedi che per questo bot non è ancora stata emessa una chiave di installazione, il canale widget non è collegato. Scrivi all'assistenza: la chiave viene emessa alla connessione del canale.
Sotto il codice c'è l'indicazione dell'host che il widget contatterà. Se il sito usa una CSP (Content Security Policy), consenti a quell'host di caricare script e di ricevere richieste, altrimenti il browser bloccherà il widget in silenzio.
Dove va il codice
Il frammento va nell'HTML di ogni pagina in cui il widget deve comparire. In pratica: una sola volta nel template comune — il footer, il campo «codice prima di </body>» del CMS o un contenitore del tag manager.
Le regole sono brevi:
- Il posto migliore è subito prima del
</body>di chiusura. Anche<head>funziona, ma allora il browser dedica tempo al widget prima che ai tuoi contenuti. - L'ordine dei due tag conta: il primo imposta la chiave, il secondo carica il widget. Non invertirli e non separarli nella pagina.
- Il secondo tag ha
asynce non blocca il rendering. Non rimuovere quell'attributo. - Un frammento per pagina. Due copie sono due tentativi di avvio.
Da lì in poi il loader stabilisce da quale data center è servito il tuo bot e ne scarica il codice. Da parte tua non serve altro.
La chiave di installazione è pubblica
La chiave nel primo tag è un identificatore pubblico del bot, non una password. Sta nel codice sorgente della pagina: qualsiasi visitatore può aprire «Visualizza sorgente» e leggerla. Tutti i widget di chat funzionano così, ed è normale.
Cosa conta:
- Con la chiave non si entra nel pannello, non si leggono dialoghi altrui, non si esporta la base iscritti e non si modifica nulla del bot. Abilita esattamente una cosa: avviare una nuova conversazione con questo bot.
- Non trattarla come un segreto: nasconderla o offuscarla non serve a niente.
- Se va sostituita (per esempio dopo esserti separato da un fornitore) se ne occupa l'assistenza. Dopo la sostituzione il vecchio codice sul sito smette di funzionare e va aggiornato.
Elenco dei domini consentiti
Il widget ha un elenco di domini consentiti (origin allowlist): gli indirizzi da cui gli è permesso funzionare. Si imposta alla connessione del canale e si modifica in seguito senza riemettere la chiave, quindi il codice sul sito resta invariato.
Le voci sono origini: schema, host e, se non standard, porta.
https://example.com
https://www.example.com
https://shop.example.com
http://localhost:3000
Il confronto è esatto, carattere per carattere:
- Niente caratteri jolly.
https://*.example.comnon funziona: elenca i sottodomini uno per uno. example.comewww.example.comsono voci diverse. Se il sito risponde a entrambi, servono entrambe.- Anche
http://ehttps://sono voci diverse. Di solito bastahttps://, ma un ambiente di test suhttp://va aggiunto esplicitamente. - Nessun percorso:
https://example.com/shopviene rifiutato, un'origine è solo l'indirizzo del sito.
Se il tuo dominio reale non è nell'elenco, il widget non parte. Il browser del visitatore riceve un rifiuto «origin not allowed» e la chat semplicemente non si apre. Succede tipicamente dopo un trasloco su un dominio nuovo, l'aggiunta di un sottodominio o il lancio di una seconda versione linguistica su indirizzo proprio: ciascuna richiede la sua voce.
Se l'elenco è vuoto non c'è alcuna restrizione e il widget funziona ovunque. Consideralo «non ancora configurato», non un'apertura voluta: appena conosci i tuoi domini, inseriscili.
Cosa protegge questa restrizione e cosa no
Protegge: impedisce a un altro sito di incorporare il tuo widget. Altrimenti qualcuno potrebbe copiare il frammento nella propria pagina e i browser di visitatori reali consegnerebbero a quel sito il contenuto delle conversazioni con il tuo bot. È esattamente ciò che l'elenco chiude.
Non protegge: non ferma chi ha copiato la chiave e interroga la piattaforma direttamente — non dal browser ma, per esempio, da uno script. L'intestazione con l'indirizzo del sito la mette il browser; un programma fuori dal browser può ometterla o inviarne un'altra. Consideralo un limite all'incorporamento, non un confine di sicurezza. Contro gli abusi proteggono i limiti di frequenza e la moderazione dei dialoghi della piattaforma, non questo elenco.
Aspetto
In Widget → Aspetto si impostano:
- Posizione: il pulsante in basso a sinistra o a destra.
- Colore d'accento: colore del pulsante e degli elementi della chat. Usa il colore del tuo brand perché il widget non sembri estraneo.
- Nome della chat: etichetta del pulsante e titolo del pannello. Di solito il nome dell'azienda o quello con cui il bot si presenta.
Accanto c'è un'anteprima: un widget vivo che mostra il risultato prima di salvare.
Il widget non ha ancora un messaggio di benvenuto: sono soltanto queste tre impostazioni. Il primo messaggio il bot lo invia in risposta al visitatore, secondo le tue reazioni abituali.
Le modifiche raggiungono il sito da sole: il widget legge le impostazioni al caricamento della pagina, il codice inserito non va mai modificato.
I visitatori sono anonimi
Il visitatore non compila nulla per scrivere. Al primo avvio il widget riceve dalla piattaforma un identificatore anonimo di visitatore e lo salva nel browser, così al ritorno la persona ritrova la propria conversazione e non una chat vuota.
Ne consegue che:
- Nei dialoghi quel visitatore appare come anonimo: senza nome, telefono o e-mail finché non li scrive lui stesso.
- L'identificatore vive in un browser preciso. Un altro browser, un altro dispositivo o i dati del sito cancellati significano un nuovo visitatore con cronologia pulita.
- Un visitatore anonimo può essere collegato a un cliente che già conosci, per esempio un utente autenticato della tua area riservata. Come farlo è spiegato nella sezione seguente.
Collegare un visitatore al tuo utente
Se il visitatore ha già effettuato l'accesso sul tuo sito, puoi dire alla piattaforma chi è. Dopo il collegamento la conversazione smette di essere anonima: viene unita al profilo di quella persona e i suoi messaggi anonimi precedenti non vanno persi.
Basta una chiamata, con una funzione che produce la prova:
mybot.identify(async (visitorId) => {
const res = await fetch("/mybot-sign", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userId: currentUser.id, visitorId }),
});
return res.json(); // { userId, signature, expiresAt }
});
Il widget chiama la tua funzione con visitorId — l'identificatore anonimo attuale del visitatore per questo browser, l'unico valore che conosce solo il widget — e attende che restituisca, o risolva in, { userId, signature, expiresAt }. L'unico compito della tua funzione è consegnare visitorId al tuo server, insieme all'identificatore dell'utente autenticato (currentUser.id sopra è quello che è sul tuo sito), e restituire esattamente ciò che risponde il tuo server. La firma vera e propria avviene sul tuo server, non in questa funzione — vedi sotto.
Una callback, non un valore già pronto né un modo per leggere visitorId direttamente, per due motivi:
- Il momento in cui esiste. Il widget genera
visitorIdin modo asincrono all'avvio — non esiste nell'istante in cui viene eseguito lo script di caricamento, emybot.identifystesso viene installato solo dopo che questo è finito (dettagli più sotto). Quindi, nel momento in cui la tua pagina può chiamaremybot.identify, l'identificatore che riceve la tua funzione è garantito reale. Un semplice getter non avrebbe questa garanzia: nulla impedirebbe a una pagina di leggerlo una riga troppo presto e di non ottenere nulla, producendo in silenzio una firma che non torna mai, senza alcun indizio sul perché. - L'ambito. Il codice della tua pagina non deve mai conservare, salvare o passare
visitorIda mano — esiste solo dentro questa funzione, per l'unica chiamata di cui ha bisogno.
Dal momento in cui lascia il widget, visitorId è una capacità al portatore (bearer capability): chiunque riesca a ottenere una firma per esso può essere unito alla sessione di quel visitatore. Inviala solo al tuo server, tramite una tua richiesta autenticata, e da nessun'altra parte — non registrarla nei log, non inoltrarla a terzi e non metterla in una chiamata di analitica lato client.
La firma si calcola solo sul tuo server
Dentro la tua funzione qui sopra, il tuo server — mai il browser — calcola la firma: un HMAC-SHA256, con il segreto del widget come chiave, in esadecimale, i primi 32 caratteri, di tre valori uniti in un unico messaggio. La stessa formula compare nel pannello accanto al segreto, sotto «Signing algorithm»:
signature = hex(HMAC-SHA256(key: secret, message: userId + "\n" + visitorId + "\n" + expiresAt)).slice(0, 32)
Ogni + "\n" + sopra è un vero carattere di ritorno a capo tra le parti, non i due caratteri barra rovesciata e n. Se la tua funzione HMAC prende il messaggio come un'unica stringa, unisci le tre parti con un ritorno a capo reale: tre chiamate .update() separate senza un a-capo tra loro fanno l'hash di un messaggio diverso, e sbagliato.
Le tre parti:
userId— l'identificatore dell'utente autenticato, lo stesso valore che il tuo server riceve dalla funzione qui sopra e restituisce nella sua risposta.visitorId— l'identificatore anonimo di visitatore che la tua funzione ha ricevuto come argomento e inoltrato invariato al tuo server.expiresAt— un timestamp unix in secondi (non millisecondi) fino a cui questa specifica firma resta valida, prodotto dal tuo server al momento della firma. La piattaforma rifiuta una chiamata il cuiexpiresAtè già nel passato, e una che è più di 24 ore nel futuro — firmala giusto prima di restituirla dalla tua funzione, non una volta per poi tenerla in cache per richieste successive.
Questa scadenza è il vero motivo del cambiamento, non un dettaglio secondario. La formula precedente copriva solo l'identificatore utente, quindi una firma catturata una volta — loggata da qualche parte, intercettata sulla rete, non importa come — restava valida per sempre e andava bene per qualsiasi visitatore, non solo per quello a cui era stata rilasciata. Chiunque se ne fosse impossessato avrebbe potuto riprodurla su un browser completamente diverso, e la piattaforma avrebbe unito la navigazione anonima di uno sconosciuto al profilo di un cliente reale. Legare la firma a uno specifico visitorId e darle una vita breve chiude entrambi i lati di questa falla: si convalida solo per la sessione per cui è stata rilasciata e per nessun'altra, e smette del tutto di convalidarsi una volta passato expiresAt — così anche una firma trapelata resta solo un rischio breve, di una singola sessione, non permanente.
Calcola tutti e tre i valori sul tuo server e restituiscili dalla tua funzione già pronti. Non è una formalità: per calcolare la firma nel browser dovresti spedirci il segreto, cioè consegnarlo a ogni visitatore della pagina. Da quel momento chiunque potrebbe spacciarsi per un tuo cliente qualsiasi e leggerne la conversazione. La firma (e visitorId/expiresAt per cui è stata calcolata) è sicura da restituire al browser, il segreto no.
La chiamata in sé non mostra nulla a schermo: il collegamento avviene lato server e in silenzio. Se la tua funzione lancia un errore o la sua promise viene rifiutata, oppure la piattaforma rifiuta la firma risultante — non torna, oppure expiresAt manca, è già passato o è a più di 24 ore nel futuro — non succede altro: il visitatore non se ne accorge e continua a scrivere da anonimo.
mybot.identify non esiste all'istante: compare quando il bundle principale del widget è stato caricato, insieme a un visitorId reale (vedi «Il momento in cui esiste» sopra). Chiamalo da un gestore di caricamento della pagina, non come prima riga nel <head>.
Dove trovare il segreto e come cambiarlo
Il segreto del widget è la chiave con cui firmi. Sta nelle impostazioni del widget, nella sezione «identify() secret». Se quella sezione dice che il widget non è ancora collegato, collega prima il canale web: il segreto compare insieme a esso.
Mostrare. Il pulsante «Reveal secret» richiede il valore. Non appare in chiaro: prima vedi dei puntini, e un interruttore a parte, «Show», mostra i caratteri («Mask» li nasconde di nuovo). Accanto c'è «Clear from screen», che toglie il valore dalla vista.
Puoi mostrarlo quante volte vuoi, e mostrarlo non invalida nulla: il segreto resta valido anche dopo aver chiuso la schermata. È così perché viene conservato cifrato e non con hash: alla piattaforma serve il valore reale per verificare ogni firma. Se tra sei mesi rilasci un nuovo backend, torna semplicemente a rileggerlo.
Dopo averlo copiato, rimetti a posto da solo. La piattaforma non può svuotare i tuoi appunti: dal browser non si può fare in modo affidabile, quindi non lo promettiamo. Togli il valore dallo schermo e svuota gli appunti a mano quando hai finito, soprattutto su un computer condiviso.
Cambiare. Il pulsante «Rotate secret», con passaggio di conferma. È un'azione che rompe all'istante: appena il nuovo segreto esiste, il vecchio smette di verificare. Non c'è finestra di sovrapposizione, nessun momento in cui valgano entrambe le chiavi.
Ciò che si rompe è esattamente il collegamento dei visitatori ai tuoi utenti. Le conversazioni non si interrompono: i visitatori continuano a scrivere e a ricevere risposta, solo da anonimi, finché il tuo backend non firma con il nuovo segreto. Il codice di installazione e l'elenco dei domini consentiti non vengono toccati, sul tuo sito non c'è nulla da cambiare.
Cambia quindi il segreto con cognizione di causa: prepara prima il rilascio del backend con il nuovo valore e solo dopo premi «Rotate secret». Premerlo per vedere che succede è una pessima idea. Il nuovo valore viene mostrato a schermo subito dopo il cambio, così puoi copiarlo immediatamente.
Come si comporta il widget nella pagina
Il widget è fatto apposta per non interferire con il sito:
- Vive in un contenitore isolato (Shadow DOM chiuso). I tuoi stili non entrano e i suoi non escono sulla pagina. Effetto collaterale: non puoi ridisegnarlo con il tuo CSS — usa le impostazioni di aspetto.
- Il contenitore copre lo schermo ma non intercetta i clic: passano alla pagina, rispondono solo il pulsante e il pannello della chat.
- Il widget sta sempre sopra i tuoi contenuti; i tuoi livelli non possono coprirlo.
- Qualsiasi errore interno resta interno: al peggio non funziona il pulsante della chat, il sito continua a girare. Se il widget non compare, guarda la console del browser — quasi sempre è la CSP o un dominio mancante nell'elenco.
Se il widget non compare
Procedi in ordine:
- Apri il sorgente della pagina e verifica che ci siano entrambi i tag e che la chiave non sia vuota.
- Verifica che l'indirizzo del sito sia esattamente quello dell'elenco,
https://ewwwcompresi. - Guarda la console del browser: un messaggio sulla Content Security Policy significa che l'host della piattaforma va consentito nella CSP del sito.
- Assicurati che un blocco pubblicità non rimuova il widget: prova in una finestra privata senza estensioni.
Cosa leggere dopo
- Canali — multicanalità e capacità dei canali.
- Reazioni: basi — cosa risponderà il bot a un visitatore.
- Chat e operatori — come risponde un operatore nella conversazione.