Ana içeriğe geç
Kesit Power BI
İleri · Müşteri Analitiği

Müşteri analitiği: yeni, geri dönen, kayıp, kohort, RFM

Müşteri yaşam döngüsünü ölçen uzun DAX kalıpları ve her birinin adım adım mantığı.

Uygulamada aç, 11 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Müşteri yaşam döngüsü soruları

SoruKalıpAnahtar fonksiyon
Bu ay kaç yeni müşteri geldi?Bu dönem − (dönem öncesi)EXCEPT
Kaçı geri döndü?Bu dönem ∩ (dönem öncesi)INTERSECT
Kaçını kaybettik?(önceki 12 ay) − bu dönemDATESINPERIOD + EXCEPT
İlk ayın müşterileri ne kadar süre kalıyor?Kohort matrisiHesaplanmış sütunlar + DISTINCTCOUNT
Hangi müşteri değerli, hangisi risk altında?RFM skoru ve segmentiDATEDIFF, SWITCH(TRUE())

Ortak teknik: tarih filtresini değiştirmek

Bu kalıpların hepsinde “bu dönem”in yanında “dönemden önceki her şey” ya da “son 12 ay” gibi ikinci bir zaman penceresi gerekir. Tarih tablosu işaretli olduğu için Tarih[Tarih] < DonemBasi filtresi Yıl, Ay gibi diğer tarih filtrelerinin yerine geçer. Tablo işaretli olmasaydı REMOVEFILTERS(Tarih) eklemen gerekirdi.

Geri Dönen Müşteri =
VAR DonemBasi = MIN(Tarih[Tarih])
VAR BuDonem =
    CALCULATETABLE(VALUES(Satislar[MusteriNo]), Satislar[Durum] <> "İptal")
VAR Onceki =
    CALCULATETABLE(
        VALUES(Satislar[MusteriNo]),
        Tarih[Tarih] < DonemBasi,
        Satislar[Durum] <> "İptal"
    )
RETURN COUNTROWS(INTERSECT(BuDonem, Onceki))

Kohort analizi

Kohort = aynı ayda ilk alışverişini yapan müşteriler. İki hesaplanmış sütun gerekir:

-- Musteriler tablosunda:
IlkSiparis = CALCULATE(MIN(Satislar[Tarih]), Satislar[Durum] <> "İptal")
KohortAy = FORMAT(Musteriler[IlkSiparis], "yyyy-MM")
-- Satislar tablosunda:
KohortAyFarki = DATEDIFF(RELATED(Musteriler[IlkSiparis]), Satislar[Tarih], MONTH)

Hesaplanmış sütunda CALCULATE bağlam geçişi yapar: müşteri satırı filtreye dönüşür ve yalnızca o müşterinin siparişleri arasında en küçük tarih bulunur. Matris: satırlar Musteriler[KohortAy], sütunlar Satislar[KohortAyFarki], değer “Kohort Tutma %”.

RFM

R (Recency, yenilik), F (Frequency, sıklık), M (Monetary, parasal değer). Her müşteri üç boyutta 1–5 puan alır; puan kombinasyonları iş dilinde segmentlere çevrilir. Ayrıntılı ölçüler Measure Lab'nda, sonuçlar RFM raporu'nda.

Ölçü mü, sütun mu?Müşteri segmentini hesaplanmış sütun yaparsan dilimleyicide ve eksende kullanabilirsin ama yenileme anında donar. Ölçü yaparsan seçili döneme göre değişir ama eksene konamaz; o zaman bağlantısız bir segment tablosu ve sayım ölçüsü gerekir (RFMSegmentleri kalıbı).
Uzmanlaş

Aktif müşteri: tanımı sen seçersin

Pazarlama müdürü soruyor: “Şu anda kaç aktif müşterimiz var?” “Aktif” bir iş tanımıdır; raporu yazan kişi onu açıkça seçip belgeye yazar. Anadolu Market'te kullanılan tanım şu: son 90 günde en az bir iptal edilmemiş siparişi olan müşteri.

Aktif Müşteri (90 Gün) =
COUNTROWS(
    CALCULATETABLE(
        VALUES(Satislar[MusteriNo]),
        DATESINPERIOD(Tarih[Tarih], MAX(Tarih[Tarih]), -90, DAY),
        Satislar[Durum] <> "İptal"
    )
)

Motor bunu nasıl değerlendirir?

  1. MAX(Tarih[Tarih]) dış bağlamda hesaplanır: 2024 hücresinde 31.12.2024.
  2. DATESINPERIOD geriye 90 günlük bir liste döndürür: 3 Ekim – 31 Aralık 2024.
  3. CALCULATETABLE bu listeyi Tarih[Tarih] filtresinin yerine koyar; tarih tablosu işaretli olduğu için Yıl filtresi de kalkar. Hücre artık “son 90 günde alışveriş yapanlar”ı sayar.
HücreMüşteri Sayısı (dönem içinde)Aktif Müşteri (90 Gün)
20223228
20237755
202412389
2024-Ç49089

2024-Ç4'teki 1 kişilik fark öğreticidir: çeyrek 92 gün, pencere 90 gün. 1–2 Ekim'de alışveriş yapıp sonra gelmeyen müşteri çeyreğin müşterisidir ama “aktif” değildir.

Kenar durumlar

  • Toplam satırı: Kategori matrisinde satırlar 32, 32, 34, 5, 50, 46, 30 gösterir. Toplamları 229 eder, ama toplam satırı 89 der. Bir müşteri birden çok kategoriden alır. Bu doğrudur; araç ipucunda (tooltip) açıkla.
  • Gün sayımı: -90, DAY son günü de sayar ve tam 90 gün verir. “Son alımdan bu yana ≤ 90 gün” yazarsan 91 gün sayarsın: 2024 sonunda 90 müşteri çıkar, ölçü 89 der. Tanımı veri sözlüğüne yaz.
  • TODAY() tuzağı: Çapayı TODAY() yaparsan veri 31.12.2024'te bittiği hâlde pencere bugünden geriye kayar ve sonuç boş gelir. Yenileme bir gün gecikirse de sayı sessizce düşer. Çapa her zaman verinin son günü olmalı: CALCULATE(MAX(Satislar[Tarih]), REMOVEFILTERS()).

Kayıp (churn) tanımını seçmek

TanımNasıl ölçülür?Ne zaman doğru?
Sabit eşikSon alımdan bu yana X günden fazla geçtiAbonelik olmayan perakende; kampanya listesi
Dönem karşılaştırmaÖnceki 12 ayda vardı, bu dönemde yok ([Kayıp Müşteri])Yıllık yönetim raporu, bütçe
Olay tabanlıÜyelik iptali, sözleşme bitişiAbonelik işi; olay verisi gerekir

Sabit eşiği tahminle seçme. Müşterilerin iki alışveriş arasında normalde ne kadar beklediğine bak. Aşağıdaki sorgu bunu motorda hesaplar:

EVALUATE
VAR T =
    ADDCOLUMNS(
        CALCULATETABLE(VALUES(Satislar[MusteriNo]), Satislar[Durum] <> "İptal"),
        "Ilk", CALCULATE(MIN(Satislar[Tarih]), Satislar[Durum] <> "İptal"),
        "Son", CALCULATE(MAX(Satislar[Tarih]), Satislar[Durum] <> "İptal"),
        "N", CALCULATE(DISTINCTCOUNT(Satislar[SiparisNo]), Satislar[Durum] <> "İptal")
    )
VAR Tekrar = ADDCOLUMNS(FILTER(T, [N] > 1), "Ara", DIVIDE(DATEDIFF([Ilk], [Son], DAY), [N] - 1))
RETURN
    ROW(
        "Medyan", MEDIANX(Tekrar, [Ara]),
        "Yuzde90", PERCENTILEX.INC(Tekrar, [Ara], 0.9)
    )

Sonuç: tekrar alan 127 müşteride medyan aralık 83 gün, %90'lık değer 155 gün (%80'lik değer 136). 90 günlük bir “kayıp” eşiği normal davranan müşterilerin neredeyse yarısını kayıp sayar; 180 gün, %90'ın olağan aralığının dışında kalır. 2024 sonunda son alımı 180 günden eski müşteri sayısı 27. Rapor hâli Vaka: müşteri kaybı dersinde.

Anti-kalıp: pencere uyuşmazlığı

“Önceki 12 ayda vardı, bu dönemde yok” mantığını çeyrek kırılımına koyarsan şu olur: 2024 yıl hücresinde oran %16,9 (77 müşterinin 13'ü). Çeyreklerde ise %30–39 görünür. Çünkü 12 aylık bir geçmiş, 3 aylık bir gözlemle karşılaştırılıyor. Üç ay alışveriş yapmamak kayıp değildir. Kural: gözlem penceresi karşılaştırma penceresinden kısa olmamalı; olursa ölçü BLANK dönsün.

Korumalı Yıllık Kayıp % =
VAR Gun = COUNTROWS(Tarih)
VAR DonemBasi = MIN(Tarih[Tarih])
VAR Onceki =
    CALCULATETABLE(
        VALUES(Satislar[MusteriNo]),
        DATESINPERIOD(Tarih[Tarih], DonemBasi - 1, -12, MONTH),
        Satislar[Durum] <> "İptal"
    )
VAR Simdi = CALCULATETABLE(VALUES(Satislar[MusteriNo]), Satislar[Durum] <> "İptal")
RETURN
    IF(Gun >= 365, DIVIDE(COUNTROWS(EXCEPT(Onceki, Simdi)) + 0, COUNTROWS(Onceki)))

+ 0 önemli: boş kümede COUNTROWS BLANK döner ve 2023'te (2022 müşterilerinin hepsi geri döndü) oran %0 yerine boş görünür.

CLV: müşteri yaşam boyu değeri

Finans direktörü soruyor: “Yeni bir müşteri kazanmak için en fazla ne harcayabiliriz?” Cevap CLV'dir (Customer Lifetime Value). Tek bir doğru formül yok. Olasılıksal modeller Python ya da Fabric not defterinde kurulur ve sonucu tabloya yazılır; DAX tarafında üç yaklaşım var.

YaklaşımHesapGüçlü yanıZayıf yanı
TarihselBugüne kadarki brüt kâr ÷ müşteriKesin, denetlenebilirGeleceği söylemez; yeni müşteriyi küçük gösterir
Basit formülYıllık müşteri başı kâr × beklenen ömür (≈ 1 ÷ yıllık kayıp oranı)Anlaşılır, tek ölçüKayıp oranına çok duyarlı
Kohort temelliHer kohortun ay ay birikimli kârıEn dürüst eğriUzun geçmiş ister
Birikimli Müşteri Kârı =
VAR Son = MAX(Tarih[Tarih])
RETURN
    DIVIDE(
        CALCULATE([Brüt Kâr], REMOVEFILTERS(Tarih), Tarih[Tarih] <= Son),
        CALCULATE([Müşteri Sayısı], REMOVEFILTERS(Tarih), Tarih[Tarih] <= Son)
    )

Basit CLV =
VAR KarMusteri = DIVIDE([Brüt Kâr], [Müşteri Sayısı])
VAR Onceki = CALCULATE([Müşteri Sayısı], DATESINPERIOD(Tarih[Tarih], MIN(Tarih[Tarih]) - 1, -12, MONTH))
VAR Kayip = IF(COUNTROWS(Tarih) >= 365, DIVIDE([Kayıp Müşteri] + 0, Onceki))
VAR Omur = MIN(5, DIVIDE(1, Kayip))
RETURN IF(Kayip > 0, KarMusteri * Omur)

2024 için: müşteri başı yıllık brüt kâr 2.346 ₺, kayıp oranı %16,9. Ömür 1 ÷ 0,169 ≈ 5,9 yıl çıkar; 5 yıllık tavanla CLV 11.730 ₺ olur. Birikimli kâr ise 2024 sonunda müşteri başı 3.354 ₺ (2023 sonunda 2.176 ₺).

  • Kayıp oranı 0: 2023'te 1 ÷ 0 sonsuz ömür demektir. IF(Kayip > 0, …) bu hücreyi boş bırakır. Tavan (5 yıl) bir iş varsayımıdır; ölçü açıklamasına yaz.
  • Tek sayı verme: Bir aralık sun: ömür 3 yılsa 7.038 ₺, 5 yılsa 11.730 ₺. Karar alt uçla verilir.
  • Segment farkı: Tüm dönemde müşteri başı brüt kâr Premium'da 5.866 ₺, Bireysel'de 1.961 ₺. Ortalama bir CLV, iki çok farklı kitleyi tek sayıda saklar.

Kohort matrisi: üretimde üç tuzak

1. Sağdan sansür

Son kohortların ileri ayları henüz yaşanmadı. [Kohort Tutma %] ölçüsü 12. ay sütununun toplamında %19,1 der (136 müşterinin 26'sı). Ama Ocak 2024'ten sonraki kohortlar 12. aya ulaşmadı; paydada olmamalılar. Yalnızca olgun kohortlarla oran %33,8 olur. 6. ayda fark %31,6'ya karşı %38,1.

Olgun Kohort Tutma % =
VAR Ay = SELECTEDVALUE(Satislar[KohortAyFarki])
VAR SonTarih = CALCULATE(MAX(Satislar[Tarih]), REMOVEFILTERS())
VAR Olgun =
    FILTER(
        VALUES(Musteriler[KohortAy]),
        VAR Ilk = CALCULATE(MIN(Musteriler[IlkSiparis]))
        RETURN NOT ISBLANK(Ilk) && DATEDIFF(Ilk, SonTarih, MONTH) >= Ay
    )
VAR Aktif = CALCULATE(DISTINCTCOUNT(Satislar[MusteriNo]), Satislar[Durum] <> "İptal", REMOVEFILTERS(Tarih), Olgun)
VAR Boyut =
    CALCULATE(
        DISTINCTCOUNT(Satislar[MusteriNo]),
        Satislar[KohortAyFarki] = 0, Satislar[Durum] <> "İptal", REMOVEFILTERS(Tarih), Olgun
    )
RETURN IF(NOT ISBLANK(Ay) && Ay >= 0, DIVIDE(Aktif, Boyut))

2. Negatif ay farkı

Matriste −6 ile −1 arası sütunlar görünür. Kohort, ilk iptal edilmemiş siparişten hesaplanır. Ondan önce iptal edilmiş siparişi olan müşteri negatif fark üretir. Görsel filtresine KohortAyFarki ≥ 0 koy ve bu kararı belgeye yaz.

3. Küçük kohortlar

2023-09 kohortunda 1 müşteri var; hücreleri ya %100 ya %0 görünür. Kohort büyüklüğünü ilk sütuna koy, 5'ten küçük kohortları gri yap ya da çeyreklik kohorta geç. Kohort büyüklüğü ölçüsünde KohortAyFarki = 0 filtresi sütundan gelen ay farkının üzerine yazar; değer satırda sabit kalır.

RFM'yi üretime almak

Uygulamadaki [RFM Skoru] sabit eşikler kullanıyor (ör. son 12 ay satışı 12.000 ₺ ve üstü → M = 5). İki seçenek var:

Sabit eşik yıllar arası kıyası anlamlı tutar (“Şampiyon” her yıl aynı ölçüt) ama dağılım dengesiz olabilir: 2024'te 123 müşteriden yalnızca 16'sı M ≥ 12.000. Yüzdelik eşik her puana yaklaşık eşit müşteri koyar ama dağılım her yıl yeniden bölündüğü için yıl kıyası zayıflar. 2024 net satışında %20'lik sınırlar 2.030 / 3.735 / 5.372 / 9.305 ₺. Segment dağılımı 2023 sonundan 2024 sonuna şöyle değişti: Şampiyon 17 → 27, Potansiyel sadık 37 → 75, Kaybedilmiş 0 → 13.

Ölçü mü, anlık görüntü mü?

Ölçü dilimleyiciye tepki verir; keşif için iyidir. Ama CRM ekibi “1 Kasım'da Şampiyon olanlara kampanya gönderdik” dediğinde rapor aynı listeyi yeniden üretebilmelidir. Bunun için her ay sonunda bir anlık görüntü tablosu (Ay, MusteriNo, Segment) yazılır; segment geçişleri de bu tablodan basit bir sayımla çıkar. Milyonlarca müşteride ölçü her hücrede müşteri başına üç CALCULATE çalıştırır; o ölçekte anlık görüntü zorunludur (DAX optimizasyonu dersi).

Yayın öncesi kontrol listesiTanımlar veri sözlüğünde mi? Çapa verinin son günü mü? Kayıp eşiği aralık dağılımına dayanıyor mu? Kohortta olgun payda, büyüklük sütunu ve ay farkı ≥ 0 filtresi var mı? CLV aralık ve varsayımlarıyla mı sunuluyor? Kampanya segmentleri anlık görüntüden mi?
Alıştırmalara geç (11)