Controlla il widget dalla tua pagina e mantieni ogni conversazione resiliente — riconnessione automatica, ripetizione dei messaggi, rilevamento offline, timeout e gestione degli errori amichevole.
Una volta che lo script del widget è caricato, Companin registra un bridge host su window.CompaninWidgetHost. Fornisce alla tua pagina una piccola API senza dipendenze per aprire e chiudere il widget, inviare messaggi, leggere lo stato e iscriversi agli eventi del ciclo di vita — senza accoppiare il tuo codice agli interni del widget.
Il bridge aggiunge anche uno strato di affidabilità sopra il widget: i messaggi vengono messi in coda mentre sono offline, ripetuti automaticamente quando la connessione ritorna, scaduti se non arriva risposta, e il widget si riconnette automaticamente dopo errori transitori. Ogni cambiamento di stato viene visualizzato come un evento DOM in modo da poter reagire nella tua UI.
Chiama questi metodi su window.CompaninWidgetHost dopo che il widget è stato caricato. Sono operazioni sicure quando il widget non è ancora pronto, quindi non è necessario proteggere ogni chiamata.
open() / close() / toggle() — Mostra, nascondi o capovolgi il pannello del widget.sendText(text) — Invia un messaggio in testo semplice come visitatore.sendPayload(payload) — Invia un messaggio strutturato o un oggetto comando.sendSafe(payload) — Invia attraverso lo strato di affidabilità — messo in coda quando offline e passato attraverso eventuali intercettatori.sendWithTimeout(payload, ms) — Invia ed emetti un evento di timeout se non arriva risposta entro ms (default 10000).intercept(fn) — Registra una funzione che può riscrivere o annullare messaggi in uscita; restituisce una funzione di disiscrizione.getState() — Leggi lo stato attuale dell'host: stato aperto, ultimo messaggio inviato e ricevuto, flag online e cronologia comandi.getIsOnline() — Se l'host considera attualmente la connessione online.drainRetryQueue() — Svuota manualmente eventuali messaggi messi in coda mentre offline.cleanup() — Disiscrivi ogni listener — chiama prima di rimuovere il widget.<script> window.addEventListener('load', function () { var host = window.CompaninWidgetHost; if (!host) return; host.open(); host.sendText('Hi! I have a question about pricing.'); console.log(host.getState()); });</script>Fai riconoscere il widget dai tuoi utenti connessi in modo che le conversazioni siano personalizzate e ripristinate sui loro dispositivi. Il tuo server firma un token a breve termine che il widget consegna a Companin; Companin lo verifica e collega la sessione a quell'utente.
1. Ottieni il tuo segreto di firma. Nel dashboard, apri Installazione → Utenti connessi → Genera segreto, quindi copialo nell'ambiente del tuo server. Non esporlo mai nel codice del browser.
2. Firma un token sul tuo server — un JWT HS256 a breve termine contenente l'id dell'utente (sub), email e nome:
const jwt = require('jsonwebtoken'); // npm i jsonwebtokenfunction signUserToken(user) { return jwt.sign( { sub: String(user.id), email: user.email, name: user.name }, process.env.COMPANIN_EMBED_SECRET, { algorithm: 'HS256', expiresIn: '5m' } );}3. Passa il token al widget. Su una pagina renderizzata dal server, aggiungilo al tag script come data-user-token; in un'app a pagina singola, chiama identify() dopo che l'utente ha effettuato l'accesso:
<!-- Option A: server-rendered page — put the signed token on the script tag --><script src="https://YOUR_WIDGET_HOST/widget.js" data-widget-key="wgt_your_key" data-user-token="SERVER_SIGNED_JWT"></script><!-- Option B: after login — fetch a fresh token and call identify() --><script> fetch('/api/widget-user-token') .then(function (r) { return r.json(); }) .then(function (data) { if (data.token) window.CompaninWidget.identify({ token: data.token }); });</script>Un token errato o scaduto viene ignorato — il widget rimane semplicemente anonimo, quindi è sicuro tentare sempre l'identificazione.
Usa sendSafe invece di sendText quando la consegna è importante. L'host osserva gli eventi online e offline del browser; mentre è offline, i messaggi vengono aggiunti a una coda di ripetizione e viene attivato un evento companin:widget:offline. Non appena la connessione ritorna, la coda viene svuotata automaticamente in ordine e viene attivato un evento companin:widget:online.
window.CompaninWidgetHost.sendSafe('Track my order #1234');window.addEventListener('companin:widget:offline', function () { showBanner('You are offline — your message will send automatically.');});window.addEventListener('companin:widget:online', function () { showBanner('Back online.');});window.addEventListener('companin:widget:retryDrained', function (e) { showBanner(e.detail.count + ' queued message(s) sent.');});Avvolgi un invio in sendWithTimeout per proteggerti da una risposta che non arriva mai. Se non viene ricevuta alcuna risposta entro il timeout (10 secondi di default), si attiva un evento companin:widget:timeout in modo da poter mostrare un messaggio di ripetizione amichevole invece di lasciare l'utente in attesa.
window.CompaninWidgetHost.sendWithTimeout('Are you there?', 8000);window.addEventListener('companin:widget:timeout', function () { showRetryPrompt('That took longer than expected. Try again?');});Quando il widget riporta un errore, l'host tenta di riconnettersi fino a tre volte con un aumento del back-off (1.5s, 3s, poi 4.5s), emettendo companin:widget:reconnecting ad ogni tentativo. Una risposta riuscita ripristina il contatore; se tutti i tentativi falliscono, si attiva companin:widget:reconnectFailed in modo da poter tornare indietro in modo elegante.
window.addEventListener('companin:widget:reconnecting', function (e) { console.log('Reconnecting — attempt', e.detail.attempt, 'in', e.detail.delay, 'ms');});window.addEventListener('companin:widget:reconnectFailed', function () { showBanner('We could not reconnect. Please refresh the page.');});Registra un intercettatore con intercept(fn) per ispezionare, riscrivere o annullare ogni messaggio in uscita. Restituisci un payload modificato per cambiarlo, restituisci false per annullare l'invio, o non restituire nulla per lasciarlo passare invariato. intercept restituisce una funzione di disiscrizione.
const stop = window.CompaninWidgetHost.intercept(function (payload) { if (typeof payload === 'string') { if (!payload.trim()) return false; // cancel the send return payload.replace(/[\w.+-]+@[\w-]+\.[\w.-]+/g, '[email]'); } return payload;});// Later, to remove the interceptor:stop();L'host riemette ogni cambiamento del ciclo di vita del widget come un DOM CustomEvent su window, così puoi reagire senza mantenere un riferimento al widget. I dati rilevanti sono su event.detail.
companin:widget:open / close — Il pannello del widget è stato aperto o chiuso.companin:widget:message / response — Il visitatore ha inviato un messaggio, o l'agente ha risposto.companin:widget:authFailure — L'autenticazione con il backend è fallita.companin:widget:error — Il widget ha segnalato un errore.companin:widget:offline / online — Il browser ha perso o ripristinato la sua connessione.companin:widget:queued / retryDrained — Un messaggio è stato messo in coda mentre era offline, o la coda è stata svuotata.companin:widget:reconnecting / reconnectFailed — Un tentativo di riconnessione automatica è iniziato, o tutti i tentativi sono stati esauriti.companin:widget:timeout — Un messaggio non ha ricevuto una risposta entro il suo timeout.window.addEventListener('companin:widget:message', function (e) { console.log('Visitor sent:', e.detail.message);});window.addEventListener('companin:widget:response', function (e) { console.log('Agent replied:', e.detail.response);});window.addEventListener('companin:widget:authFailure', function (e) { console.warn('Widget auth failed:', e.detail.error);});Il codice decoupled può guidare il widget emettendo un evento companin:widget:command invece di chiamare direttamente l'API. Invia una stringa per consegnare un messaggio, o un oggetto di dettaglio come { action: 'open' } o { text: 'Hello' }. Questo è utile per tag di analisi, GTM o altri script che non dovrebbero importare il widget.
// Open the widget from anywhere — no widget reference needed.window.dispatchEvent(new CustomEvent('companin:widget:command', { detail: { action: 'open' }}));// Or send a message.window.dispatchEvent(new CustomEvent('companin:widget:command', { detail: { text: 'I need help with billing' }}));Imposta window.__COMPANIN_WIDGET_WEBHOOK_URL su un endpoint di raccolta e l'host inoltra eventi di apertura, chiusura, messaggio e risposta a esso come JSON tramite navigator.sendBeacon (ritornando a un fetch di keepalive). Questo è un complemento leggero, lato client, ai webhook lato server — utile per analisi di prima parte.
// Point the host at your collector before the widget loads.window.__COMPANIN_WIDGET_WEBHOOK_URL = 'https://example.com/collect/widget';