Hızlı başlangıç
- Konsolda Ayarlar → Kurulum sayfasından site anahtarınızı (
cd_ile başlar) kopyalayın. - Sayfanın başındaki kodu sitenizin tüm sayfalarına,
</body>etiketinden hemen önce ekleyin.SITE_ANAHTARINIZyerine kendi anahtarınızı yazın. - 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 yönetiminde Eklentiler → Yeni ekle → Eklenti yükle ile zip dosyasını yükleyip etkinleştirin.
- Ayarlar → Layvchat sayfasına site anahtarınızı yapıştırın.
- İ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 | İngilizce | Ne 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 | İngilizce | Ne zaman | Veri |
|---|---|---|---|
hazir | ready | Widget kuruldu (sonradan eklenen dinleyici de hemen çağrılır). | durum() |
acildi / kapandi | open / close | Pencere açıldı / kapandı. | — |
sohbetBasladi | chatStarted | Ziyaretçi yeni bir sohbet başlattı. | — |
sohbetBitti | chatEnded | Sohbet sona erdi. | — |
mesaj | message | Temsilci ya da ziyaretçi mesaj gönderdi. | { kim: 'ajan' | 'ziyaretci', metin, ajan } |
okunmamis | unread | Okunmamış 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şken | Varsayılan | Ne yapar |
|---|---|---|
--layvchat-alt | Widget ayarındaki alt boşluk | Butonun sayfanın altından uzaklığı. |
--layvchat-yan | Widget ayarındaki yan boşluk | Butonun sağ (ya da sol) kenardan uzaklığı. |
--layvchat-z | 2147483600 | Katman 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)
| Alan | Kural |
|---|---|
id | Üyenin sitenizdeki kimliği. 1–64 karakter: harf, rakam, _ ve -. |
username | Ajanlara gösterilen kullanıcı adı. İmzada gönderdiğiniz değerin aynısı kullanılır (en fazla 80 karakter gösterilir). |
zaman | Unix zamanı, saniye (milisaniye değil). İmza 2 saat geçerlidir; sunucu saatiniz en fazla 5 dakika ileride olabilir. |
imza | HMAC-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.
- Sunucunuzda aşağıdaki uçları yazın (ör.
https://siteniz.com/layvchat-apialtında). - 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. - Ajanlara gereken izinleri Ayarlar → Ajanlar bölümünden verin (bilgileri görme, not, engelleme).
İstekler
| İstek | Gövde | Ne 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ür | Alanlar |
|---|---|
| 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ır | cevrimici, epostaDogrulandi, telefonDogrulandi |
| Zaman (ISO 8601) | sonCevrimici, sonGiris, kayitTarihi |
| Tarih (YYYY-AA-GG) | dogumTarihi |
| Tutar (sayı) | toplamHarcama, toplamIade |
| Durum | durum: aktif, engelli, beklemede, kapali |
| Liste | riskEtiketleri (en fazla 20) |
| Son işlemler | sonIslemler[]: 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.
| Olay | Ne zaman | veri |
|---|---|---|
sohbet.basladi | Yeni sohbet başladı | { konusma } |
sohbet.bitti | Sohbet kapandı | { konusma } |
sohbet.kacirildi | Ziyaretçi yanıt almadan ayrıldı | { konusma } |
sohbet.cevrimdisi | Çevrimdışıyken mesaj bırakıldı | { konusma, mesaj } |
sohbet.puanlandi | Ziyaretçi puan verdi | { konusmaId, puan, yorum, anket } |
sohbet.risk | Risk 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-Olay | Olay adı |
X-Imza-Zaman | Unix saniye |
X-Imza-Imza | sha256= + HMAC-SHA256(sır, zaman + "." + hamGövde), küçük harf onaltılık |
X-Imza-Teslim | Teslim 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ç | Parametreler | Yanıt |
|---|---|---|
GET /api/v1/canli/rapor | gun: 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/sohbetler | bas, 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/ayaristeğinin yanıtına bakın:404anahtarın tanınmadığını gösterir. - Ziyaretçi doğrulanmış görünmüyor
- En sık sebepler:
zamanmilisaniye gönderilmiş (saniye olmalı), imza büyük harfle yazılmış, sunucu saati yanlış, imzadaki kullanıcı adı gönderilenden farklı ya daidizin 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
httpsolmalı, 8 saniye içinde2xxdö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.