Mengendalikan widget dari halaman Anda dan menjaga setiap percakapan tetap tangguh — sambungan otomatis, percobaan pesan, deteksi offline, waktu tunggu, dan penanganan kesalahan yang ramah.
Setelah skrip widget dimuat, Companin mendaftarkan jembatan host di window.CompaninWidgetHost. Ini memberi halaman Anda API kecil yang bebas ketergantungan untuk membuka dan menutup widget, mengirim pesan, membaca status, dan berlangganan acara siklus hidup — tanpa mengaitkan kode Anda dengan internal widget.
Jembatan ini juga menambahkan lapisan keandalan di atas widget: pesan-pesan di antrean saat offline, dicoba kembali secara otomatis saat koneksi kembali, waktu habis jika tidak ada respons yang tiba, dan widget menyambung kembali secara otomatis setelah kesalahan sementara. Setiap perubahan status ditampilkan sebagai acara DOM sehingga Anda dapat bereaksi di UI Anda sendiri.
Panggil metode ini di window.CompaninWidgetHost setelah widget dimuat. Mereka adalah no-op yang aman ketika widget belum siap, jadi Anda tidak perlu melindungi setiap panggilan.
open() / close() / toggle() — Tampilkan, sembunyikan, atau balik panel widget.sendText(text) — Kirim pesan teks biasa sebagai pengunjung.sendPayload(payload) — Kirim pesan terstruktur atau objek perintah.sendSafe(payload) — Kirim melalui lapisan keandalan — antrean saat offline dan diteruskan melalui intersepsi apa pun.sendWithTimeout(payload, ms) — Kirim dan keluarkan acara waktu habis jika tidak ada respons yang tiba dalam ms (default 10000).intercept(fn) — Daftarkan fungsi yang dapat menulis ulang atau membatalkan pesan yang keluar; mengembalikan fungsi pembatalan.getState() — Baca status host saat ini: status terbuka, pesan terakhir yang dikirim dan diterima, bendera online, dan riwayat perintah.getIsOnline() — Apakah host saat ini menganggap koneksi online.drainRetryQueue() — Flush secara manual pesan apa pun yang di antrean saat offline.cleanup() — Batalkan langganan setiap pendengar — panggil sebelum menghapus 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>Biarkan widget mengenali pengguna yang masuk sehingga percakapan dipersonalisasi dan dipulihkan di seluruh perangkat mereka. Server Anda menandatangani token jangka pendek yang diserahkan widget kepada Companin; Companin memverifikasinya dan menghubungkan sesi tersebut dengan pengguna tersebut.
1. Dapatkan rahasia penandatanganan Anda. Di dasbor, buka Instal 🔗; Pengguna yang masuk 🔗; Hasilkan rahasia, lalu salin ke lingkungan server Anda. Jangan pernah mengeksposnya dalam kode browser.
2. Tandatangani token di server Anda — JWT HS256 jangka pendek yang membawa id pengguna (sub), email, dan nama:
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. Serahkan token kepada widget. Di halaman yang dirender di server, tambahkan ke tag skrip sebagai data-user-token; dalam aplikasi satu halaman, panggil identify() setelah pengguna masuk:
<!-- 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>Token yang buruk atau kedaluwarsa diabaikan — widget tetap anonim, jadi aman untuk selalu mencoba identifikasi.
Gunakan sendSafe alih-alih sendText saat pengiriman penting. Host memantau acara online dan offline browser; saat offline, pesan ditambahkan ke antrean percobaan dan acara companin:widget:offline dipicu. Begitu koneksi kembali, antrean dikuras secara otomatis dalam urutan dan companin:widget:online dipicu.
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.');});Bungkus pengiriman dalam sendWithTimeout untuk melindungi dari respons yang tidak pernah tiba. Jika tidak ada balasan yang diterima dalam waktu habis (10 detik secara default), acara companin:widget:timeout dipicu sehingga Anda dapat menunjukkan prompt percobaan yang ramah daripada membiarkan pengguna menunggu.
window.CompaninWidgetHost.sendWithTimeout('Are you there?', 8000);window.addEventListener('companin:widget:timeout', function () { showRetryPrompt('That took longer than expected. Try again?');});Ketika widget melaporkan kesalahan, host mencoba menyambung kembali hingga tiga kali dengan penundaan yang meningkat (1,5 detik, 3 detik, lalu 4,5 detik), memancarkan companin:widget:reconnecting pada setiap percobaan. Respons yang berhasil mengatur ulang penghitung; jika semua percobaan gagal, companin:widget:reconnectFailed dipicu sehingga Anda dapat kembali dengan baik.
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.');});Daftarkan intersepsi dengan intercept(fn) untuk memeriksa, menulis ulang, atau membatalkan setiap pesan keluar. Kembalikan payload yang dimodifikasi untuk mengubahnya, kembalikan false untuk membatalkan pengiriman, atau kembalikan tidak ada untuk membiarkannya lewat tanpa perubahan. intercept mengembalikan fungsi pembatalan.
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 memancarkan setiap perubahan siklus hidup widget sebagai DOM CustomEvent di window, sehingga Anda dapat bereaksi tanpa memegang referensi ke widget. Data yang relevan ada di event.detail.
companin:widget:open / close — Panel widget dibuka atau ditutup.companin:widget:message / response — Pengunjung mengirim pesan, atau agen merespons.companin:widget:authFailure — Autentikasi dengan backend gagal.companin:widget:error — Widget melaporkan kesalahan.companin:widget:offline / online — Browser kehilangan atau mendapatkan kembali koneksinya.companin:widget:queued / retryDrained — Pesan di antrean saat offline, atau antrean dikosongkan.companin:widget:reconnecting / reconnectFailed — Percobaan sambungan otomatis dimulai, atau semua percobaan telah habis.companin:widget:timeout — Pesan tidak menerima respons dalam waktu habisnya.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);});Kode yang terpisah dapat mengendalikan widget dengan memicu acara companin:widget:command alih-alih memanggil API secara langsung. Kirim string untuk mengirim pesan, atau objek detail seperti { action: 'open' } atau { text: 'Hello' }. Ini berguna untuk tag analitik, GTM, atau skrip lain yang tidak boleh mengimpor 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' }}));Set window.__COMPANIN_WIDGET_WEBHOOK_URL ke endpoint pengumpul dan host meneruskan acara buka, tutup, pesan, dan respons ke sana sebagai JSON melalui navigator.sendBeacon (kembali ke pengambilan keepalive). Ini adalah pelengkap ringan, sisi klien untuk webhook sisi server — berguna untuk analitik pihak pertama.
// Point the host at your collector before the widget loads.window.__COMPANIN_WIDGET_WEBHOOK_URL = 'https://example.com/collect/widget';