İçeriğe geç

Kurulum rehberi

Widget'ı sitenize eklemek tek satır kod. Ziyaretçi kimliği, site entegrasyonu, webhook ve API isteğe bağlıdır; ihtiyaç duyduğunuzda ilgili bölümü izleyin.

<script src="{{KOK}}/cd/w.js?k=SITE_ANAHTARINIZ" async></script>

Site anahtarınız konsolda Ayarlar → Kurulum sayfasındadır. WordPress kullanıyorsanız eklentiyle kod yazmadan kurun.

Hızlı başlangıç

  1. Konsolda Ayarlar → Kurulum sayfasından site anahtarınızı (cd_ ile başlar) kopyalayın.
  2. Sayfanın başındaki kodu sitenizin tüm sayfalarına, </body> etiketinden hemen önce ekleyin. SITE_ANAHTARINIZ yerine kendi anahtarınızı yazın.
  3. Sayfayı yenileyin; sağ altta sohbet düğmesi görünür. Konsolda çevrimiçi olduğunuzda ziyaretçiler size yazabilir.

Kod sayfanızı yavaşlatmaz: yükleyici küçük ve önbelleklidir, widget ayrı ve sürümlü yüklenir. Sunucuya ulaşılamazsa, Ayarlar → Genel → Yedek iletişim bağlantısı alanına yazdığınız adrese giden basit bir düğme gösterilir.

WordPress

Kod yazmadan kurmak için eklentiyi indirin. Eklenti widget'ı ekler ve isterseniz giriş yapmış üyelerinizi imzalı kimlikle tanıtır.

WordPress eklentisini indir

  1. WordPress yönetiminde Eklentiler → Yeni ekle → Eklenti yükle ile zip dosyasını yükleyip etkinleştirin.
  2. Ayarlar → Layvchat sayfasına site anahtarınızı yapıştırın.
  3. İsteğe bağlı: Üye kimliği kutusunu işaretleyip imza sırrını girin (konsolda Ayarlar → Ziyaretçi kimliği → Sırrı göster).

Önbellek eklentileriyle uyumludur: üye kimliği sayfanın HTML'ine yazılmaz, her ziyaretçi için ayrı ve önbelleğe alınmayan bir istekle alınır. İmza sırrı sitenizin sunucusunda kalır.

Widget'ı kodla yönetmek

Kurulum kodu sayfaya window.layvchat nesnesini ekler. Komutlar kod yüklenir yüklenmez kullanılabilir: widget henüz hazır değilse çağrı bekletilir, hazır olunca çalışır. Her komutun İngilizce adı da vardır (ör. ac = open).

Komutlar

KomutİngilizceNe yapar
ac()open()Sohbet penceresini açar.
kapat()close()Pencereyi kapatır.
degistir()toggle()Açıksa kapatır, kapalıysa açar.
gizle() / goster()hide() / show()Butonu ve pencereyi sayfadan tamamen kaldırır / geri getirir (ör. ödeme adımında).
doldur(metin)prefill()Pencereyi açar ve yazma kutusuna metni yazar; ziyaretçi gönder'e basar.
ziyaretci({ ad, eposta, telefon })setVisitor()Ziyaretçiyi tanıtır: formdaki alanlar önceden dolar, sohbette ad ve e-posta görünür.
ozellik({ anahtar: değer })setAttributes()Temsilcinin göreceği özel bilgiler (sepet tutarı, üyelik türü…). En çok 20 alan; null değer alanı siler. Sohbet açıkken de güncellenebilir.
sayfa()pageView()Sayfa değişimini bildirir. Tek sayfalı uygulamalarda (React, Vue…) adres değişimi zaten otomatik algılanır; özel yönlendirmelerde kullanın.
durum()getState(){ acik, sohbet, okunmamis, ajan } döndürür.
on(olay, fn) / off(olay, fn)aynıOlay dinler / dinlemeyi bırakır.
// "Bu ürünü sor" düğmesi
document.querySelector('#urun-sor').addEventListener('click', function () {
  window.layvchat.doldur('Merhaba, "Deri Sırt Çantası" hakkında bilgi almak istiyorum.')
})

// Giriş yapmış üyeyi ve sepetini temsilciye göster
window.layvchat.ziyaretci({ ad: 'Ayşe Yılmaz', eposta: '[email protected]' })
window.layvchat.ozellik({ 'Sepet tutarı': '1.249 TL', 'Üyelik': 'Altın' })

ziyaretci ve ozellik bilgileri tarayıcıdan gelir, imzasızdır; konsolda doğrulanmamış olarak gösterilir. Üye hesabını güvenle tanıtmak için ziyaretçi kimliğini kullanın.

Olaylar

OlayİngilizceNe zamanVeri
hazirreadyWidget kuruldu (sonradan eklenen dinleyici de hemen çağrılır).durum()
acildi / kapandiopen / closePencere açıldı / kapandı.—
sohbetBasladichatStartedZiyaretçi yeni bir sohbet başlattı.—
sohbetBittichatEndedSohbet sona erdi.—
mesajmessageTemsilci ya da ziyaretçi mesaj gönderdi.{ kim: 'ajan' | 'ziyaretci', metin, ajan }
okunmamisunreadOkunmamış mesaj sayısı değişti.{ n }
window.layvchat.on('sohbetBasladi', function () {
  gtag('event', 'canli_destek_sohbet')        // analitik
})
window.layvchat.on('mesaj', function (m) {
  if (m.kim === 'ajan') console.log(m.ajan + ': ' + m.metin)
})

// Aynı olaylar window üzerinde de yayınlanır
window.addEventListener('layvchat:okunmamis', function (e) { rozet(e.detail.n) })

Kodunuz kurulum kodundan önce çalışıyorsa çağrıları kuyruğa ekleyin:

(window.layvchatKuyruk = window.layvchatKuyruk || []).push(['ac'], ['ozellik', { 'Sayfa': 'Ödeme' }])

CSS değişkenleri

Butonun konumu ve katmanı sitenizin CSS'iyle ezilebilir; pencere de butona göre konumlanır. Çerez bandı ya da mobil alt menüyle çakışıyorsa kullanın.

DeğişkenVarsayılanNe yapar
--layvchat-altWidget ayarındaki alt boşlukButonun sayfanın altından uzaklığı.
--layvchat-yanWidget ayarındaki yan boşlukButonun sağ (ya da sol) kenardan uzaklığı.
--layvchat-z2147483600Katman sırası (z-index).
@media (max-width: 768px) {
  :root { --layvchat-alt: 84px; }   /* mobil alt menünün üstünde dursun */
}

Daha önce Tawk.to ya da Comm100 kullandıysanız mevcut Tawk_API.maximize() ve Comm100API.do('livechat.button.click') çağrılarınız da Layvchat penceresini açar; düğmelerinizi değiştirmeniz gerekmez.

Ziyaretçi kimliği

Sitenize giriş yapmış ziyaretçileri tanıtırsanız ajanlarınız sohbet eden kişinin hangi üye olduğunu doğrulanmış olarak görür (mavi onay işareti). Doğrulanmış ziyaretçide ön sohbet formu atlanabilir ve site entegrasyonu açıksa müşteri kartı gösterilir.

Kimlik, sitenizin sunucusunda bir imza ile kanıtlanır; böylece kimse tarayıcıdan başka bir üyeyi taklit edemez. İmza sırrını konsolda Ayarlar → Ziyaretçi kimliği → Sırrı göster ile alın ve yalnız sunucunuzda saklayın.

İmza

imza = HMAC-SHA256(sır, id + "|" + kullaniciAdi + "|" + zaman)   → küçük harf onaltılık (64 karakter)
AlanKural
idÜyenin sitenizdeki kimliği. 1–64 karakter: harf, rakam, _ ve -.
usernameAjanlara gösterilen kullanıcı adı. İmzada gönderdiğiniz değerin aynısı kullanılır (en fazla 80 karakter gösterilir).
zamanUnix zamanı, saniye (milisaniye değil). İmza 2 saat geçerlidir; sunucu saatiniz en fazla 5 dakika ileride olabilir.
imzaHMAC-SHA256, küçük harf onaltılık. Sır, olduğu gibi metin olarak anahtar yapılır.

Kimliği widget'a iletmenin üç yolu

1. Sayfaya yazmak. Sayfayı sunucuda üretiyorsanız kurulum kodundan önce ekleyin. Sayfa önbelleği kullanıyorsanız bu yolu seçmeyin; bir üyenin imzası başka ziyaretçilere gösterilebilir.

<script>
  window.layvchatKimlik = { id: "123", username: "ahmet", zaman: 1760000000, imza: "…" }
</script>

2. Giriş ve çıkışta bildirmek. Tek sayfalık uygulamalar (React, Vue…) için uygundur. İmza 2 saat geçerli olduğundan uzun açık kalan sayfalarda yeni imzayla tekrar çağırın.

window.layvchat.kimlik({ id: "123", username: "ahmet", zaman: 1760000000, imza: "…" })
window.layvchat.kimlik(null)   // çıkış yapınca

3. Kimlik ucu. Konsolda Ayarlar → Ziyaretçi kimliği → Kimlik ucu alanına sitenizde imzalı kimliği döndüren göreli bir adres yazın (ör. /layvchat/kimlik). Widget bu adresi aynı kökenden, çerezlerle birlikte okur; sayfa açılışında, 15 saniyede bir, sekmeye dönüldüğünde ve sayfa içi gezinmede tazeler. Giriş yapmamış ziyaretçi için {"id": null} dönün; JSON olmayan ya da başarısız yanıt "çıkış yapmış" sayılır.

<?php // /layvchat/kimlik
session_start();
header('Content-Type: application/json');
header('Cache-Control: no-store');
$sir = getenv('LAYVCHAT_KIMLIK_SIRRI');
if (empty($_SESSION['uye_id'])) { echo json_encode(['id' => null]); exit; }
$id = (string) $_SESSION['uye_id'];
$ad = (string) $_SESSION['uye_adi'];
$zaman = time();
echo json_encode([
  'id' => $id, 'username' => $ad, 'zaman' => $zaman,
  'imza' => hash_hmac('sha256', "$id|$ad|$zaman", $sir),
]);
// Express — /layvchat/kimlik
import crypto from 'node:crypto'
app.get('/layvchat/kimlik', (req, res) => {
  res.set('Cache-Control', 'no-store')
  const uye = req.session?.uye
  if (!uye) return res.json({ id: null })
  const id = String(uye.id), ad = String(uye.kullaniciAdi), zaman = Math.floor(Date.now() / 1000)
  const imza = crypto.createHmac('sha256', process.env.LAYVCHAT_KIMLIK_SIRRI).update(`${id}|${ad}|${zaman}`).digest('hex')
  res.json({ id, username: ad, zaman, imza })
})
# Flask — /layvchat/kimlik
import hmac, hashlib, os, time
from flask import jsonify, session

@app.get("/layvchat/kimlik")
def layvchat_kimlik():
    if "uye_id" not in session:
        yanit = jsonify(id=None)
    else:
        uid, ad, zaman = str(session["uye_id"]), str(session["uye_adi"]), int(time.time())
        imza = hmac.new(os.environ["LAYVCHAT_KIMLIK_SIRRI"].encode(), f"{uid}|{ad}|{zaman}".encode(), hashlib.sha256).hexdigest()
        yanit = jsonify(id=uid, username=ad, zaman=zaman, imza=imza)
    yanit.headers["Cache-Control"] = "no-store"
    return yanit

Ayarlar → Ziyaretçi kimliği → Yalnız imzalı kimliği göster açıkken imzası geçersiz kullanıcı adları ajanlara hiç gösterilmez. Kapalıyken yalnız görünen ad olarak kullanılır, doğrulanmış sayılmaz.

İçerik güvenlik politikası (CSP)

Sitenizde CSP varsa Layvchat adresine şu izinleri ekleyin:

script-src   {{KOK}}
connect-src  {{KOK}} {{WS}}     (kimlik ucu kullanıyorsanız 'self' de)
frame-src    {{KOK}}
style-src    'unsafe-inline'
img-src      https:            (yalnız özel düğme görseli kullanıyorsanız)
media-src    {{KOK}}           (yalnız özel bildirim sesi kullanıyorsanız)

Widget sitenizde çerez oluşturmaz. Ziyaretçi anahtarı ve yedek bağlantı localStorage içinde layv_cd_ önekiyle tutulur; sohbet içeriği ve erişim anahtarı yalnız Layvchat penceresinin kendi kökeninde kalır.

Site entegrasyonu Pro

Ajanlarınız sohbet sırasında doğrulanmış ziyaretçinin hesap bilgilerini (son siparişler, durum…) görür ve izin verdiğiniz işlemleri yapar. Layvchat bu bilgileri sizin sunucunuzdaki birkaç uçtan, imzalı isteklerle alır. Entegrasyon yalnız kimliği doğrulanmış ziyaretçilerde çalışır.

  1. Sunucunuzda aşağıdaki uçları yazın (ör. https://siteniz.com/layvchat-api altında).
  2. Konsolda Ayarlar → Site entegrasyonu sayfasına bu adresi girin. İmza sırrı (entg_ ile başlar) yalnız bir kez gösterilir; sunucunuzda saklayın.
  3. Ajanlara gereken izinleri Ayarlar → Ajanlar bölümünden verin (bilgileri görme, not, engelleme).

İstekler

İstekGövdeNe zaman
GET /uye/:id—Ajan sohbeti açınca (müşteri kartı)
POST /uye/:id/not{ not, yapan }Müşteri notu
POST /uye/:id/durum{ engelli: true | false, yapan }Hesabı engelleme / açma
POST /uye/:id/mesaj{ baslik, govde, yapan }Sitenizin mesaj kutusuna yanıt

:id, ziyaretçi kimliğindeki id değeridir. yapan işlemi yapan ajanı gösterir (canli-destek:kullaniciadi).

İmzayı doğrulayın

Her istek X-Imza-Zaman (unix saniye) ve X-Imza başlıklarıyla gelir:

X-Imza = HMAC-SHA256(sır, zaman + "." + YÖNTEM + "." + tamYol + "." + hamGövde)   → küçük harf onaltılık

tamYol, adresinizin yolu dahil isteğin yoludur: adres https://siteniz.com/layvchat-api ise /layvchat-api/uye/42. GET isteklerinde gövde boş metindir. 5 dakikadan eski zamanı reddedin.

<?php
function layvchat_dogrula(string $sir): bool {
  $zaman = $_SERVER['HTTP_X_IMZA_ZAMAN'] ?? '';
  $imza  = $_SERVER['HTTP_X_IMZA'] ?? '';
  if (!ctype_digit($zaman) || abs(time() - (int) $zaman) > 300) return false;
  $govde = file_get_contents('php://input');
  $beklenen = hash_hmac('sha256', $zaman . '.' . $_SERVER['REQUEST_METHOD'] . '.' . $_SERVER['REQUEST_URI'] . '.' . $govde, $sir);
  return hash_equals($beklenen, $imza);
}
// Express: ham gövde gerekir → app.use(express.json({ verify: (req, _r, buf) => { req.hamGovde = buf.toString() } }))
import crypto from 'node:crypto'
function layvchatDogrula(req, sir) {
  const zaman = req.get('x-imza-zaman') || '', imza = req.get('x-imza') || ''
  if (!/^\d+$/.test(zaman) || Math.abs(Date.now() / 1000 - Number(zaman)) > 300) return false
  const beklenen = crypto.createHmac('sha256', sir)
    .update(`${zaman}.${req.method}.${req.originalUrl}.${req.hamGovde || ''}`).digest('hex')
  return beklenen.length === imza.length && crypto.timingSafeEqual(Buffer.from(beklenen), Buffer.from(imza))
}

Müşteri kartı yanıtı

GET /uye/:id bir JSON nesnesi döndürmelidir. Yalnız uye.id zorunludur; tanımadığımız alanlar yok sayılır. Üye yoksa 404 dönün.

{
  "uye": {
    "id": "42", "kullaniciAdi": "ahmet", "ad": "Ahmet", "soyad": "Yılmaz",
    "eposta": "[email protected]", "telefon": "5551112233", "ulke": "TR", "paraBirimi": "TRY",
    "toplamHarcama": 5000, "toplamIade": 320,
    "durum": "aktif", "kayitTarihi": "2025-03-14T10:00:00Z", "sonGiris": "2026-10-04T21:10:00Z",
    "riskEtiketleri": ["yeni hesap"]
  },
  "sonIslemler": [
    { "id": "S1001", "tur": "siparis", "tutar": 500, "durum": "kargoda", "aciklama": "2 ürün", "zaman": "2026-10-04T20:00:00Z" }
  ]
}
Tüm müşteri alanları
TürAlanlar
Metin (en fazla 200 karakter)kullaniciAdi, eposta, ad, ikinciAd, soyad, telefon, telefonKodu, sehir, dil, sonGirisIp, kayitIp, yoneticiNotu
Ülke kodu (2 harf)ulke, kayitUlke
Para birimi (3 harf)paraBirimi
Evet / hayırcevrimici, epostaDogrulandi, telefonDogrulandi
Zaman (ISO 8601)sonCevrimici, sonGiris, kayitTarihi
Tarih (YYYY-AA-GG)dogumTarihi
Tutar (sayı)toplamHarcama, toplamIade
Durumdurum: aktif, engelli, beklemede, kapali
ListeriskEtiketleri (en fazla 20)
Son işlemlersonIslemler[]: id (zorunlu), tur (siparis, odeme, iade ya da kendi metniniz), tutar, durum, aciklama, zaman — ilk 10 kayıt gösterilir

POST isteklerinde başarılıysanız 2xx ve bir JSON nesnesi dönün (ör. {"ok": true}). Reddetmek için {"hata": "kısa_kod"} dönün. 404 "bulunamadı", diğer hata kodları "site hata döndürdü" olarak ajana gösterilir.

İstekler yalnız https ve 443 portuna, genel internetteki adreslere yapılır; yönlendirme izlenmez. Zaman aşımı 10 saniye, yanıt en fazla 512 KB.

Webhook Pro

Sohbet olaylarını kendi sisteminize (CRM, bildirim, raporlama) anında gönderin. Konsolda Ayarlar → Webhook ve API sayfasından adres ve olayları seçin; imza sırrı (whsec_ ile başlar) bir kez gösterilir.

OlayNe zamanveri
sohbet.basladiYeni sohbet başladı{ konusma }
sohbet.bittiSohbet kapandı{ konusma }
sohbet.kacirildiZiyaretçi yanıt almadan ayrıldı{ konusma }
sohbet.cevrimdisiÇevrimdışıyken mesaj bırakıldı{ konusma, mesaj }
sohbet.puanlandiZiyaretçi puan verdi{ konusmaId, puan, yorum, anket }
sohbet.riskRisk seviyesi yükseldi{ konusmaId, risk: { seviye, turler, kelimeler, zaman } }
{
  "id": "6f1c…",                 // teslim kimliği — yeniden denemelerde aynı kalır
  "olay": "sohbet.bitti",
  "zaman": "2026-10-05T09:12:00.000Z",
  "deneme": 1,
  "veri": {
    "konusma": {
      "id": "…", "durum": "kapandi", "kaynak": "ziyaretci",
      "baslatildi": "…", "kapandi": "…", "kapanisSebep": "kapatildi",
      "ziyaretci": { "no": 128, "ad": "Ahmet", "kullaniciAdi": "ahmet", "uyeId": "42", "ulke": "TR" },
      "ajan": "Ayşe", "etiketler": ["ödeme"], "puan": 5
    }
  }
}

kullaniciAdi ve uyeId yalnız kimliği doğrulanmış ziyaretçide doludur.

Başlıklar ve imza

X-Imza-OlayOlay adı
X-Imza-ZamanUnix saniye
X-Imza-Imzasha256= + HMAC-SHA256(sır, zaman + "." + hamGövde), küçük harf onaltılık
X-Imza-TeslimTeslim kimliği (gövdedeki id ile aynı)
<?php
$govde = file_get_contents('php://input');
$zaman = $_SERVER['HTTP_X_IMZA_ZAMAN'] ?? '';
$beklenen = 'sha256=' . hash_hmac('sha256', $zaman . '.' . $govde, getenv('LAYVCHAT_WEBHOOK_SIRRI'));
if (!ctype_digit($zaman) || abs(time() - (int) $zaman) > 300 || !hash_equals($beklenen, $_SERVER['HTTP_X_IMZA_IMZA'] ?? '')) {
  http_response_code(401); exit;
}
$olay = json_decode($govde, true);
// $olay['id'] daha önce işlendiyse atlayın; sonra 2xx dönün
http_response_code(204);
import crypto from 'node:crypto'
app.post('/layvchat/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const zaman = req.get('x-imza-zaman') || '', ham = req.body.toString()
  const beklenen = 'sha256=' + crypto.createHmac('sha256', process.env.LAYVCHAT_WEBHOOK_SIRRI).update(`${zaman}.${ham}`).digest('hex')
  const imza = req.get('x-imza-imza') || ''
  const gecerli = /^\d+$/.test(zaman) && Math.abs(Date.now() / 1000 - Number(zaman)) <= 300 &&
    imza.length === beklenen.length && crypto.timingSafeEqual(Buffer.from(imza), Buffer.from(beklenen))
  if (!gecerli) return res.sendStatus(401)
  const olay = JSON.parse(ham)
  // olay.id daha önce işlendiyse atlayın
  res.sendStatus(204)
})

8 saniye içinde 2xx dönün; ağır işleri kuyruğa alın. Başarısız teslim 5 sn, 30 sn ve 2 dk sonra yeniden denenir (en fazla 4 deneme). Art arda 20 başarısız denemede webhook kapatılır; konsoldan son 50 teslimi görebilir ve "Test" ile deneme gönderebilirsiniz. Adres https ve 443 portunda, genel internette olmalıdır.

REST API Pro

Raporları ve sohbetleri kendi sistemlerinize çekin. Anahtarı konsolda Ayarlar → Webhook ve API → API anahtarları bölümünden (yalnız çalışma alanı sahibi) oluşturun; gizli anahtar bir kez gösterilir. En fazla 5 etkin anahtar olabilir; her anahtar için izinli IP listesi tanımlanabilir. Anahtarlar salt okunurdur.

curl -u "layv_…:layvs_…" "{{KOK}}/api/v1/canli/rapor?gun=7"
UçParametrelerYanıt
GET /api/v1/canli/raporgun: 1, 7, 30 ya da 90 (varsayılan 7)Özet, günlük ve saatlik dağılım, ajan performansı, puanlar, etiketler, kaçırılan sohbetler
GET /api/v1/canli/sohbetlerbas, bit (YYYY-AA-GG, dahil) · durum: acik | kapandi · adet 1–200 (50) · sayfa{ toplam, sayfa, adet, liste: [konusma] }
GET /api/v1/canli/sohbet/:id—{ sohbet, mesajlar: [{ kim, ajan, metin, dosya, zaman }] } — iç notlar ve fısıltılar dahil edilmez
GET /api/v1/ben—Anahtarın adı ve kapsamı

konusma nesnesi webhook'takiyle aynıdır. Hata kodları: 401 anahtar eksik ya da geçersiz (sebep güvenlik için açıklanmaz) · 402 paketinizde API yok · 404 sohbet bulunamadı.

Sorun giderme

Sohbet düğmesi görünmüyor
Site anahtarını kontrol edin (cd_ ile başlar). Konsolda Ayarlar → Genel → Canlı destek açık kapalı olabilir ya da Ayarlar → Widget görünümü → Mobilde gizle açık olabilir. Sitenizde CSP varsa izinleri ekleyin. Tarayıcı konsolunda /cd/v/ayar isteğinin yanıtına bakın: 404 anahtarın tanınmadığını gösterir.
Ziyaretçi doğrulanmış görünmüyor
En sık sebepler: zaman milisaniye gönderilmiş (saniye olmalı), imza büyük harfle yazılmış, sunucu saati yanlış, imzadaki kullanıcı adı gönderilenden farklı ya da id izin verilmeyen karakter içeriyor. İmza 2 saat geçerlidir; uzun açık kalan sayfalarda yenileyin.
Webhook gelmiyor
Konsolda Ayarlar → Webhook ve API sayfasında teslim geçmişine bakın. Adres https olmalı, 8 saniye içinde 2xx dönmeli ve yönlendirme yapmamalıdır. Art arda 20 hatadan sonra webhook kapanır; düzelttikten sonra tekrar açın.
Müşteri kartı açılmıyor
Kart yalnız kimliği doğrulanmış ziyaretçilerde ve ajanın bilgileri görme izni varsa açılır. Sunucunuz imzayı doğrularken tam yolu (adresinizin yolu dahil) kullanmalıdır.