Eventi
Eventi emessi dal widget BluBot, payload di ciascuno e inoltro verso Google Analytics 4 e Tag Manager.
BluBot emette eventi in due forme equivalenti: tramite BluBot.on(...) e come
CustomEvent su window con il prefisso blubot:. Usa la prima per la logica
applicativa, la seconda quando devi ascoltare prima che il widget sia pronto.
Ascolto rapido di tutti gli eventi (debug)
window.BluBot.on('*', (e) => console.log('[blubot]', e))Incollalo nella console del browser per osservare il flusso degli eventi.
Riepilogo
| Evento | Quando scatta | Frequenza |
|---|---|---|
ready | Il widget è inizializzato e utilizzabile | Una volta per caricamento |
open | La finestra di chat viene aperta | Ogni apertura |
close | La finestra viene chiusa | Ogni chiusura |
message:sent | L'utente invia un messaggio | Ogni messaggio in uscita |
message:received | L'assistente o l'operatore risponde | Ogni messaggio in entrata |
handover:requested | Viene richiesto un operatore umano | Una volta per richiesta |
handover:started | Un operatore prende in carico la conversazione | Una volta per presa in carico |
booking:completed | Una prenotazione viene confermata nel flusso | Ogni prenotazione |
error | Si verifica un errore recuperabile o bloccante | Variabile |
ready
Scatta quando il widget ha completato l'inizializzazione, ha validato la chiave di progetto e ha caricato la configurazione. Da questo momento tutti i metodi dell'API sono invocabili.
{
"version": "1.24.0",
"projectKey": "bp_proj_7f3a9c21",
"sessionId": "ses_c41f7d2a9b0e4386",
"locale": "it",
"environment": "production",
"isReturning": true
}window.addEventListener('blubot:ready', function (event) {
console.log('BluBot pronto, sessione', event.detail.sessionId);
if (event.detail.isReturning) {
window.BluBot.open();
}
});open
Scatta all'apertura della finestra, sia manuale sia programmatica.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"trigger": "launcher",
"hasUnread": false,
"timestamp": "2026-09-04T10:15:32.114Z"
}Valori possibili di trigger: launcher, api, auto_open, proactive_message,
deep_link.
window.BluBot.on('open', function (payload) {
if (payload.trigger === 'auto_open') {
console.log('Apertura automatica dopo il ritardo configurato');
}
});close
Scatta alla chiusura della finestra. La sessione resta attiva.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"trigger": "user",
"messageCount": 6,
"durationMs": 184000
}window.BluBot.on('close', function (payload) {
if (payload.messageCount === 0) {
console.log('Chat aperta e chiusa senza interazione');
}
});message:sent
Scatta quando l'utente invia un messaggio, anche tramite sendMessage.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"messageId": "msg_a71b90c3",
"text": "Vorrei prenotare una visita cardiologica",
"length": 41,
"hidden": false,
"timestamp": "2026-09-04T10:16:02.900Z"
}Contenuto dei messaggi
Il campo text contiene quanto scritto dall'utente e può includere dati personali.
Non inoltrarlo a strumenti di analisi: usa length o un valore aggregato.
window.BluBot.on('message:sent', function (payload) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'blubot_message_sent',
blubot_session_id: payload.sessionId,
blubot_message_length: payload.length
});
});message:received
Scatta a ogni messaggio ricevuto dall'assistente o da un operatore.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"messageId": "msg_a71b90c4",
"source": "assistant",
"text": "Certo. Per quale sede preferisci prenotare?",
"hasWidget": false,
"citations": [
{ "documentId": "doc_9f31", "title": "Listino prestazioni 2026", "page": 12 }
],
"latencyMs": 1240,
"timestamp": "2026-09-04T10:16:04.140Z"
}Valori possibili di source: assistant, operator, system.
window.BluBot.on('message:received', function (payload) {
if (payload.latencyMs > 5000) {
console.warn('Risposta lenta:', payload.latencyMs, 'ms');
}
});handover:requested
Scatta quando la conversazione viene messa in coda per un operatore umano.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"reason": "user_request",
"queue": "assistenza-generale",
"queuePosition": 3,
"estimatedWaitSec": 120,
"businessHours": true
}Valori possibili di reason: user_request, low_confidence, flow_action,
repeated_fallback, negative_sentiment, keyword.
window.BluBot.on('handover:requested', function (payload) {
if (!payload.businessHours) {
document.getElementById('avviso-orari')?.classList.remove('nascosto');
}
});handover:started
Scatta quando un operatore prende in carico la conversazione.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"operator": { "id": "opr_1187", "displayName": "Giulia" },
"waitedSec": 96,
"timestamp": "2026-09-04T10:18:04.000Z"
}window.BluBot.on('handover:started', function (payload) {
console.log('Presa in carico da', payload.operator.displayName);
});booking:completed
Scatta quando un flusso conferma una prenotazione. È l'evento da usare per la misurazione delle conversioni.
{
"sessionId": "ses_c41f7d2a9b0e4386",
"bookingId": "bkg_71c9d0a4",
"service": { "code": "VIS_CARD", "name": "Visita cardiologica" },
"startsAt": "2026-09-09T09:00:00+02:00",
"location": { "code": "MI01", "name": "Milano — Vittor Pisani" },
"value": 120,
"currency": "EUR",
"channel": "web"
}window.BluBot.on('booking:completed', function (payload) {
window.gtag?.('event', 'purchase', {
transaction_id: payload.bookingId,
value: payload.value,
currency: payload.currency,
items: [{ item_id: payload.service.code, item_name: payload.service.name }]
});
});error
Scatta su ogni errore gestito dal widget.
{
"code": "origin_not_allowed",
"message": "Origin https://www.acme.it is not authorised for this project.",
"fatal": true,
"sessionId": null,
"timestamp": "2026-09-04T10:15:31.002Z"
}| Codice | Significato | fatal |
|---|---|---|
invalid_project_key | Chiave inesistente o di un altro ambiente | Sì |
origin_not_allowed | Dominio non autorizzato | Sì |
project_archived | Progetto archiviato o sospeso | Sì |
invalid_user_signature | Firma dell'identificativo non valida | No |
websocket_failed | Connessione in tempo reale non stabilita | No |
rate_limited | Troppi messaggi in poco tempo | No |
message_too_long | Messaggio oltre 4000 caratteri | No |
network_error | Errore di rete transitorio | No |
window.BluBot.on('error', function (payload) {
if (payload.fatal) {
document.getElementById('contatti-alternativi')?.classList.remove('nascosto');
}
window.Sentry?.captureMessage('BluBot: ' + payload.code, { level: 'warning' });
});Errori non fatali
Con fatal uguale a false il widget continua a funzionare, eventualmente con
funzionalità ridotte: ad esempio ripiega sul polling se il WebSocket è bloccato.
Inoltro a Google Analytics 4
Con gtag.js
<script>
window.addEventListener('blubot:ready', function () {
var mapping = {
open: 'blubot_open',
close: 'blubot_close',
'message:sent': 'blubot_message_sent',
'message:received': 'blubot_message_received',
'handover:requested': 'blubot_handover_requested',
'handover:started': 'blubot_handover_started'
};
Object.keys(mapping).forEach(function (evt) {
window.BluBot.on(evt, function (payload) {
window.gtag('event', mapping[evt], {
blubot_session_id: payload.sessionId,
blubot_trigger: payload.trigger || payload.reason || 'n_d'
});
});
});
window.BluBot.on('booking:completed', function (payload) {
window.gtag('event', 'generate_lead', {
currency: payload.currency,
value: payload.value,
transaction_id: payload.bookingId
});
});
});
</script>Con Google Tag Manager
Pubblica gli eventi sul dataLayer
Crea un tag HTML personalizzato con attivatore Initialization — All Pages.
<script>
window.dataLayer = window.dataLayer || [];
window.addEventListener('blubot:ready', function () {
['open', 'close', 'message:sent', 'handover:requested', 'booking:completed'].forEach(
function (evt) {
window.BluBot.on(evt, function (payload) {
window.dataLayer.push({
event: 'blubot_' + evt.replace(':', '_'),
blubot_session_id: payload.sessionId || null,
blubot_value: payload.value || null,
blubot_currency: payload.currency || null,
blubot_reason: payload.reason || payload.trigger || null
});
});
}
);
});
</script>Crea le variabili del dataLayer
Crea una variabile di tipo Variabile livello dati per ciascuna chiave:
blubot_session_id, blubot_value, blubot_currency, blubot_reason.
Crea gli attivatori
Attivatore di tipo Evento personalizzato per ogni nome, ad esempio
blubot_booking_completed.
Collega il tag GA4
Crea un tag GA4 — Evento che usa gli attivatori e passa le variabili come parametri dell'evento.
Verifica e pubblica
Usa Anteprima, esegui una conversazione di prova e controlla il DebugView di GA4. Poi pubblica il contenitore.
Non inviare il testo dei messaggi
Inoltrare payload.text a Google Analytics costituisce un trasferimento di dati
personali non necessario e viola le condizioni d'uso del servizio.
Invia solo identificativi e metriche aggregate. Vedi
Conformità.
Eventi come CustomEvent
Ogni evento è disponibile anche su window con prefisso blubot: e payload
in event.detail. Questa forma funziona anche prima che il widget sia pronto.
window.BluBot.on('booking:completed', function (payload) { /* ... */ });
window.addEventListener('blubot:booking:completed', function (event) {
var payload = event.detail;
});Passi successivi
- API JavaScript — metodi per controllare il widget.
- Webhook — gli stessi fatti, notificati al tuo server.
- Risoluzione dei problemi — cosa fare quando arriva un evento
error.