Single Page Uygulamalarında (SPA) GA4, Search Console ve CDP Event Yönetimi: SDK ve Mimari Rehberi
SPA Mimarisi ve Veri Analytics Dünyasındaki Sessiz Kriz
Modern web geliştirmede React, Next.js, Vue ve Nuxt gibi Single Page Application (SPA) mimarileri; hız, akıcı kullanıcı deneyimi (UX) ve uygulama benzeri hissi sebebiyle standart hale geldi. Ancak geleneksel veri analitiği, Müşteri Veri Platformları (CDP) ve arama motoru indeksleme altyapıları, doğası gereği sayfa yenilenmesine (full page reload) göre tasarlanmıştır.
Google Analytics 4 (GA4) raporlarına baktığınızda ziyaretçilerin sitede tek bir sayfada kalıp ayrıldığını (0 saniye oturum süresi), buna karşın Google Search Console (GSC) tarafında binlerce alt sayfanızın sorunsuz indekslendiğini görüyorsanız; sorun içerik kalitenizde değil, SPA Event & SDK mimarinizdedir.
Bu rehberde, GA4 ve Search Console okuma verilerindeki uyumsuzluklardan başlayarak; CDP (Meiro, Segment, RudderStack vb.) entegrasyonlarında yapılan hayati SDK hatalarını ve 2026 standartlarında uygulanması gereken mimari çözümleri inceliyoruz.
1. GA4 ve Search Console Sinyallerini Doğru Okumak
Bir SPA projesinde analitik altyapısının bozuk olduğunu gösteren temel GA4 ve Search Console sinyalleri şunlardır:
Search Console Sinyali: İndeks Var, Sayfa Trafiği Yok
Search Console URL Inspection veya Performans raporunda /urun/123 veya /hizmetler/cdp-danismanligi gibi dinamik rotaların indekslendiği görülür. Ancak Googlebot sayfayı tararken JavaScript execution limitlerine takılırsa veya hydration öncesi HTML'i tararsa, sayfa üzerindeki istemci tabanlı (client-side) GA4/CDP etiketleri hiç çalışmaz.
GA4 Sinyali: "Sanal Sayfa" (Virtual Pageview) Kopukluğu
Standart GTM veya GA4 gtag.js entegrasyonlarında page_view eventi sayfa ilk yüklendiğinde otomatik atılır. Kullanıcı SPA içinde bağlantılara tıklayıp URL domain.com/page-a'dan domain.com/page-b'ye geçtiğinde:
- Eğer Otomatik Gelişmiş Ölçüm (Enhanced Measurement) Açıksa: HTML
history.pushStateolaylarında bazen çift (duplicate)page_view, bazen de parametreleri eksik (ör.page_locationveyapage_titlegüncellenmemiş) eventler atılır. - Eğer Manuel Tetikleniyorsa: Sayfa geçişinde bileşenler unmount/mount olurken listener birikmesi yaşanır ve kullanıcı 5. sayfaya geldiğinde tek tıkta 5 tane
page_viewbirden tetiklenir.
| Analitik Göstergesi | Geleneksel Web (MPA) | Hatalı Kurgulanmış SPA | İdeal SPA Mimarisi |
|---|---|---|---|
| Sayfa Geçiş Algısı | Full Document Reload | pushState / popstate (Gözden kaçan) |
Centralized Router Middleware Hook |
GA4 page_view Tetiklenmesi |
Sunucu Yanıtı ile %100 Doğru | Çift / Eksik / Parametresiz | Deduped & State-synchronized |
| SDK Bellek Yönetimi | Her sayfada bellek temizlenir | Bellekte biriken event listener'lar | Immutable Client SDK Context |
Identity Stitching (user_id) |
Cookie tabanlı sorunsuz | Oturum kapansa da bellekte kalan ID | Explicit Reset & Token Refresh |
2. CDP ve SDK Yönetiminde En Sık Yapılan 4 Hayati Hata
CDP (Customer Data Platform) sistemlerinin ana hedefi, kullanıcının omnichannel davranışlarını tek bir tutarlı profil altında birleştirmektir (Identity Stitching). Ancak SPA mimarilerinde istemci taraflı (client-side) SDK kullanımı bazı kritik hatalara yol açar:
flowchart TD
subgraph SPA Client Execution
A[Kullanıcı Route Değiştirir] --> B{Router Event Listener}
B -->|Temizlenmemiş Handler| C[N Adet Duplicate Event]
B -->|Async SDK Yüklenmedi| D[Event Drop / Kayıp Profil]
B -->|Çıkış Yapıldı Ama Reset Edilmedi| E[Identity Leakage / Veri Sızıntısı]
end
C --> F[GA4 & CDP Veri Bozulması]
D --> F
E --> F
Hata 1: Profil Sızıntısı (Identity Leakage & Stale State)
SPA yapılarında window nesnesi veya global JavaScript belleği sayfa değişse de sıfırlanmaz. A Kullanıcısı oturum açtığında SDK'ya cdp.identify("user_A") gönderilir. Kullanıcı çıkış yaptığında tarayıcı yönlendirmesi pushState ile yapıldığı için SDK belleğinde hâlâ Kullanıcı A'nın ID'si ve nitelikleri (traits) kalır. Ardından B Kullanıcısı giriş yaptığında veya anonim gezindiğinde, B'nin tüm event'leri A'nın CDP profiline yazılır.
[!WARNING] Güvenlik ve KVKK/GDPR Riski: Çıkış (logout) işlemlerinde
cdp.reset()veyacdp.clearIdentity()fonksiyonunu çağırmamak, iki farklı kullanıcının kişisel verilerinin CDP üzerinde birleşmesine ve ciddi kişisel veri ihlallerine yol açar.
Hata 2: Bellekte Biriken Listener'lar (Memory Leaks & Event Multiplication)
React useEffect veya Vue mounted yaşam döngülerinde router değişimlerini dinleyen event listener'lar eklenir. Eğer bu listener'lar unmount anında temizlenmezse (cleanup function), kullanıcı sitede gezindikçe bellekte aynı event dinleyiciden onlarca birikir. Sonuç: Kullanıcı bir butona bastığında CDP ve GA4'e aynı event 10 kere gönderilir.
Hata 3: Yarış Koşulları (Race Conditions & Async Hydration)
Next.js app dizini gibi modern yapılarda SDK'lar next/script ile strategy="lazyOnload" veya async olarak yüklenir. Kullanıcı sayfa açılır açılmaz bir CTA butonuna tıklarsa, CDP SDK'sı henüz window.cdp nesnesini initialize etmediği için event undefined hatası alır veya kaybolur.
Hata 4: GSC Bot Trafiğinin CDP Segmentasyonunu Bozması
Googlebot veya diğer arama motoru botları SPA sayfalarınızı tararken JavaScript çalıştırdığında, CDP SDK'ları bu botları "Gerçek Ziyaretçi" olarak algılayıp binlerce sahte anonim profil oluşturur. Bu durum CDP maliyetlerini (MTU - Monthly Tracked Users) yükseltir ve dönüşüm oranlarını (CR) düşürür.
3. SPA Mimarisi İçin 2026 Standartlarında Çözüm ve Öneriler
ONMARTECH olarak Single Page Application projelerinde uyguladığımız ve %100 veri doğruluğu sağlayan mimari prensipler:
Çözüm 1: Merkezi Router Event Middleware (Next.js / React Router)
Event tetiklemelerini tekil bileşenlerin (component) içinden çıkarıp merkezi bir Router Middleware katmanına bağlayın.
Örnek Next.js (App Router) Merkezi Event Tracking Entegrasyonu:
// components/AnalyticsProvider.tsx
'use client';
import { usePathname, useSearchParams } from 'next/navigation';
import { useEffect, useRef } from 'react';
export function AnalyticsProvider({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const searchParams = useSearchParams();
const lastTrackedUrl = useRef<string>('');
useEffect(() => {
const currentUrl = `${pathname}${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;
// Duplicate sayfa geçişini engelle (Deduplication)
if (lastTrackedUrl.current === currentUrl) return;
lastTrackedUrl.current = currentUrl;
// Bot Kontrolü
const isBot = /bot|googlebot|crawler|spider|robot|crawling/i.test(navigator.userAgent);
if (isBot) return;
// GA4 & CDP Sanal Sayfa Bildirimi
if (typeof window !== 'undefined') {
// GA4 Virtual Pageview
window.gtag?.('config', process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!, {
page_path: currentUrl,
page_title: document.title,
});
// CDP SDK Event
window.cdp?.track('page_view', {
url: currentUrl,
title: document.title,
referrer: document.referrer,
route_type: 'spa_soft_navigation'
});
}
}, [pathname, searchParams]);
return <>{children}</>;
}
Çözüm 2: İstemci SDK Katmanından Edge Relay (Server-Side) Katmanına Geçiş
İstemci tarafında çalışan onlarca SDK (GA4, CDP, Meta Pixel, LinkedIn Insight) yerine, tarayıcıdan yalnızca tek bir lightweight event stream çıkarın. Bu akışı Cloudflare Workers veya Vercel Middleware gibi bir Edge katmanında karşılayıp sunucu tarafında (Server-Side) hedeflere dağıtın.
architecture-beta
group client(browser)[SPA Browser Client]
group edge(cloud)[Edge Computing Layer]
group destinations(analytics)[Destinations]
service app(server)[Next.js / React App] in client
service sdk(javascript)[Single Unified SDK] in client
service worker(cloud)[Cloudflare Edge Relay] in edge
service ga4(database)[GA4 Measurement Protocol] in destinations
service cdp(database)[Meiro / Segment CDP] in destinations
service meta(database)[Meta CAPI] in destinations
app --> sdk
sdk -- "HTTP POST (JSON Event)" --> worker
worker -- "Validates & Enriches" --> ga4
worker -- "Identity Stitching" --> cdp
worker -- "Hashed Conversions" --> meta
Edge Relay Yaklaşımının Avantajları:
- AdBlocker Engelini Aşar: Event'ler birinci taraf domaininiz üzerinden (
analytics.siteniz.com/api/v1/event) gönderildiği için reklam engelleyicilerden etkilenmez. - Sıfır SDK Bellek Sızıntısı: İstemci tarafında karmaşık CDP SDK'ları çalışmadığı için bellek birikmesi veya profil sızıntısı yaşanmaz.
- Mükemmel LCP & CWV Performansı: Sayfa yüküne eklenen 300-500 KB'lık JavaScript kütüphaneleri elenir, Core Web Vitals skorları yükselir.
Çözüm 3: Kimlik Yönetimi (Identity Management) Protokolü
SPA uygulamanızda oturum yönetimi için kesin bir protokol tanımlayın:
// auth/authService.ts
export const handleUserLogout = () => {
// 1. Yerel depolamayı temizle
localStorage.removeItem('auth_token');
// 2. CDP SDK Kimliğini Sıfırla (Çok Kritik!)
if (window.cdp) {
window.cdp.reset(); // Tüm biriken anonim ve tanımlı id'leri sıfırlar
}
// 3. GA4 user_id temizliği
window.gtag?.('config', process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID!, {
user_id: null
});
// 4. SPA Yönlendirmesi
router.push('/login');
};
Sonuç: SPA Veri Mimarisi Bir Seçenek Değil, Zorunluluktur
2026'da veri odaklı karar alan markalar için SPA mimarisi üzerinde doğru bir analitik ve CDP kurgusu kurmak, pazarlama bütçelerinin doğru optimizasyonu için en kritik yatırımdır.
GA4'te kaybolan sanal sayfalar, Search Console'da görünüp analitikte sıfır çeken kullanıcılar ve CDP sistemlerinde birbirine karışan kullanıcı profilleri kaderiniz değildir.
ONMARTECH olarak, mevcut SPA (React, Next.js, Vue) projelerinizdeki event hatalarını, SDK sızıntılarını ve CDP entegrasyonlarını 360 derece denetliyor; edge-relay ve server-side event mimarileri ile veri kalitenizi %100 güvenceye alıyoruz.
Sıkça Sorulan Sorular (FAQ)
SPA mimarisinde GTM (Google Tag Manager) kullanımı önerilir mi?
GTM kullanılabilir ancak SPA'larda varsayılan "History Change" tetikleyicileri (triggers) sıklıkla çift kayıt (double counting) üretir. GTM kullanılıyorsa, tetikleyicileri doğrudan dataLayer.push({ event: 'virtual_page_view' }) gibi özel event'lere bağlamak en güvenli yoldur.
Edge Event Relay mimarisini kurmak ne kadar sürer?
Mevcut veri yapınıza bağlı olarak ONMARTECH ekibi, Edge Relay altyapısını ve CDP entegrasyonunu 2 ila 3 hafta içinde sıfır kesintiyle canlıya almaktadır.
Önerilen Okumalar
Dynamic Personalization with AI & CDP: Transforming Content and Reviews Based on Real-Time Search Intent
The era of static pages is over. We explore how to leverage AI and CDP profiles to personalize page content and user reviews in milliseconds, using cost-effective and optimized architectures.
Okumaya Devam Et →LMO (Language Model Optimization) Techniques for B2B: How to Make Your Site Readable for AI Agents
As we rank on the first page of Google for LMO keywords, let's dive into practical techniques to optimize your B2B website for AI search engines like Gemini, Perplexity, and ChatGPT. The difference between AEO and LMO.
Okumaya Devam Et →