
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_idvaluecurrencytaxshippingcouponitems
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_idanalytics_purchase_sent_at
tutulabilir.
Süreç:
- Sipariş PAID olur.
- Sistem
analytics_purchase_sent_atkontrol eder. - Null ise purchase gönderilir.
- Başarılıysa timestamp kaydedilir.
- 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_idgerç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:
- Paid orders: backend.
- Tracked purchases: GA4.
- 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.
