Tracking Veri Kaybının Çoğu URL’den Başlıyor
Direct trafik şişiyor, GA4 ile Meta Ads Manager arasındaki conversion sayısı uzlaşmıyor, Shopify Custom Pixel’den giden pageview verisi gerçek sayfa URL’i yerine sandbox URL’i içeriyor. Bu sorunların ortak noktası URL’in tracking için doğru okunmamış olması.
URL bir tarayıcı satırı değil, scheme, host, path, query ve fragment’ten oluşan ve her parçası farklı tracking sonuçları doğuran bir yapı. Hangi parça server’a gider hangisi gitmez, hangi parametre tarayıcıda kırpılır hangisi geçer, CNAME subdomain kurmak first-party bağlamı garantiler mi, sandbox iframe gerçek URL’i nasıl gizler. Bu yazı her birini saha tecrübesiyle açıklıyor.
URL Anatomisi
https://shop.example.com/products/widget?utm_source=newsletter&gclid=abc#size-l
└─┬─┘ └──────┬───────┘└─────┬─────┘└──────────────┬───────────┘└──┬──┘
│ │ │ │ │
scheme host path query fragment
| Parça | Tracking’deki Rolü |
|---|---|
scheme | https zorunlu (cookie Secure flag, ITP uyumluluğu, HTTP/2 multiplexing) |
host | eTLD+1 belirler, cookie scope ve first-party tanımının temeli |
path | Gateway endpoint kimliği, routing kararı |
query | Attribution’ın omurgası: UTM, click ID’ler, custom parametreler |
fragment | Server’a gitmez. Tek başına SPA navigation için kullanılırsa server-side pageview kayboluyor |
Origin kavramı: scheme + host + port üçlüsü tarayıcı güvenliğinin temeli olan “origin”i tanımlar. Same-origin policy, CORS, postMessage targetOrigin kontrolü, cookie scope, Content Security Policy kuralları hep bu üçlüye göre çalışır.
Query String: Attribution’ın Omurgası ve Sızıntı Vektörü
Query string en zengin tracking yüzeyi, en kırılgan yüzey de o. Her platform farklı parametre seti istiyor, her tarayıcı farklı parametreyi kırpıyor, kişisel veri sızıntıları çoğunlukla query string üzerinden oluyor.
Standart Parametreler
- UTM standardı:
utm_source,utm_medium,utm_campaign,utm_content,utm_term. GA4 kaynak/medium çözümlemesi tamamen bu parametrelere bağlı. - Platform click ID’leri:
gclid(Google Ads),wbraid/gbraid(Google iOS app, geçiş dönemi parametreleri1),fbclid(Meta),ttclid(TikTok),msclkid(Microsoft),dclid(DoubleClick),yclid(Yahoo). - Consent Mode v2 sinyalleri:
gcs=G100,gcs=G111gibi değerler consent durumunu server’a taşır. Server-side container’da bu sinyale göre tag firing kurgusu kurulur. Consent bilgisi server’a ulaşmazsa hem yasal hem platform-side ceza riski (Google: reklam hedeflemenin bozulması, Meta CAPI: deduplication kaybı).
Türkçe Karakter ve Encoding Tuzakları
UTM değerlerinde İ, ş, ğ, ü, ö, ç farklı platformlarda farklı encode edilir. GA4 UTF-8 raw bekler, bazı conversion API endpoint’leri percent-encoded UTF-8 ister, e-mail platformları link şablonunda çift encode üretebilir. Pratik kural: UTM değerlerini ASCII ve lowercase tut, kampanya başlığını insan-okunaklı olarak ayrı bir alanda taşı.
%20 ve + arasında space-encoding farkı var. & ile = kampanya isminin içine girerse query string parser’ı kırar, mutlaka encode edilmeli. Çift encode (%2520) genelde kopyala-yapıştır kaynaklı, manuel link şablonlarında en sık görülen hata.
PII Sızıntısı
?email=user@example.com, ?phone=..., ?order_id=... URL’e girdiğinde sızabileceği yerler:
- Tarayıcı geçmişi
- Same-origin server access log
- CDN edge log
- Hata izleme servisleri (Sentry vb.)
- GA4
page_locationboyutu - Sayfada koşan üçüncü taraf scriptler (heatmap araçları, embed reklamlar)
Modern tarayıcılar Referrer-Policy: strict-origin-when-cross-origin’i default kullanıyor, yani path ve query cross-origin Referer header’da artık çıkmıyor. Ama Referrer-Policy: unsafe-url ayarlandığında veya same-origin akışta tam URL korunur. KVKK ve GDPR açısından kişisel veriyi URL’e koymak doğrudan sızıntıdır. Kişisel veri POST body veya hashed identifier olarak taşınır, query string’e asla. Gateway’de query parametreleri ingest edilmeden önce allow-list ile filtrelenmeli.
Tarayıcılar URL’i Nasıl Filtreliyor
Privacy odaklı tarayıcılar URL’den bilinen tracking parametrelerini otomatik kırpıyor. Ama kapsam birbirinden çok farklı ve yıllar içinde değişti, panik başlıklarının çoğu yanlış. 2026 itibarıyla gerçek tablo:
| Tarayıcı | Default Normal Browsing | Stripping Aktif Olduğunda | Kırpılan Parametreler |
|---|---|---|---|
| Safari | Kırpma yok | Private Browsing, Mail/Messages açılan link, manuel ATFP açıkken2 3 | gclid, fbclid, msclkid, ttclid, dclid, yclid (UTM korunur) |
| Firefox | Kırpma yok | ETP Strict (manuel açılır) | fbclid, mc_eid, oly_enc_id, __s, vero_id, _hsenc, mkt_tok (gclid listede yok) |
| Brave | Default aktif | Default Shields | Click ID’ler + bazı mailer parametreleri |
| DuckDuckGo | Default aktif | Browser app + extension | Click ID’ler + tracking parametre seti |
| Chrome | Kırpma yok | Otomatik kırpma yok | - |
Safari 26 Advanced Fingerprinting Protection (AFP): Eylül 2025’te Safari 26 ile gelen AFP tüm browsing modlarında default açık4. AFP üç şey yapıyor: (1) yüksek-entropi device API’lerine bilinen fingerprinting scriptlerinin erişimini kısıtlıyor, (2) tracker-classified scriptlerin uzun-ömürlü storage yazmasını engelliyor, (3) tracker scriptlerin sayfanın URL query string’ini ve document.referrer’ı browser API üzerinden okumasını engelliyor.
Kritik nüans: AFP sayfa-içi script’leri kısıtlar; tam URL HTTP isteğiyle hâlâ server’a ulaşır5. Server-side gateway pageview event’inin URL’ini olduğu gibi alır, gclid ve UTM orada. AFP doğrudan server-side tracking’in değerini artıran bir tarayıcı kararı: client-side dünya kısıtlanıyor, server-side kanal açık kalıyor.
iOS 26 Panik Başlıklarına Dair
Eylül 2025’te yayınlanan iOS 26 release notes’u6 medyada “Apple UTM’leri öldürüyor” başlıklarıyla geçti. Triple Whale ve Northbeam’in iOS 18 vs iOS 26 yan yana testleri7 panik başlıklarının yanlış olduğunu doğruladı:
- Standart UTM’ler (utm_source, utm_medium, utm_campaign, utm_content, utm_term) kırpılmıyor
- Default Safari normal browsing’de hiçbir parametre kırpılmıyor
- Reklam tıklamasının kendisi (Facebook app → ürün sayfası) click ID’yi koruyor
- Kırpma Private Browsing, Mail ve Messages app’inden açılan link’lerde olmaya devam ediyor (iOS 18 ile aynı)
Apple, Safari Technology Preview’de full Link Tracking Protection’ı tüm browsing modlarına yaymayı test ediyor8. Bu yakın bir gelecekte gelebilir; o gün geldiğinde panik etmemenin yolu bugünden gateway altyapısını hazırlamak.
Custom Parameter Transformation Pattern
GA4 dahil çoğu analiz platformu attribution’ı UTM ismine hardcoded yapar. Bu sınırlamayı aşmak için Stape’in önerdiği pattern:
- Reklam URL’lerinde UTM yerine kendi prefix’inle trafik gönder:
?st_src=newsletter&st_mdm=email&st_cmp=spring269 - Server-side container’da landing’e gelen
page_location’ı oku st_*parametreleriniutm_*’a dönüştür (Stape Query Replacer template’i bunu hazır sunuyor10)- GA4 tag’ine giden augmented event’te UTM parametreleri doğru olarak görünür
Avantaj: tarayıcı stripping listesinde olmayan custom isimler hayatta kalır. Trade-off: her platform için ekstra konfigürasyon + ham UTM convention disiplini hâlâ şart.
First-Party Context ve Custom Domain
ITP, ETP ve adblock listeleri third-party context’i ezdikçe, tracking altyapısının kalan tek dayanağı first-party context oluyor. Burada kritik kavram eTLD+1.
eTLD+1 ve Cookie Scope
eTLD+1 (effective Top-Level Domain + 1), cookie sahipliği için tarayıcının baktığı sınır. gw.dnomia.app (subdomain) ile dnomia.app (apex) aynı eTLD+1’e sahip; cookie paylaşılır. dnomia-tracking.com ayrı bir eTLD+1, first-party değil; Safari, Firefox ve Brave default’unda silinir.
2026 itibarıyla third-party cookie tablosu:
| Tarayıcı | Third-Party Cookie | Not |
|---|---|---|
| Safari | Default block (2020+) | ITP |
| Firefox | Default block (2019+) | ETP Strict |
| Brave | Default block | Shields |
| Chrome | Destekliyor | Google Temmuz 2024’te zorunlu deprecation’dan vazgeçti, Nisan 2025’te user-choice prompt’u da iptal etti; Privacy Sandbox API’leri paralel track |
CNAME Subdomain vs Path-Based Proxy
| Özellik | CNAME Subdomain (gw.example.com → vendor) | Path-Based Proxy (example.com/_track → vendor) |
|---|---|---|
| First-party cookie scope | Tam (eTLD+1 aynı) | Tam (aynı domain) |
| SSL yönetimi | Vendor yönetir | Kendi CDN/worker katmanın gerekli |
| CORS | Cross-origin, preflight gerekir | Same-origin, preflight yok |
| CNAME cloaking riski | Var (Safari ITP 2.3+ tespit edebilir, 7 gün cap) | Yok |
| Operasyonel yük | Düşük (vendor altyapıya bakar) | Yüksek (kendi worker/edge’ini yönetiyorsun) |
| Vendor lock-in | Daha az | Vendor değişimi proxy’i yeniden yazmayı gerektirir |
CNAME cloaking caveat: Safari ITP 2.3 sonrası CNAME tabanlı tracking subdomain’leri sınıflandırıcı yakalarsa server-side Set-Cookie ile yazılan cookie bile 7 gün cap’ine tabi tutulur. CNAME first-party “bağışıklık” değil, görece dayanıklılık.
Storage Cap ve CHIPS
Safari ITP 2.3 script-writable storage’ın hepsine 7 gün cap koyuyor: localStorage, IndexedDB, service worker registration. Cookie’yi localStorage’a fallback yaparak ITP’yi aşma denemesi bu yüzden çalışmaz.
CHIPS (Cookies Having Independent Partitioned State): Chrome’un Partitioned cookie attribute’u embed/iframe context’te third-party cookie’yi top-level site bazında izole eder. Subdomain CNAME yerine cross-origin embed çözümleri kullanan kurulumlar için relevant.
Gateway Domain Seçimi
Subdomain isminde dikkat: analytics., tracking., pixel. gibi adlar adblock filtreleri tarafından engelleniyor. Generic subdomain tercih edilmeli: gw., c., t., m.. DNS tarafında CNAME chain 3 hop’tan uzun olmasın; çözümleme gecikmesi pageview ölçümünü etkiler.
Gateway Tasarımı: Path vs Query, Limitler, CORS
Endüstride dominant implementasyonlar: GTM Server-Side Container (Google’ın resmi server container’ı, sGTM), Cloudflare Zaraz (path-based, edge), Stape (CNAME-based managed sGTM hosting).
Path ve Query Sorumluluk Ayrımı
- Path-based gateway:
/cdn-cgi/zaraz/track?event=purchase— CDN-level routing kolay - Subdomain-based gateway:
gw.example.com/track— bağımsız worker/proxy
Query’de sadece event-specific veri, path’te endpoint kimliği olmalı. Karışırsa cache key bozulur, log analizi zorlaşır.
URL Uzunluğu
“Güvenli legacy sınırı” 2 KB (IE 2083 mirası, SEO/share güvencesi). Modern tarayıcılarda gerçek tavan çok daha yüksek: Chrome 32 KB-2 MB, Firefox ~64 KB, Safari ~80 KB. Asıl sınır server/CDN/proxy konfigürasyonu: Cloudflare default 8 KB header, Nginx default 4-8 KB.
Büyük payload için fetch(url, { method: 'POST', keepalive: true }). sendBeacon hâlâ standart (WHATWG living spec), ancak keepalive daha esnek (POST/PUT, custom header) olduğu için tercih ediliyor.
CORS
Cross-origin gateway endpoint’i için:
Access-Control-Allow-Origindoğru set edilmeli- Preflight (
OPTIONS) cevaplanmalı - Credentialled istekler için
Access-Control-Allow-Credentials: true+ spesifik origin (wildcard kabul edilmez)
Path-based proxy bu sorunu sıfırlar: aynı origin, preflight yok. Solo kurulumda operasyonel yükü düşüren bir tercih.
Fragment ve SPA: Server’a Ulaşmayan Veri
Tarayıcı server’a # sonrasını göndermez. Server-side log, CDN analytics ve geleneksel pageview tracking tüm SPA route’larını aynı pageview olarak görür. SPA framework’ünde pushState ile path-based routing kullanılmalı, hash-based değil.
Attribution senaryosu: ?utm_source=x#campaign-detail formunda query server-side’a gider, fragment gitmez. Hashtag kampanyalar link’i kırmasın diye query’den önce konulmalı.
Mini Case: Shopify Custom Pixel Sandbox
Shopify Custom Pixel (Web Pixels API) sandboxed bir iframe içinde çalışır. URL erişimi burada sıradan değil.
| URL Erişim Yöntemi | Döndürdüğü | Tracking’de Kullanılır mı? |
|---|---|---|
window.location.href | Sandbox iframe URL’i | Hayır (sahte) |
event.context.document.location.href | Sandbox URL’i içerir | Hayır (sahte) |
event.context.window.location.href (page_viewed’de) | Gerçek storefront URL | Evet (tek doğru kaynak) |
Cookie ve storage izolasyonu: window.localStorage ve document.cookie sandbox iframe’inde çalışır ama top frame’e değmez. Storefront cookie’sine erişmek için browser.cookie ve browser.localStorage (async API) kullanılır.
URL ile bağlantı: Sandbox URL gerçek URL’in yerine geçtiğinde GA4’te tüm pageview’lar fake URL’e gider. GA4 auto page_view kapatılır, manuel olarak event.context.window.location.href ile gönderilir.
Primary domain trap: Shopify Settings → Domains’te primary domain başka bir domain’den redirect alıyorsa, sayfa pixel bitmeden navigate ediyor; sandbox tracking kırılıyor. Domain hizalaması: Shopify primary = GA4 Web Stream = GTM container domain.
Uçtan Uca Senaryo: Shopify + Cloudflare + GA4 + Meta CAPI
Bir Shopify mağazası: Cloudflare arkasında, Custom Pixel ile GA4 ve Meta CAPI’ye veri gönderiyor.
- Müşteri
https://shop.example.com/products/widget?utm_source=newsletter&fbclid=...ile geliyor. - Custom Pixel sandbox
page_viewedevent’indeevent.context.window.location.href’i okuyor; gerçek URL elde ediliyor. - UTM ve
fbclidparametreleri allow-list ile filtreleniyor (kişisel veri yok).fbclidayıklanıp Meta’nın beklediğifbcformatına dönüştürülüyor:fb.1.<unix_timestamp_ms>.<fbclid>. Hamfbclidyetmez. - Pixel
fetch('https://shop.example.com/cdn-cgi/zaraz/track', { method: 'POST', keepalive: true, body: JSON.stringify(payload) })ile path-based gateway’e POST atıyor. - Aynı origin: CORS preflight yok. Cookie tam first-party (eTLD+1 aynı).
- Cloudflare Worker payload’ı çoğaltıp GA4 Measurement Protocol ve Meta CAPI endpoint’lerine fan-out yapıyor.
gcs(consent state) parametresi GA4 isteğinde bayrak olarak taşınıyor. fbccookie’si_fbpile birleşip CAPI event’ininuser_databloğuna ekleniyor.
Akışın her adımı URL anatomisinin doğru çözülmesine bağlı: yanlış host → first-party kaybı; query’de PII → log sızıntısı; fragment’ta UTM → veri kaybı; sandbox URL → fake pageview; ham fbclid → Meta deduplication bozulması.
URI, URL, URN: Kısa Referans
Eski yazıyı arayan için kısa hatırlatma:
- URI: en geniş şemsiye, bir kaynağı tanımlayan herhangi bir string.
- URL: URI’nın “konum” varyantı, kaynağa nasıl ulaşılacağını söyler (
https://...,ftp://...). - URN: URI’nın “isim” varyantı, konumdan bağımsız kalıcı kimlik (
urn:isbn:...,urn:uuid:...).
Pratikte web’de “URL” yeterli. URI ve URN ayrımı RFC 398611 ve W3C standartlarında geçer; kaynak yönetimi veya metadata sistemleri tasarlarken gerekir. Modern tracking pratiğinde günlük olarak URL’in parçalarıyla çalışılır, URN nadiren gündeme gelir. URI scheme kayıtları için IANA registry kanonik kaynak12.
Özet: URL’in Hangi Parçası Neyi Etkiliyor
| URL Parçası | Tracking Etkisi |
|---|---|
scheme (https) | Cookie Secure flag, HTTP/2, ITP uyumluluğu |
host | eTLD+1, first-party scope, CNAME cloaking riski |
path | Gateway endpoint kimliği, CORS davranışı |
query | Attribution omurgası, browser stripping yüzeyi, PII sızıntı vektörü |
fragment (#) | Server’a hiç gitmez, SPA pageview kaybı kaynağı |
Gateway tasarımında her parça için bilinçli karar vermek tracking veri kalitesinin temeli. URL’i tarayıcı satırı olarak değil, beş ayrı sorumluluğu olan bir veri yapısı olarak okumak gerekiyor.
Footnotes
-
Update to iOS 14 campaign measurement. Google Ads Help
wbraidvegbraidiOS app campaign measurement için Mart 2021’de tanıtıldı; kullanıcı-seviyesi bağlama olmadan kampanya-seviyesi veri taşırlar. ↩ - Private Browsing 2.0. WebKit Blog Apple’ın Link Tracking Protection kapsamı: “campaign parameter that’s only used for campaign attribution, as opposed to click or user-level tracking. Safari allows such parameters to pass through.” ↩
- iOS 26 UTM tracking testleri. Triple Whale iOS 18 ve iOS 26 yan-yana karşılaştırma testleri: “Safari still preserves common tracking tags (like utm_source, utm_medium, and utm_campaign).” ↩
- WebKit Features in Safari 26.0. WebKit Blog Safari 26’da Advanced Fingerprinting Protection default açılış kararı. ↩
- Safari 26 tracking changes explained. Taggrs Ocak 2026 saha doğrulaması: AFP’nin tracker scriptlerinin URL ve referrer okumasını engellediği ama tam URL’in hâlâ server’a ulaştığı tespiti. ↩
- iOS & iPadOS 26 Release Notes. Apple Developer Apple’ın resmi iOS 26 release notes’ları. ↩
- iOS 26 Won’t Kill Your UTMs. Northbeam Northbeam’in iOS 18 vs iOS 26 controlled test sonuçları; click ID’lerin Messages/Mail/Private’da kırpılması, UTM’lerin tüm modlarda korunması. ↩
- Safari vs UTM: Do We Really Need to Panic? Alex Ignatenko Safari Technology Preview testleri; full LTP’nin yakın gelecekte tüm modlara yayılabileceği işaretleri. ↩
-
How to avoid UTM parameters removal. Stape Custom parameter transformation pattern: reklamda
st_src/st_mdm/st_cmptaşı, server-side container’dautm_*’a dönüştür. ↩ - Query Replacer Variable. Stape on GitHub Stape’in açık kaynaklı sGTM Query Replacer template’i. ↩
- RFC 3986: Uniform Resource Identifier (URI): Generic Syntax. IETF URI sözdiziminin kanonik standardı. ↩
- Uniform Resource Identifier (URI) Schemes. IANA IANA’nın URI scheme registry’si. ↩
- 01 Fragment (
#) sunucuya gitmez; SPA'da hash routing kullanılırsa pageview server-side log'da görünmez - 02 Safari Link Tracking Protection sadece click ID'leri (
gclid,fbclid,msclkid,ttclid,dclid,yclid) kırpar; UTM parametreleri default normal browsing'de korunur - 03 Safari 26 AFP tracker-classified scriptlerin URL query ve
document.referrerokumasını browser-level engelliyor; ama tam URL hâlâ server'a ulaşıyor - 04 Custom Pixel sandbox'ında
window.location.hrefsahte URL döner; gerçek storefront URLevent.context.window.location.hrefile alınır - 05 CNAME first-party subdomain ITP koruması mutlak değil; cloaking tespit edilirse server-side cookie de 7 güne düşer
+ Safari UTM parametrelerini kırpıyor mu?
Hayır. Safari Link Tracking Protection sadece click ID'leri kırpar (gclid, fbclid, msclkid, ttclid, dclid, yclid). UTM parametreleri default normal browsing'de korunur. iOS 26 ile iOS 18 davranışı aynı; medya panik başlığına rağmen UTM kırpma yok. Stripping yalnızca Private Browsing, Mail ve Messages app'inden açılan link'lerde veya kullanıcı manuel Advanced Tracking and Fingerprinting Protection'ı açtığında devreye giriyor.
+ URL fragment (#) server-side tracking'de neden sorun?
Tarayıcı # sonrasını HTTP isteğiyle sunucuya göndermez. SPA'da hash routing (#/sayfa1, #/sayfa2) kullanılırsa server-side log, CDN analytics ve geleneksel pageview tracking tüm route'ları aynı pageview olarak görür. Çözüm pushState ile path-based routing. Attribution parametresi varsa query'ye konmalı, fragment'a değil.
+ Server-side gateway path-based mi olmalı subdomain-based mi?
Path-based proxy (örn. example.com/_track) aynı origin'de çalışır, CORS preflight yok, CNAME cloaking tespiti riski yok. Subdomain-based (örn. gw.example.com) vendor yönetimi kolaylaştırır ama CNAME cloaking tespitine açıktır. Cloudflare Zaraz path-based, Stape CNAME-based, GTM Server-Side ikisini de destekler. Solo veya küçük ekipte path-based daha az operasyonel yük.
+ Shopify Custom Pixel'de gerçek URL'e nasıl erişirim?
Sandbox iframe'i nedeniyle window.location.href ve event.context.document.location.href sahte sandbox URL'i döner. Gerçek storefront URL için page_viewed event payload'ındaki event.context.window.location.href kullanılır. Bu değeri yakalayıp diğer event'lere custom dimension olarak taşımak gerekiyor. GA4 auto page_view kapatılmalı, manuel pageview gönderiminde gerçek URL kullanılmalı.
+ Custom parameter transformation pattern ne işe yarar?
GA4 dahil çoğu analiz platformu attribution'ı UTM ismine hardcoded yapar. Reklam URL'lerine UTM yerine kendi prefix'inle parametre koyarsın (örn. st_src, st_mdm, st_cmp), landing'de server-side container page_location'ı okuyup bu parametreleri utm_*'a dönüştürür. Tarayıcı parametre kırpma listesinde olmayan custom isimler hayatta kalır. Stape'in Query Replacer template'i bu pattern'i resmî olarak destekliyor.