Zarządzaj widgetem z twojej strony i utrzymuj każdą rozmowę odporną — automatyczne ponowne połączenie, ponowne wysyłanie wiadomości, wykrywanie offline, limity czasowe i przyjazne obsługi błędów.
Gdy skrypt widgetu się załadowuje, Companin rejestruje most hosta w window.CompaninWidgetHost. Daje twojej stronie małe, niezależne API do otwierania i zamykania widgetu, wysyłania wiadomości, odczytywania stanu i subskrybowania zdarzeń cyklu życia — bez łączenia twojego kodu z wewnętrznymi elementami widgetu.
Most dodaje również warstwę niezawodności na szczycie widgetu: wiadomości są kolejkowane podczas braku połączenia, automatycznie ponownie wysyłane, gdy połączenie wraca, czas oczekiwania, jeśli nie przychodzi odpowiedź, a widget automatycznie ponownie łączy się po błędach przejściowych. Każda zmiana stanu jest ujawniana jako zdarzenie DOM, abyś mógł zareagować w swoim własnym interfejsie użytkownika.
Wywołaj te metody na window.CompaninWidgetHost po załadowaniu widgetu. Są one bezpiecznymi no-opami, gdy widget nie jest jeszcze gotowy, więc nigdy nie musisz chronić każdego wywołania.
open() / close() / toggle() — Pokaż, ukryj lub obróć panel widgetu.sendText(text) — Wyślij wiadomość w formacie tekstowym jako odwiedzający.sendPayload(payload) — Wyślij zorganizowaną wiadomość lub obiekt polecenia.sendSafe(payload) — Wyślij przez warstwę niezawodności — kolejkowane, gdy offline i przekazywane przez wszelkie przechwytywacze.sendWithTimeout(payload, ms) — Wyślij i emituj zdarzenie limitu czasowego, jeśli nie przychodzi odpowiedź w ciągu ms (domyślnie 10000).intercept(fn) — Zarejestruj funkcję, która może przepisać lub anulować wychodzące wiadomości; zwraca funkcję anulującą subskrypcję.getState() — Odczytaj aktualny stan hosta: status otwarcia, ostatnia wysłana i odebrana wiadomość, flaga online i historia poleceń.getIsOnline() — Czy host obecnie uważa połączenie za online.drainRetryQueue() — Ręcznie opróżnij wszelkie wiadomości kolejkowane podczas braku połączenia.cleanup() — Anuluj subskrypcję każdego słuchacza — wywołaj przed usunięciem widgetu.<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>Pozwól widgetowi rozpoznać twoich zalogowanych użytkowników, aby rozmowy były spersonalizowane i przywracane na ich urządzeniach. Twój serwer podpisuje krótkożyjący token, który widget przekazuje do Companin; Companin weryfikuje go i łączy sesję z tym użytkownikiem.
1. Uzyskaj swój sekret podpisu. W panelu otwórz Instalacja → Zalogowani użytkownicy → Generuj sekret, a następnie skopiuj go do środowiska swojego serwera. Nigdy nie ujawniaj go w kodzie przeglądarki.
2. Podpisz token na swoim serwerze — krótkożyjący HS256 JWT zawierający id użytkownika (sub), e-mail i imię:
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. Przekaż token do widgetu. Na stronie renderowanej przez serwer dodaj go do tagu skryptu jako data-user-token; w aplikacji jednostronicowej wywołaj identify() po zalogowaniu użytkownika:
<!-- 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>Zły lub wygasły token jest ignorowany — widget po prostu pozostaje anonimowy, więc zawsze jest bezpiecznie próbować identyfikacji.
Użyj sendSafe zamiast sendText, gdy dostarczenie ma znaczenie. Host obserwuje zdarzenia online i offline przeglądarki; podczas braku połączenia wiadomości są dodawane do kolejki ponownego wysyłania, a zdarzenie companin:widget:offline jest wywoływane. Gdy tylko połączenie wraca, kolejka jest automatycznie opróżniana w kolejności, a zdarzenie companin:widget:online jest wywoływane.
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.');});Owiń wysyłanie w sendWithTimeout, aby chronić przed odpowiedzią, która nigdy nie przychodzi. Jeśli nie otrzymasz odpowiedzi w ciągu limitu czasowego (10 sekund domyślnie), wywoływane jest zdarzenie companin:widget:timeout, abyś mógł pokazać przyjazny komunikat o ponownym próbie zamiast zostawiać użytkownika w oczekiwaniu.
window.CompaninWidgetHost.sendWithTimeout('Are you there?', 8000);window.addEventListener('companin:widget:timeout', function () { showRetryPrompt('That took longer than expected. Try again?');});Gdy widget zgłasza błąd, host próbuje ponownie połączyć się do trzech razy z rosnącym opóźnieniem (1,5 s, 3 s, a następnie 4,5 s), emitując companin:widget:reconnecting przy każdej próbie. Udana odpowiedź resetuje licznik; jeśli wszystkie próby się nie powiodą, wywoływane jest companin:widget:reconnectFailed, abyś mógł wrócić do normy.
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.');});Zarejestruj przechwytywacz za pomocą intercept(fn), aby sprawdzić, przepisać lub anulować każdą wychodzącą wiadomość. Zwróć zmodyfikowany ładunek, aby go zmienić, zwróć false, aby anulować wysyłanie, lub nie zwracaj niczego, aby go przepuścić bez zmian. intercept zwraca funkcję anulującą subskrypcję.
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();Host ponownie emituje każdą zmianę cyklu życia widgetu jako zdarzenie DOM CustomEvent w oknie, abyś mógł zareagować bez trzymania odniesienia do widgetu. Odpowiednie dane znajdują się w event.detail.
companin:widget:open / close — Panel widgetu został otwarty lub zamknięty.companin:widget:message / response — Odwiedzający wysłał wiadomość lub agent odpowiedział.companin:widget:authFailure — Uwierzytelnienie z backendem nie powiodło się.companin:widget:error — Widget zgłosił błąd.companin:widget:offline / online — Przeglądarka straciła lub odzyskała połączenie.companin:widget:queued / retryDrained — Wiadomość została kolejkowana podczas braku połączenia lub kolejka została opróżniona.companin:widget:reconnecting / reconnectFailed — Rozpoczęła się próba automatycznego ponownego połączenia lub wszystkie próby zostały wyczerpane.companin:widget:timeout — Wiadomość nie otrzymała odpowiedzi w ciągu limitu czasowego.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);});Odłączony kod może sterować widgetem, wywołując zdarzenie companin:widget:command zamiast bezpośredniego wywoływania API. Wyślij ciąg, aby dostarczyć wiadomość, lub obiekt szczegółowy, taki jak { action: 'open' } lub { text: 'Hello' }. To jest przydatne dla tagów analitycznych, GTM lub innych skryptów, które nie powinny importować widgetu.
// 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' }}));Ustaw window.__COMPANIN_WIDGET_WEBHOOK_URL na punkt końcowy kolektora, a host przekazuje zdarzenia otwarcia, zamknięcia, wiadomości i odpowiedzi do niego jako JSON za pomocą navigator.sendBeacon (przechodząc do fetch keepalive). To jest lekkie, klienckie uzupełnienie dla serwerowych webhooków — przydatne dla analityki pierwszej strony.
// Point the host at your collector before the widget loads.window.__COMPANIN_WIDGET_WEBHOOK_URL = 'https://example.com/collect/widget';