KampanyalarKampanya Raporları (ROI & A/B)

Kampanya Raporları

Kampanya bittiğinde asıl soru “kaç kişi arandı” değil — “bu kampanya para kazandırdı mı?” Kampanya raporları tam bunu gösterir: 420 çağrının maliyeti ne oldu, kaçı gerçek görüşmeye döndü, kaç randevu açıldı ve bu maliyet hangi kaleme (konuşma tanıma, model, ses, hat) gitti. İki rapor var — ROI raporu her kampanyada çalışır; A/B raporu ise iki varyantı istatistiksel olarak karşılaştırıp “hangisi gerçekten kazandı, yoksa bu fark rastlantı mı?” sorusunu cevaplar.

İki rapor, iki soru

RaporCevapladığı soruUç nokta
ROI raporuKampanya kaça mal oldu, ne kazandırdı? Maliyet nereye gitti?GET /api/campaigns/{id}/roi
A/B raporuA ve B varyantından hangisi kazandı — ve bu istatistiksel olarak anlamlı mı?GET /api/campaigns/{id}/ab-report

Her iki rapor da panelde ilgili kampanyanın detay ekranından açılır; oturum (giriş) yetkisiyle çalışır ve sadece kendi kampanyalarını gösterir.

Dönüşüm ve maliyet her planda çalışır — süre ve cost_breakdown verisinden hesaplanır. Ama sonuç dağılımı, randevu sayısı ve duygu metrikleri AI Çağrı Analizi’ne dayanır (Premium özellik). Asistanında çağrı analizi kapalıysa bu alanlar boş/sıfır görünebilir.

ROI raporu

ROI = “return on investment”, yani yatırımın geri dönüşü. Rapor, kampanyaya ait tüm çağrıları okur, her çağrının maliyet kırılımını ve AI analizini toplar, sonra tek bir tabloya indirger.

Kampanya çağrıları biter

Her çağrının cost_breakdown + AI analizi okunur

Toplanır: maliyet (stt / llm / tts / sip) + sonuç + randevu + SMS

ROI raporu: özet metrikler + maliyet kırılımı + sonuç dağılımı

Özet metrikler

Raporun summary bölümü, kampanyanın tek bakışta özetidir:

AlanNe anlatır
totalCallsKampanyada denenen toplam çağrı (başarılı + başarısız hepsi).
completedCallsDurumu completed olan, yani karşı tarafın açtığı çağrılar.
successfulCallsTamamlanmış ve 30 saniyeden uzun süren çağrılar. 30 saniyenin altı meşgul/hatalı sayılır.
conversionRatesuccessfulCalls ÷ totalCalls × 100. Yani tüm denemelerin yüzde kaçı gerçek görüşmeye döndü (sadece açılanların değil).
avgDurationTamamlanan çağrılara bölünmüş toplam görüşme süresi (saniye).
appointmentsBookedAI analizinde başarıyla tamamlanmış booking (randevu) aksiyonlarının sayısı.
smsSentAI analizinde başarıyla gönderilmiş sms aksiyonlarının sayısı.
⚠️

Dönüşüm oranı beklediğinden düşük mü? Payda totalCalls — meşgul, cevapsız ve 30 saniyeden kısa çağrılar da bu paydanın içinde. Yani “arananların yüzde kaçı ile konuşabildik” sorusunun cevabı. Cevapsız çağrılar çoksa oran düşer; bu bir hata değil, gerçeğin ta kendisi. Cevaplanma oranını ayrı görmek için completedCalls / totalCalls’a bak.

Maliyet kırılımı

Her çağrının maliyeti dört ayrı sağlayıcının toplamıdır. Rapor bunları kampanya genelinde toplar (cost.breakdown). Bir sesli çağrının maliyetini şöyle düşün: karşı taraf konuşur (tanıma), asistan düşünür (model), asistan konuşur (ses) ve tüm bunlar bir telefon hattı üzerinden akar (hat).

KalemNeyin karşılığı
sttKonuşma tanıma — karşı tarafın söylediklerini metne çeviren servis (Speech-to-Text).
llm_inputModele giren token — asistanın prompt’u, bilgi tabanı bağlamı ve o ana kadarki konuşma.
llm_outputModelin ürettiği token — asistanın söylediği her cümle.
ttsSes üretimi — metni doğal sese çeviren servis (Text-to-Speech). Uzun konuşan asistanlarda en büyük kalem genelde budur.
sipTelefon hattı — dakika bazlı hat/SIP ücreti. Görüşme uzadıkça artar.

Ayrıca cost.total (kampanyanın toplam maliyeti) ve cost.avgPerCall (çağrı başına ortalama maliyet, 6 ondalık hassasiyetle) döner.

Kırılımın toplamı, total’dan biraz düşük çıkabilir. Sağlayıcı kırılımı yalnızca cost_breakdown verisi olan çağrılardan toplanır. Çok eski çağrılarda bu ayrıntı yoksa, o çağrının maliyeti total’a yansır ama kalem kalem dağılıma girmez. Yeni çağrılarda bu fark oluşmaz.

Kalem bazında birim fiyatların (dakika/1000 karakter/1M token) hesap genelindeki güncel karşılıkları için: Maliyet ve Gecikme.

Sonuç dağılımı

outcomes nesnesi, her çağrının AI analizinden çıkan outcome (sonuç) etiketini sayar. Böylece “132 kişi ilgilendi, 40 kişi reddetti, 102 kişi açmadı” gibi bir dağılım görürsün. Etiket üretilmemiş çağrılar unknown altında toplanır. Sık görülen etiketler:

EtiketAnlamı
interestedİlgilendi (pipeline’da “değerlendiriyor”a taşınır).
appointment_scheduledRandevu oluştu (“karar aşaması”).
callback_scheduledTekrar aranma sözü verildi.
information_providedBilgi verildi, net karar yok.
rejectedReddetti (“kaybedildi”).
no_answerAçmadı.
unknownAI analizi bir etiket üretmedi.

Örnek yanıt

{
  "campaign": {
    "id": "1842",
    "name": "Ağustos Sıcak Lead'ler",
    "status": "completed",
    "createdAt": "2026-08-01T09:00:00.000Z"
  },
  "summary": {
    "totalCalls": 420,
    "completedCalls": 318,
    "successfulCalls": 205,
    "conversionRate": 49,
    "avgDuration": 138,
    "appointmentsBooked": 37,
    "smsSent": 88
  },
  "cost": {
    "total": 42.815,
    "avgPerCall": 0.10194,
    "breakdown": {
      "stt": 6.204,
      "llm_input": 9.881,
      "llm_output": 7.442,
      "tts": 14.903,
      "sip": 4.385
    }
  },
  "outcomes": {
    "interested": 132,
    "appointment_scheduled": 37,
    "callback_scheduled": 41,
    "information_provided": 27,
    "rejected": 40,
    "no_answer": 102,
    "unknown": 41
  }
}

Bu örnekte kampanya 42,815 birim maliyetle 37 randevu açmış. Çağrı başına maliyet 0,10194 — yani bir randevunun maliyeti kabaca 42,815 ÷ 37 ≈ 1,16 birim. İşte “ROI” bu iki sayının oranıdır.

📸 [Ekran görüntüsü: Kampanya detayı → ROI sekmesi, özet kartları + maliyet kırılımı grafiği]

A/B raporu

İki farklı açılış cümlesi mi deniyorsun? İki farklı asistan mı? A/B testi kampanyanın çağrılarını iki gruba (A ve B) böler; bu rapor da iki grubu yan yana koyar. Ama en kritik kısmı sadece “hangisi daha yüksek” demez — bu farkın rastlantı olup olmadığını ölçer.

Rapor yalnızca kampanyada A/B testi açıksa (abTestEnabled) çalışır; kapalıysa 400 döner. Her varyant için şu metrikler hesaplanır:

MetrikAçıklama
totalCallsO varyanttaki çağrı sayısı.
completedCallsAçılan (tamamlanan) çağrılar.
successfulCallsTamamlanmış ve en az 30 saniye süren çağrılar.
conversionRatesuccessfulCalls ÷ totalCalls × 100.
avgDurationOrtalama görüşme süresi (saniye).
totalCost / avgCostPerCallVaryantın toplam ve çağrı başına maliyeti.
sentimentPositive / sentimentNegativeAI analizinin “olumlu” / “olumsuz” işaretlediği görüşme sayısı.

Rapor ayrıca splitRatio (A ve B arasındaki trafik dağılımı), winner (dönüşüm oranı yüksek olan varyant ya da tie) ve recommendation (öneri metni) döndürür.

İstatistiksel anlamlılık

Diyelim A yüzde 43, B yüzde 62 dönüştü. B daha iyi görünüyor — ama sadece 8 çağrıya bakıyorsan bu fark tamamen şans eseri olabilir. İstatistiksel anlamlılık işte bunu ayıklar: gözlemlediğin farkın gerçek mi yoksa gürültü mü olduğunu söyler.

Rapor bunu bir iki-oran z-testi ile yapar:

En az 30 çağrı şartı

Anlamlılık hesabı yalnızca her iki varyant da en az 30 çağrıya ulaştığında yapılır (minSampleSize: 30). Altındaysa sonuç statisticallySignificant: false kalır ve “daha fazla veri gerekli” önerisi döner. Bu, küçük örneklemle yanlış karar vermeni engeller.

Ortak oran ve standart hata

İki varyantın başarılı çağrıları birleştirilerek ortak bir dönüşüm oranı (pooled rate) bulunur; buradan farkın standart hatası (se) hesaplanır. Basitçe: “iki oran arasındaki fark, tesadüfle ne kadar oynayabilirdi?“

z değeri ve yüzde 95 güven

İki dönüşüm oranı arasındaki fark, standart hataya bölünerek bir z değeri elde edilir. Bu değer eşik olan 1.96’yı aşarsa fark yüzde 95 güvenle anlamlı kabul edilir (p < 0.05). Yani “bu farkın şans eseri olma ihtimali yüzde 5’ten az”.

⚠️

“Kazanan” görünmesi yeterli değil. winner alanı her zaman doludur (dönüşümü yüksek olan varyant), ama statisticallySignificant false ise bu kazananı kalıcı bir karar için kullanma. Örneklem 30’un altındaysa ya da fark küçükse, “kazanan” bir sonraki gün rahatlıkla yer değiştirebilir. Kararı anlamlılık true olduğunda ver.

Örnek yanıt

{
  "campaign": { "id": "1907", "name": "Eylül Deneme — Açılış Cümlesi" },
  "splitRatio": 50,
  "variantA": {
    "variant": "A",
    "totalCalls": 140,
    "completedCalls": 108,
    "successfulCalls": 60,
    "conversionRate": 43,
    "avgDuration": 127,
    "totalCost": 13.9,
    "avgCostPerCall": 0.099286,
    "sentimentPositive": 52,
    "sentimentNegative": 18
  },
  "variantB": {
    "variant": "B",
    "totalCalls": 145,
    "completedCalls": 121,
    "successfulCalls": 90,
    "conversionRate": 62,
    "avgDuration": 148,
    "totalCost": 15.62,
    "avgCostPerCall": 0.107724,
    "sentimentPositive": 78,
    "sentimentNegative": 9
  },
  "winner": "B",
  "statisticallySignificant": true,
  "minSampleSize": 30,
  "recommendation": "Variant B is the winner with statistical significance (p<0.05)."
}

Burada B varyantı yüzde 62 dönüşümle, hem daha çok olumlu duygu (78) hem de anlamlı bir farkla kazanmış. Artık B’yi tüm kampanyaya güvenle yayabilirsin.

📸 [Ekran görüntüsü: A/B raporu — A ve B kartları yan yana, “İstatistiksel olarak anlamlı” rozeti]

Metrikleri doğru okumak

  • “Başarılı” = tamamlanmış + 30 saniye. Açılıp hemen kapanan çağrı başarı sayılmaz. Bu yüzden başarı sayısı, açılma sayısından her zaman düşüktür — bu doğru davranıştır.
  • Dönüşüm oranı tüm denemeler üzerinden hesaplanır, sadece açılanlar üzerinden değil. Cevapsız çağrı çoksa oran düşük görünür; asistanın performansı değil, listenin ulaşılabilirliği zayıf olabilir.
  • Maliyeti kalem kalem oku. tts çok yüksekse asistan gereğinden uzun konuşuyor olabilir; sip yüksekse görüşmeler uzun. Her ikisi de prompt ile kısaltılabilir.
  • A/B’de sabırlı ol. 30 çağrıya ulaşmadan “kazanan” ilan etme. Anlamlılık rozeti çıkana kadar test açık kalsın.

KVKK notu

Raporlar özet sayı gösterse de, altlarındaki çağrılar kayıt, transkript ve AI analizi içerir — bunlar kişisel veridir. Raporlara yalnızca kampanyanın sahibi (oturum yetkisiyle) erişebilir; başka bir hesabın kampanyası 404 döner. Aradığın kişi görüşmede “aramayın / verimi silin” derse, asistan onu otomatik olarak arama listesinden çıkarır ve sonraki kampanyalara dahil etmez.

Sorun giderme

BelirtiOlası neden / çözüm
ROI raporu tamamen sıfırKampanyada henüz çağrı yok ya da çağrılar başladı ama tamamlanmadı.
Sonuç dağılımı / randevu / duygu boşAI Çağrı Analizi kapalı (Premium). Maliyet ve dönüşüm yine de dolu olur.
Maliyet kırılımı toplamı, total’dan düşükEski çağrılarda cost_breakdown yok; maliyet toplama girer ama kalem dağılımına girmez.
appointmentsBooked 0 ama randevu aldınızAsistana booking aksiyonu bağlı değil ya da AI analizi randevuyu yakalamadı.
A/B raporu 400 hatasıKampanyada A/B testi açık değil. A/B testini etkinleştir.
statisticallySignificant hep falseBir varyant henüz 30 çağrıya ulaşmadı; testi açık tut.
Kazanan var ama anlamlılık yokFark rastlantı olabilir; örneklem büyüyene kadar karar verme.
Dönüşüm oranı çok düşükÇoğu çağrı 30 saniyenin altında (meşgul/cevapsız). Listeyi ve arama saatlerini gözden geçir.

İlgili