Contrôlez le widget depuis votre page et gardez chaque conversation résiliente — reconnexion automatique, réessai de message, détection hors ligne, délais d'attente et gestion des erreurs conviviales.
Une fois que le script du widget est chargé, Companin enregistre un pont hôte à window.CompaninWidgetHost. Il donne à votre page une petite API sans dépendance pour ouvrir et fermer le widget, envoyer des messages, lire l'état et s'abonner aux événements de cycle de vie — sans coupler votre code aux internals du widget.
Le pont ajoute également une couche de fiabilité au-dessus du widget : les messages sont mis en file d'attente pendant qu'ils sont hors ligne, réessayés automatiquement lorsque la connexion revient, expirés si aucune réponse n'arrive, et le widget se reconnecte automatiquement après des erreurs transitoires. Chaque changement d'état est exposé comme un événement DOM afin que vous puissiez réagir dans votre propre interface utilisateur.
Appelez ces méthodes sur window.CompaninWidgetHost après que le widget a été chargé. Elles sont des no-ops sûrs lorsque le widget n'est pas encore prêt, donc vous n'avez jamais besoin de protéger chaque appel.
open() / close() / toggle() — Afficher, cacher ou retourner le panneau du widget.sendText(text) — Envoyer un message en texte brut en tant que visiteur.sendPayload(payload) — Envoyer un message structuré ou un objet de commande.sendSafe(payload) — Envoyer à travers la couche de fiabilité — mis en file d'attente lorsqu'il est hors ligne et passé à travers les intercepteurs.sendWithTimeout(payload, ms) — Envoyer et émettre un événement de délai d'attente si aucune réponse n'arrive dans ms (par défaut 10000).intercept(fn) — Enregistrer une fonction qui peut réécrire ou annuler les messages sortants ; renvoie une fonction de désinscription.getState() — Lire l'état actuel de l'hôte : statut ouvert, dernier message envoyé et reçu, indicateur en ligne et historique des commandes.getIsOnline() — Que l'hôte considère actuellement la connexion en ligne.drainRetryQueue() — Vider manuellement tous les messages mis en file d'attente pendant qu'ils sont hors ligne.cleanup() — Se désinscrire de chaque écouteur — appelez avant de retirer le 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>Laissez le widget reconnaître vos utilisateurs connectés afin que les conversations soient personnalisées et restaurées sur leurs appareils. Votre serveur signe un jeton à courte durée de vie que le widget remet à Companin ; Companin le vérifie et lie la session à cet utilisateur.
1. Obtenez votre secret de signature. Dans le tableau de bord, ouvrez Installer → Utilisateurs connectés → Générer un secret, puis copiez-le dans l'environnement de votre serveur. Ne l'exposez jamais dans le code du navigateur.
2. Signez un jeton sur votre serveur — un JWT HS256 à courte durée de vie portant l'identifiant de l'utilisateur (sub), l'email et le nom :
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. Remettez le jeton au widget. Sur une page rendue par le serveur, ajoutez-le à la balise script en tant que data-user-token ; dans une application à page unique, appelez identify() après que l'utilisateur se soit connecté :
<!-- 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 jeton invalide ou expiré est ignoré — le widget reste simplement anonyme, donc il est sûr de toujours tenter l'identification.
Utilisez sendSafe au lieu de sendText lorsque la livraison compte. L'hôte surveille les événements en ligne et hors ligne du navigateur ; lorsqu'il est hors ligne, les messages sont ajoutés à une file d'attente de réessai et un événement companin:widget:offline se déclenche. Dès que la connexion revient, la file d'attente est vidée automatiquement dans l'ordre et un événement companin:widget:online se déclenche.
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.');});Enveloppez un envoi dans sendWithTimeout pour vous protéger contre une réponse qui n'arrive jamais. Si aucune réponse n'est reçue dans le délai d'attente (10 secondes par défaut), un événement companin:widget:timeout se déclenche afin que vous puissiez afficher une invite de réessai conviviale au lieu de laisser l'utilisateur attendre.
window.CompaninWidgetHost.sendWithTimeout('Are you there?', 8000);window.addEventListener('companin:widget:timeout', function () { showRetryPrompt('That took longer than expected. Try again?');});Lorsque le widget signale une erreur, l'hôte tente de se reconnecter jusqu'à trois fois avec un temps d'attente croissant (1,5 s, 3 s, puis 4,5 s), émettant companin:widget:reconnecting à chaque tentative. Une réponse réussie réinitialise le compteur ; si toutes les tentatives échouent, companin:widget:reconnectFailed se déclenche afin que vous puissiez revenir en arrière de manière élégante.
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.');});Enregistrez un intercepteur avec intercept(fn) pour inspecter, réécrire ou annuler chaque message sortant. Retournez une charge utile modifiée pour la changer, retournez false pour annuler l'envoi, ou ne retournez rien pour laisser passer sans changement. intercept renvoie une fonction de désinscription.
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'hôte réémet chaque changement de cycle de vie du widget en tant qu'événement DOM CustomEvent sur window, afin que vous puissiez réagir sans tenir une référence au widget. Les données pertinentes sont sur event.detail.
companin:widget:open / close — Le panneau du widget a été ouvert ou fermé.companin:widget:message / response — Le visiteur a envoyé un message, ou l'agent a répondu.companin:widget:authFailure — L'authentification avec le backend a échoué.companin:widget:error — Le widget a signalé une erreur.companin:widget:offline / online — Le navigateur a perdu ou retrouvé sa connexion.companin:widget:queued / retryDrained — Un message a été mis en file d'attente pendant qu'il était hors ligne, ou la file d'attente a été vidée.companin:widget:reconnecting / reconnectFailed — Une tentative de reconnexion automatique a commencé, ou toutes les tentatives ont été épuisées.companin:widget:timeout — Un message n'a pas reçu de réponse dans son délai d'attente.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);});Un code découplé peut piloter le widget en émettant un événement companin:widget:command au lieu d'appeler directement l'API. Envoyez une chaîne pour délivrer un message, ou un objet de détail tel que { action: 'open' } ou { text: 'Hello' }. C'est pratique pour les balises d'analyse, GTM ou d'autres scripts qui ne devraient pas importer le 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' }}));Définissez window.__COMPANIN_WIDGET_WEBHOOK_URL sur un point de collecte et l'hôte transfère les événements d'ouverture, de fermeture, de message et de réponse à celui-ci sous forme de JSON via navigator.sendBeacon (retombant sur un fetch keepalive). C'est un complément léger côté client aux webhooks côté serveur — utile pour l'analyse de première partie.
// Point the host at your collector before the widget loads.window.__COMPANIN_WIDGET_WEBHOOK_URL = 'https://example.com/collect/widget';