signalbird.io/sdk/v1 ↗
Kurulum<script async src="https://signalbird.io/sdk/v1/signalbird.js" data-key="sb_public_live_…" data-channel="destek"></script>

Web Widget - Canlı sohbet (signalbird.js)

Sitenize tek satırla eklenen canlı sohbet balonu. Ziyaretçi yazar, ekibiniz panelde Inbox'tan yanıtlar. Widget ayrıca ziyaretçiyi bir kişiye bağlar (identify) ve web push cihazını kaydeder (push.register), böylece aynı kişi kampanyalarda da hedeflenebilir.

Bağımlılığı yoktur, 40 KB gzip altındadır, Shadow DOM içinde çalışır - sitenizin CSS'i widget'a, widget'ın CSS'i sitenize karışmaz.

Kurulum

html
<script async
  src="https://signalbird.io/sdk/v1/signalbird.js"
  data-app-key="sb_public_live_xxxxxxxxxxxxxxxx"></script>

Bu kadar. Betik yüklenince POST /v1/sdk/bootstrap ile uygulama ayarlarını çeker ve balonu çizer. </body> kapanışından hemen önce ya da <head> içinde async ile eklenebilir; sayfanın yüklenmesini bloklamaz.

Anahtar

Panelde Inbox → Ayarlar → Uygulamalar → Yeni uygulama ile bir uygulama açın; size bir uygulama anahtarı (sb_public_live_…) verilir.

Bu anahtar açıktır - HTML'de durur, herkes görebilir. Güvenliği kısıttan gelir: uygulama ayarlarındaki izinli kökenler (alan adları) dışından gelen istekler 403 ile reddedilir. Yeni bir alan adına (staging, yeni domain) kurarken önce izinli kökenlere ekleyin.

Gizli anahtar (sb_secret_live_…) burada çalışmaz; sb_… gizlidir ve HTML'e asla gömülmez.

Seçenekler

Betik etiketi üzerinden (data-*) ya da Signalbird.init() ile verilir; ikisi aynı alanlardır.

data-* init() alanı Varsayılan Açıklama
data-app-key publicKey - Zorunlu. sb_public_live_ ile başlamalı
data-base-url baseUrl https://signalbird.io/api Kendi kurulumunuz varsa
data-locale locale tarayıcı dili tr ya da en
- user - Sayfa açılışında bilinen kullanıcı (identify ile aynı biçim)
data-external-id user.external_id - Oturumdaki kullanıcının sizin sisteminizdeki kimliği
data-identity-hash identityHash - external_id'nin hash'i - sunucunuzda üretilir (Kimlik doğrulaması)
- debug false Konsola ayrıntı yazar

data-app-key verildiğinde widget kendini kurar; init() çağırmanız gerekmez. Anahtarı çalışma zamanında belirlemek isterseniz data-app-key'i atlayıp Signalbird.init({...}) çağırın.

API

window.Signalbird betik yüklendiğinde hazırdır. Hiçbir metot sayfaya hata fırlatmaz: widget'ın bir sorunu sitenizi bozmaz.

Metot Açıklama
Signalbird.init({ publicKey, baseUrl?, locale?, user?, identityHash?, debug? }) Elle kurulum
Signalbird.identify({ external_id, identityHash?, email?, name?, phone?, attributes? }) Ziyaretçiyi bir kişiye bağlar - girişten sonra çağırın. identityHash olmadan kimlik doğrulanmamış sayılır
Signalbird.chat.open() · close() · toggle() Paneli açar / kapatır
Signalbird.chat.isOpen() boolean
Signalbird.chat.on('unread' | 'open' | 'close', fn) · off(event, fn) Olay dinleyici. unread sayıyla çağrılır
Signalbird.push.register({ token, platform, provider?, external_id? }) Cihazı push kaydına ekler. platform: web · ios · android; provider: fcm · apns · webpush
Signalbird.destroy() Widget'ı DOM'dan söker, zamanlayıcıları durdurur

Kullanıcıyı tanıtmak

Ziyaretçi anonim başlar (localStorage['sb_visitor']). Giriş yaptığında identify çağırın; sohbet geçmişi ve kişi kaydı o kullanıcıya bağlanır, ekibiniz Inbox'ta ismini görür.

html
<script>
  Signalbird.identify({
    external_id: 'user-1042',          // sizin sistemdeki kimlik
    identityHash: '{{ hash }}',        // SUNUCUNUZDA üretilir - aşağıya bakın
    email: 'ahmet@example.com',
    name: 'Ahmet Çil',
    attributes: { plan: 'pro', company: 'Penyu' },
  })
</script>

external_id sizin sisteminizdeki kalıcı kimliktir; e-posta değişse de aynı kişi kalır. Aynı external_id ile Gönderim SDK'sından sendPush({ to: 'external:user-1042' }) çağırabilirsiniz.

Programatik açma

Kendi "Yardım" bağlantınızdan paneli açın:

html
<button onclick="Signalbird.chat.open()">Bize yazın</button>
javascript
Signalbird.chat.on('unread', (count) => {
  document.querySelector('#help-badge').textContent = count > 0 ? String(count) : ''
})

Web push kaydı

Kendi servis çalışanınızla token aldıktan sonra cihazı kaydedin; kişi panelden push kampanyalarında hedeflenebilir olur.

javascript
const token = await getFcmToken()   // sizin FCM / Web Push akışınız
Signalbird.push.register({ token, platform: 'web', provider: 'fcm', external_id: 'user-1042' })

React / Next.js

tsx
'use client'
import Script from 'next/script'

export function SignalbirdWidget({ user }: { user?: { id: string; email: string; name: string } }) {
  return (
    <Script
      src="https://signalbird.io/sdk/v1/signalbird.js"
      data-app-key={process.env.NEXT_PUBLIC_SIGNALBIRD_APP_KEY}
      strategy="afterInteractive"
      onLoad={() => {
        if (user) window.Signalbird?.identify({ external_id: user.id, email: user.email, name: user.name })
      }}
    />
  )
}

useEffect ile de eklenebilir: bir <script> oluşturup document.body'ye takın, load olayında window.Signalbird?.identify(...) çağırın. Bileşen kaldırılırken Signalbird.destroy() çağırmak isteğe bağlıdır; widget tek örnektir ve tekrar init çağrısını yok sayar.

Özellikler

  • Başlatıcı balon + panel; ≤ 640 px genişlikte tam ekran
  • Boş ekran bir form değil, davet: marka avatarı, karşılama cümlesi, yanıt süresi ve destek konularından türeyen hazır başlangıç çipleri. Çipe dokunmak o metni mesaj olarak gönderir - "ne yazacağımı bilmiyorum" en sık terk sebebidir
  • Kendini fark ettiren üç sinyal: ziyaretçi paneli hiç açmadıysa 11 sn sonra bir kez çıkan karşılama kartı; panel kapalıyken gelen yanıtın balonun üstünde beliren önizlemesi; okunmamış varken balonun sessiz nabzı. Üçü de kapatılabilir, kapatma kararı tarayıcıda saklanır
  • Sohbet öncesi form (isim / e-posta - uygulama ayarına göre), karşılama mesajı, çalışma saatleri dışında çevrimdışı şeridi
  • Gün ayraçları, ✓ / ✓✓ okundu bilgisi, iki yönlü yazıyor göstergesi
  • Mesaj gruplama: aynı kişinin 5 dk içindeki ardışık mesajları tek öbek; avatar ve saat yalnız öbeğin sonunda
  • Emoji seçici, uzun mesaj geçmişinde "en alta in" düğmesi, gövdedeki bağlantılar tıklanır
  • Tek mesajda 420 karakter (sunucudan gelir, panelden değişebilir). Son 60 karakterde sayaç belirir, sınır aşılınca gönderilmez. Sınır iki taraf için de geçerlidir: jetonu yakan şey mesajı kimin yazdığı değil, uzunluğu
  • Dosya yükleme: sürükle-bırak, yapıştır; jpeg / png / gif / webp / avif, PDF ve düz metin - üst sınır max_attachment_mb. image/* joker'i bilerek yok: image/svg+xml betik çalıştırabilen bir belgedir, görsel değil. Tür sunucuda dosyanın İÇERİĞİNDEN okunur; uzantıyı değiştirmek işe yaramaz
  • Alıntıyla yanıt, emoji tepkileri, kendi mesajını 15 dk içinde düzenle / sil
  • Okunmamış rozeti + document.title yanıp sönmesi, ses
  • Enter gönderir, Shift+Enter satır atlar
  • tr / en otomatik; kapanışta 1–5 puan
  • Canlı bağlantı (socket.io); bağlantı kurulamazsa yoklamaya düşer (kapalıyken 20 s → 180 s, açıkken 3 s)
  • Ziyaretçi paneli taşır ve boyutlandırır: başlığı sürükle, dış üst köşedeki tutamaktan çek. Seçim tarayıcıda saklanır (localStorage['sb_geometry']); mobilde kapalıdır
  • Mobil: tam ekran (100dvh), çentik ve ev çubuğu boşlukları, klavye açılınca kompozitör klavyenin üstünde kalır, arkadaki sayfa kaymaz, tepedeki tutamağı aşağı sürükleyerek kapanır
  • Açık / koyu tema; koyu için theme ayarı ya da ziyaretçinin tercihi (auto)
  • Sohbet bitince panel sıfırdan başlar - kapanmış yazışma geri açılmaz. Ziyaretçi sohbeti bitirdiyse temsilci o konuşmaya yazamaz: kapanan kapı iki taraf için de kapalıdır
  • Shadow DOM izolasyonu, marka rengi / logo / konum panelden

Panel ayarları

Kodda hiçbir görünüm ayarı yoktur; hepsi Inbox → Ayarlar → Uygulamalar altında durur ve bootstrap ile widget'a iner.

Panel ayarı Widget'ta karşılığı
Sohbet açık / kapalı (chat_enabled) Kapalıysa widget hiçbir şey çizmez
İzinli kökenler Liste dışı alan adından 403
Tema rengi, konum (sağ / sol) Marka rengi ve panelin başlangıç yeri
Logo adresi (logo_url) Başlık avatarı; launcher_icon: logo ise balon
Tema (theme: açık / koyu / ziyaretçinin tercihi) Widget'ın kendi yüzeyi - sayfaya dokunmaz
Balon ikonu (launcher_icon: kuş / baloncuk / logo) Balondaki işaret
Balon davranışı (launcher_mode: her zaman / yalnız çağrıldığında) manual seçilirse balon hiç çizilmez; sohbeti sitenizin kendi düğmesi açar
Panel biçimi (layout: köşe penceresi / kenar çekmecesi / sayfa içi) sidebar ekran boyu kenar panelidir; inline sohbeti sayfanın içine çizer
Sayfa içi kap (inline_selector) inline biçiminde sohbetin çizileceği kabın CSS seçicisi (varsayılan #signalbird-chat)
Görünen ajan adı (agent_display_name) Ziyaretçi ajanın gerçek adı yerine bunu görür
Dile göre metinler (texts) Karşılama, çevrimdışı notu ve balon etiketi ziyaretçinin diline göre
Başlatıcı metni, karşılama mesajı Balon üstündeki etiket, ilk mesaj
Sohbet öncesi form alanları İsim / e-posta zorunluluğu
Çalışma saatleri Çevrimdışı şeridi ve "en kısa sürede döneriz" notu
max_attachment_mb Yükleme üst sınırı

Ayar değişikliği yeni yayın gerektirmez; bir sonraki sayfa yüklemesinde geçerlidir.

Sayfa içi (inline) sohbet

Sohbeti köşedeki balon yerine sayfanın İÇİNE koyabilirsiniz - destek sayfasının gövdesi sohbet olur. Balon, kapatma düğmesi ve sürükleme yoktur; sohbet kendiliğinden açıktır.

html
<div id="destek" style="height:640px"></div>

<script async src="https://signalbird.io/sdk/v1/signalbird.js"
        data-key="sb_public_live_…" data-channel="destek"
        data-layout="inline" data-container="#destek"></script>

Aynı sitede ikisi birden. Panel ayarı sitenin varsayılanıdır; tek bir sayfa ondan ayrılabilir. Her sayfada balon dururken destek sayfasına sayfa içi bir sohbet daha koymak için:

html
<script async src="https://signalbird.io/sdk/v1/signalbird.js"
        data-key="sb_public_live_…" data-channel="destek"></script>

<div id="destek" style="height:640px"></div>
<script>Signalbird.inline('#destek')</script>

Signalbird.inline(kap, seçenekler?) anahtarları init()ten devralır ve aynı kaba ikinci kez çizmez. Kap bulunamazsa sohbet balon olarak açılır - yanlış bir seçici yüzünden sohbetin hiç görünmemesindense.

Balonu kendi düğmenizle açmak

Sitenizde zaten bir "Canlı destek" düğmesi varsa balonu hiç göstermeyebilirsiniz. Panelden balon davranışı: yalnız çağrıldığında (launcher_mode: manual) seçin ve düğmenize tek satır bağlayın:

html
<button onclick="Signalbird.chat.open()">Canlı destek</button>

Sohbet başladıktan sonra balon görünür olur: ziyaretçi pencereyi kapatırsa temsilcinin yanıtı balonda ışık ve sesle bildirilir. Ziyaretçi sohbeti bitirdiğinde balon yeniden kaybolur.

Kimlik doğrulaması ve captcha

Kimlik doğrulaması (2.7.0). Açık anahtar sayfanın kaynağında durduğu için herkes identify({ external_id: 'user-1042' }) yazabilir. Bu yüzden Signalbird external_id'yi (ve e-postayı) ancak yanında geçerli bir identityHash varsa güvenilir sayar. Hash olmadan:

  • ziyaretçi kişi kaydınıza (contact) bağlanmaz,
  • cihazı o kullanıcıya push hedefi olarak bağlanmaz (external:user-1042),
  • kanal ajanının araçları kimliği güvenilir ziyaretçi olarak değil, yalnız visitor.unverified altında görür.

Hash SUNUCUNUZDA, gizli anahtarla üretilir ve sayfaya kullanıcının kimliğiyle birlikte yazılır; gizli anahtar asla tarayıcıya inmez:

text
identity_hash = hex( HMAC-SHA256( hex(SHA-256(sb_secret_live_…)), external_id ) )

Her sunucu dilinde hazır yardımcı var: PHP Signalbird::identityHash($id), Node client.identityHash(id), Python client.identity_hash(id), Go client.IdentityHash(id), .NET client.IdentityHash(id).

html
<!-- Laravel Blade -->
<script async src="https://signalbird.io/sdk/v1/signalbird.js"
        data-key="sb_public_live_…" data-channel="destek"
        data-external-id="{{ $user->id }}"
        data-identity-hash="{{ Signalbird::identityHash((string) $user->id) }}"></script>

Widget bildiği hash'i oturum, identify ve aynı external_id'li push.register çağrılarına kendisi ekler.

Captcha. Kanalınızda açıksa widget iki noktada görünmez bir Cloudflare Turnstile jetonu alır: yeni ziyaretçinin oturumu açılırken ve doğrulanmamış ziyaretçi ilk konuşmayı başlatırken. Kurulumda yapmanız gereken bir şey yoktur:

  • Turnstile betiği yalnız ziyaretçi sohbeti ilk açtığında yüklenir; sohbeti hiç açmayan ziyaretçiye indirilmez.
  • Çoğu ziyaretçi hiçbir şey görmez; Cloudflare etkileşim isterse kutu panelin içinde çıkar.
  • Kısa sürede çok fazla sohbet başlatılırsa ziyaretçiye nazik bir uyarı gösterilir (429 CONVERSATION_RATE_LIMITED).
  • İçerik güvenlik politikası (CSP) kullanıyorsanız script-src ve frame-src'e https://challenges.cloudflare.com ekleyin.

Gizlilik ve güvenlik

  • Ziyaretçi kimliği ve gizli anahtarı yalnız localStorage['sb_visitor'] içinde durur; çerez yazılmaz, üçüncü tarafa gitmez.
  • Ekibin Inbox'ta yazdığı iç notlar ziyaretçiye hiçbir zaman gönderilmez.
  • Anlık çeviri yalnız iki taraf farklı dil kullanıyorsa çalışır ve her taraf yalnız KARŞI tarafın mesajını çevrilmiş görür; kendi yazdığı hep orijinaliyle durur.
  • Uygulama anahtarı açıktır; koruma izinli kökenlerdedir. Bu listeyi geniş tutmayın (* yok).
  • Widget sitenizin DOM'unu okumaz, form alanlarına dokunmaz; yalnız kendi Shadow DOM kökünde çalışır.
  • Yüklenen dosyalar takımınızın depolamasına gider ve yalnız o sohbetin taraflarına açılır.

Sorun giderme

Belirti Sebep / çözüm
Widget hiç görünmüyor, konsol sessiz Uygulamada sohbet kapalı (chat_enabled: false). Panelden açın
Konsolda bootstrap 403 Alan adı izinli kökenlerde yok - https:// şemasıyla birlikte ekleyin; localhost:3000 da ayrıca eklenmeli
bootstrap 401 Anahtar yanlış türde (gizli/açık karışmış) ya da iptal edilmiş
Balon var, mesaj gitmiyor Ağ sekmesinde /v1/sdk/* isteklerine bakın; debug: true ile konsola ayrıntı yazılır
Giriş sonrası geçmiş görünmüyor identify çağrılmamış ya da farklı external_id
Ziyaretçi kişi kaydına bağlanmıyor, push kullanıcıya gitmiyor identityHash verilmemiş ya da yanlış anahtarla üretilmiş - kimlik doğrulanmamış sayılır
"Güvenlik doğrulaması tamamlanamadı" bandı Turnstile yüklenemedi ya da reddedildi; CSP'de challenges.cloudflare.com izinli mi bakın
Sitenin CSS'i widget'ı bozdu Olmamalı (Shadow DOM). Sayfada all: unset gibi agresif global kurallar varsa debug ile bildirin