Stuur de widget vanaf jouw pagina en houd elk gesprek veerkrachtig — automatische reconnect, berichtretry, offline detectie, time-outs en vriendelijke foutafhandeling.
Zodra het widget-script is geladen, registreert Companin een hostbrug bij window.CompaninWidgetHost. Het geeft jouw pagina een kleine, afhankelijkheidsvrije API om de widget te openen en te sluiten, berichten te verzenden, status te lezen, en je aan te melden voor levenscycusevenementen — zonder je code aan de interne werking van de widget te koppelen.
De brug voegt ook een betrouwbaarheidslaag bovenop de widget toe: berichten worden in de wachtrij geplaatst terwijl ze offline zijn, automatisch opnieuw geprobeerd wanneer de verbinding terugkomt, tijdslimieten als er geen antwoord arriveert, en de widget maakt automatisch opnieuw verbinding na tijdelijke fouten. Elke statuswijziging wordt weergegeven als een DOM-evenement zodat je kunt reageren in jouw eigen UI.
Roep deze methoden aan op window.CompaninWidgetHost nadat de widget is geladen. Ze zijn veilige no-ops wanneer de widget nog niet klaar is, zodat je nooit elke oproep hoeft te beveiligen.
open() / close() / toggle() — Toon, verberg of draai het widgetpaneel.sendText(text) — Stuur een platte tekstbericht als de bezoeker.sendPayload(payload) — Stuur een gestructureerd bericht of commando-object.sendSafe(payload) — Verzend via de betrouwbaarheidslaag — in de wachtrij geplaatst wanneer offline en doorgegeven via interceptors.sendWithTimeout(payload, ms) — Verzend en geef een time-out-evenement af als er binnen ms (standaard 10000) geen antwoord arriveert.intercept(fn) — Registreer een functie die uitgaande berichten kan herschrijven of annuleren; retourneert een afmeldfunctie.getState() — Lees de huidige hoststatus: open status, laatst verzonden en ontvangen bericht, online vlag en commando geschiedenis.getIsOnline() — Of de host de verbinding momenteel als online beschouwt.drainRetryQueue() — Handmatig alle berichten flushen die in de wachtrij stonden terwijl ze offline waren.cleanup() — Annuleer elke luisteraar — roep aan voordat je de widget verwijdert.<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>Laat de widget jouw ingelogde gebruikers herkennen zodat gesprekken gepersonaliseerd zijn en over hun apparaten worden hersteld. Jouw server ondertekent een kortlevende token die de widget aan Companin overhandigt; Companin verifieert het en koppelt de sessie aan die gebruiker.
1. Verkrijg jouw ondertekeningsgeheim. Open in het dashboard Installeren → Ingelogde gebruikers → Genereer geheim, en kopieer het dan in de omgeving van jouw server. Stel het nooit bloot in browsercode.
2. Onderteken een token op jouw server — een kortlevende HS256 JWT met het id (sub), e-mailadres en naam van de gebruiker:
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. Geef het token aan de widget. Op een server-gerenderde pagina, voeg het toe aan de script-tag als data-user-token; in een single-page app, roep identify() aan nadat de gebruiker inlogt:
<!-- 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>Een slecht of verlopen token wordt genegeerd — de widget blijft gewoon anoniem, dus het is veilig om altijd identificatie te proberen.
Gebruik sendSafe in plaats van sendText wanneer levering belangrijk is. De host houdt de online en offline evenementen van de browser in de gaten; terwijl offline worden berichten aan een retry-wachtrij toegevoegd en wordt een companin:widget:offline-evenement afgevuurd. Zodra de verbinding terugkomt, wordt de wachtrij automatisch in volgorde geleegd en wordt companin:widget:online afgevuurd.
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.');});Wikkel een verzendopdracht in sendWithTimeout om te beschermen tegen een antwoord dat nooit arriveert. Als er binnen de time-out (10 seconden standaard) geen antwoord wordt ontvangen, wordt een companin:widget:timeout-evenement afgevuurd zodat je een vriendelijke retry-prompt kunt tonen in plaats van de gebruiker te laten wachten.
window.CompaninWidgetHost.sendWithTimeout('Are you there?', 8000);window.addEventListener('companin:widget:timeout', function () { showRetryPrompt('That took longer than expected. Try again?');});Wanneer de widget een fout meldt, probeert de host tot drie keer opnieuw verbinding te maken met een toenemende back-off (1,5s, 3s, dan 4,5s), waarbij bij elke poging companin:widget:reconnecting wordt afgegeven. Een succesvolle reactie reset de teller; als alle pogingen mislukken, wordt companin:widget:reconnectFailed afgevuurd zodat je elegant kunt terugvallen.
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.');});Registreer een interceptor met intercept(fn) om elk uitgaand bericht te inspecteren, herschrijven of annuleren. Geef een aangepast payload terug om het te wijzigen, geef false terug om de verzending te annuleren, of geef niets terug om het onveranderd door te laten. intercept retourneert een afmeldfunctie.
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();De host heruitzendt elke wijziging in de levenscyclus van de widget als een DOM CustomEvent op window, zodat je kunt reageren zonder een referentie naar de widget vast te houden. De relevante gegevens bevinden zich op event.detail.
companin:widget:open / close — Het widgetpaneel is geopend of gesloten.companin:widget:message / response — De bezoeker heeft een bericht verzonden, of de agent heeft gereageerd.companin:widget:authFailure — Authenticatie met de backend is mislukt.companin:widget:error — De widget heeft een fout gerapporteerd.companin:widget:offline / online — De browser heeft zijn verbinding verloren of hersteld.companin:widget:queued / retryDrained — Een bericht is in de wachtrij geplaatst terwijl het offline was, of de wachtrij is geleegd.companin:widget:reconnecting / reconnectFailed — Een automatische reconnectpoging is gestart, of alle pogingen zijn uitgeput.companin:widget:timeout — Een bericht heeft binnen zijn time-out geen antwoord ontvangen.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);});Ontkoppelde code kan de widget aansteken door een companin:widget:command-evenement te verzenden in plaats van de API direct aan te roepen. Stuur een string om een bericht te leveren, of een detailobject zoals { action: 'open' } of { text: 'Hallo' }. Dit is handig voor analysetags, GTM of andere scripts die de widget niet moeten importeren.
// 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' }}));Stel window.__COMPANIN_WIDGET_WEBHOOK_URL in op een verzamelendpoint en de host stuurt open-, sluit-, bericht- en reactie-evenementen als JSON via navigator.sendBeacon (terugvallend op een keepalive fetch). Dit is een lichte, client-side aanvulling op server-side webhooks — nuttig voor first-party analytics.
// Point the host at your collector before the widget loads.window.__COMPANIN_WIDGET_WEBHOOK_URL = 'https://example.com/collect/widget';