Toplantı Planla
Analytics & TrackingAnalyticsTrackingGA4

GA4 Purchase Event Neden Çift Sayılır? Duplicate Purchase Sorunu Nasıl Çözülür?

GA4 purchase event neden iki kez çalışır? Duplicate purchase nedenlerini, transaction_id kullanımını, GTM ve backend kaynaklı hataları adım adım inceleyin.

Reliefers DigitalReliefers DigitalYazar20 Ağustos 20264 Dakika
GA4 Purchase Event Neden Çift Sayılır? Duplicate Purchase Sorunu Nasıl Çözülür?

E-ticaret tracking altyapılarında en kritik hatalardan biri aynı siparişin Google Analytics 4'e birden fazla kez gönderilmesidir.

Bu hata doğrudan revenue, transaction, conversion rate, ROAS ve campaign attribution verilerini bozar.

GA4 purchase event nedir?

GA4'te tamamlanan bir e-ticaret işlemi purchase eventiyle ölçülür.

Event içerisinde genellikle:

  • transaction_id
  • value
  • currency
  • tax
  • shipping
  • coupon
  • items

gibi bilgiler bulunur.

Purchase event neden çift çalışır?

En yaygın sebep aynı satın alma işleminin birden fazla kaynaktan gönderilmesidir.

Örneğin:

Frontend → GTM → GA4 Purchase

aynı zamanda:

Backend → Measurement Protocol → GA4 Purchase

çalışıyorsa aynı sipariş iki farklı event olarak Analytics'e gidebilir.

1. Thank you sayfasının tekrar açılması

Purchase event çoğu zaman sipariş başarı sayfası açıldığında çalıştırılır.

Kullanıcı sayfayı refresh ederse, geri gelip yeniden açarsa veya tarayıcı geçmişinden tekrar girerse purchase event yeniden çalışabilir.

Bu nedenle “success page görüntülendi = yeni purchase oluştu” mantığı güvenilir değildir.

2. GTM trigger iki kere çalışıyor olabilir

Purchase tag hem custom event hem page view trigger üzerinden çalışıyor olabilir veya aynı dataLayer eventi iki kez push edilmiş olabilir.

3. SPA / React / Next.js lifecycle problemleri

Modern storefront'larda component yeniden mount olabilir, route değişiminde tekrar render olabilir veya hydration sırasında farklı davranabilir.

Tracking sistemi UI lifecycle'ından mümkün olduğunca ayrılmalıdır.

4. Frontend ve backend aynı purchase'ı gönderiyor olabilir

Server-side tracking'e geçerken eski browser-side tracking kaldırılmadan backend tracking açılırsa duplicate riski oluşur.

transaction_id neden önemli?

Her işlem için benzersiz ve stabil bir transaction ID kullanılmalıdır.

Yanlış:

transaction_id: randomUUID()

Doğru yaklaşım:

transaction_id: order.id

veya sisteminizdeki benzersiz sipariş numarasıdır.

Payment success ile order success aynı şey mi?

Her zaman değil.

Ödeme sağlayıcısından “3D Secure tamamlandı” cevabı almak ile backend'de siparişin gerçekten PAID durumuna geçmesi farklı olaylardır.

Sağlam tracking mimarisinde purchase event mümkün olduğunca doğrulanmış ticari olaya bağlanmalıdır.

Backend purchase tracking nasıl daha güvenli hale getirilir?

Event üretimi idempotent olmalıdır.

Örneğin veritabanında:

  • order_id
  • analytics_purchase_sent_at

tutulabilir.

Süreç:

  1. Sipariş PAID olur.
  2. Sistem analytics_purchase_sent_at kontrol eder.
  3. Null ise purchase gönderilir.
  4. Başarılıysa timestamp kaydedilir.
  5. Callback yeniden gelse bile ikinci purchase gönderilmez.

GA4 ve backend sipariş sayısı neden birebir aynı olmayabilir?

Duplicate problemi yokken bile consent, ad blocker, network failure, analytics configuration, attribution, timezone ve event processing gibi faktörlerle küçük farklar olabilir.

İşletmenin finansal source of truth'u Analytics değildir.

Duplicate purchase audit checklist

  • Purchase hangi koddan gönderiliyor?
  • GTM purchase tag kaç kez çalışıyor?
  • dataLayer purchase kaç kez push ediliyor?
  • Browser tracking var mı?
  • Measurement Protocol kullanılıyor mu?
  • Server-side GTM var mı?
  • Payment callback purchase üretiyor mu?
  • Success page purchase üretiyor mu?
  • transaction_id gerçekten benzersiz mi?
  • Refresh sonrası event tekrar gidiyor mu?
  • SPA route değişiminde event yeniden çalışıyor mu?
  • Retry mekanizması aynı event'i tekrar üretiyor mu?
  • Event idempotency var mı?

GA4'te duplicate problemine transaction identity açısından bakın

transaction_id, e-ticaret olayının ticari kimliğidir. En güvenli yaklaşım sipariş sistemiyle aynı stabil identifier'ı kullanmaktır.

gtag('event', 'purchase', {
  transaction_id: 'ORDER-12345',
  value: 2499.90,
  currency: 'TRY'
});

UI lifecycle'dan üretilen random ID, refresh sonrası değişirse aynı sipariş yeni transaction gibi ölçülebilir.

Frontend purchase event ne zaman risklidir?

SPA storefront'larda:

  • component remount,
  • hydration,
  • route transition,
  • browser back/forward cache

gibi durumlar effect tabanlı tracking'i tekrar tetikleyebilir.

Bu nedenle useEffect(() => sendPurchase()) benzeri kod, tek başına güvenilir transaction guarantee değildir.

Client-side guard ile backend idempotency aynı şey değildir

localStorage içine “bu siparişi gönderdim” yazmak yardımcı olabilir ama güvenlik garantisi değildir.

Sorunlar:

  • başka cihaz,
  • incognito,
  • storage temizleme,
  • callback retry,
  • farklı browser.

Gerçek idempotency ticari order state'e yakın katmanda kurulmalıdır.

Source of truth ve analytics truth

Üç sayı ayrı tutulmalıdır:

  1. Paid orders: backend.
  2. Tracked purchases: GA4.
  3. Attributed purchases: channel reports.

Capture rate:

GA4 Purchase Capture Rate =
unique GA4 transaction_id / backend paid order

zaman içinde izlenebilir.

Duplicate tespit sorgusu nasıl düşünülmeli?

SELECT
  transaction_id,
  COUNT(*) AS purchase_count
FROM purchase_events
GROUP BY transaction_id
HAVING COUNT(*) > 1;

Gerçek export şeması farklı olabilir; önemli olan order identity üzerinden duplicate adayları bulmaktır.

Test matrisi

Senaryo Beklenen
Thank-you refresh Yeni purchase yok
Back/forward Yeni purchase yok
Payment retry Yeni logical purchase yok
Server worker retry Aynı transaction
Browser + server Tek ticari işlem
Partial refund Purchase yeniden gönderilmez

DebugView neden yeterli değildir?

Production duplicate sorununun:

  • hangi order'da,
  • hangi kaynaktan,
  • hangi retry nedeniyle

oluştuğunu application logs ve order-level reconciliation ile görmek gerekir.

Event schema versioning

schema_version: 3
source: storefront

gibi alanlar deployment'lar arasında event contract değişimini izlemeyi kolaylaştırır.

Gerçek çözüm: commerce event bus

OrderPaid
→ Analytics Adapter → GA4
→ Ads Adapter → Meta
→ Ads Adapter → Google Ads
→ Warehouse

Bu, her platform için ayrı ayrı purchase mantığı yazılmasını önler ve duplicate riskini azaltır.

Order-level reconciliation örneği

Günlük 500 sipariş varsa yalnız “GA4 493 gösteriyor” demek yeterli değildir.

Eşleme tablosu:

Order Backend GA4 Durum
1001 paid 1 event OK
1002 paid 2 event duplicate
1003 paid 0 event missing

Bu sayede capture rate ile duplicate rate birbirinden ayrılır.

Release sonrası kontrol

Checkout veya thank-you page değişikliğinden sonra:

  • purchase count,
  • unique transaction_id,
  • duplicate transaction count,
  • revenue delta

otomatik smoke test/monitoring ile izlenmelidir. Analytics regresyonu günler sonra raporda fark edilmemelidir.

Sonuç

GA4 duplicate purchase problemi yalnızca Analytics ayarı değildir.

Çoğu zaman uygulamanın event mimarisindeki bir problemdir.

Reliefers olarak e-ticaret tracking projelerinde ödeme, sipariş, frontend ve backend event akışlarını birlikte ele alıyoruz.

Bir Sonraki Büyüme Adımınızı Birlikte Kuralım

Yeni bir e-ticaret altyapısı, özel yazılım veya daha güçlü bir dijital pazarlama yönetimi planlıyorsanız mevcut durumu ve hedefinizi konuşalım.