[{"data":1,"prerenderedAt":1668},["ShallowReactive",2],{"article-alternates":3,"article-\u002Ftr\u002Fdata\u002Fserver-side-gtm-ve-conversion-api-sifirdan-productiona":13},{"i18nKey":4,"paths":5},"data-001-2026-05",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fdata\u002Fserver-side-gtm-conversion-api-produktion","\u002Fen\u002Fdata\u002Fserver-side-gtm-conversion-api-production","\u002Fes\u002Fdata\u002Fserver-side-gtm-conversion-api-produccion","\u002Ffr\u002Fdata\u002Fgtm-serverside-conversion-api-production","\u002Fit\u002Fdata\u002Fserver-side-gtm-conversion-api-da-produzione","\u002Fru\u002Fdata\u002Fserver-side-gtm-konversiya-api-production","\u002Ftr\u002Fdata\u002Fserver-side-gtm-ve-conversion-api-sifirdan-productiona",{"_path":12,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1662,"_id":1663,"_source":1664,"_file":1665,"_stem":1666,"_extension":1667},"data",false,"","Server-Side GTM ve Conversion API: Sıfırdan Production'a","Cloud Run ve Workers üzerinde server-side tagging kurulumu, container template, event deduplication ve production monitoring stratejileri.","2026-05-07",[21,22,23,24,25],"server-side-gtm","conversion-api","cloud-run","event-deduplication","privacy-sandbox",8,"Roibase",{"type":29,"children":30,"toc":1654},"root",[31,39,46,51,56,102,108,129,134,245,281,453,518,524,574,579,1031,1075,1110,1131,1137,1142,1147,1199,1220,1233,1254,1260,1366,1387,1437,1513,1519,1540,1605,1625,1639,1643,1648],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","Tarayıcı-tabanlı ölçüm öldü. Third-party cookie'ler gitti, ITP 12 saate düştü, Consent Mode v2 zorunlu hale geldi. Meta ve Google'ın doğrudan API endpoint'lerine server-side event göndermeyen markalar artık attribution karanlığında kalıyor. Server-side Google Tag Manager (sGTM) ve Conversion API kurulumu 2026'da opsiyonel değil — production requirement. Bu yazıda Cloud Run üzerinde sıfırdan production-ready bir sGTM container nasıl deploy edilir, event deduplication nasıl kurulur ve hangi metrikler monitoring edilir göstereceğiz.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"server-side-tagging-neden-container-gerektirir",[44],{"type":37,"value":45},"Server-Side Tagging Neden Container Gerektirir",{"type":32,"tag":33,"props":47,"children":48},{},[49],{"type":37,"value":50},"Tarayıcıda çalışan klasik GTM JavaScript kütüphanesi yükler ve user agent'tan veri toplar. Server-side GTM tam tersi çalışır: kendi sunucun üzerinde çalışan bir Node.js container, client'tan gelen HTTP POST'ları alır, event'ları zenginleştirir (IP, user-agent parsing, cookie'den gelen first-party ID) ve hedef API'lere (Meta CAPI, Google Ads Conversion, GA4 Measurement Protocol) iletir. Bu mimari 3 temel fayda sağlar: (1) tarayıcı kısıtlamalarını bypass edersin — ITP, adblocker, CORS yok; (2) PII'yi kontrollü şekilde hash'leyip gönderebilirsin — email, telefon server'da SHA-256'lanır, tarayıcıya asla dönmez; (3) tek event'tan çoklu platforma paralel istek atarsın — client'tan tek POST, server'dan 4 farklı endpoint'e fan-out.",{"type":32,"tag":33,"props":52,"children":53},{},[54],{"type":37,"value":55},"Google'ın resmi deployment yolu App Engine veya Cloud Run. App Engine sabit maliyet + auto-scale getirir ama customize edilemez. Cloud Run tercih edilir çünkü minimum instance=1 ile 7\u002F24 latency garantisi verebilirsin ve container image'ini custom Dockerfile ile özelleştirebilirsin (örneğin environment variable'lardan secret çekme, startup script injection). Alternatif Cloudflare Workers deployment'ı var — daha düşük cold-start latency (~5ms vs 200ms) ama Node.js sandbox sınırlamaları nedeniyle bazı GTM tag'leri çalışmaz (özellikle custom template'lerde native module require eden).",{"type":32,"tag":33,"props":57,"children":58},{},[59,61,68,70,76,78,84,86,92,94,100],{"type":37,"value":60},"Deployment süreci şu adımlardan oluşur: (1) Google Cloud Console'da yeni proje, (2) ",{"type":32,"tag":62,"props":63,"children":65},"code",{"className":64},[],[66],{"type":37,"value":67},"gcloud",{"type":37,"value":69}," CLI ile sGTM container image'ını pull et, (3) Cloud Run service oluştur + environment variable'ları set et (",{"type":32,"tag":62,"props":71,"children":73},{"className":72},[],[74],{"type":37,"value":75},"CONTAINER_CONFIG",{"type":37,"value":77},", ",{"type":32,"tag":62,"props":79,"children":81},{"className":80},[],[82],{"type":37,"value":83},"PREVIEW_SERVER_URL",{"type":37,"value":85},"), (4) custom domain bağla (örn. ",{"type":32,"tag":62,"props":87,"children":89},{"className":88},[],[90],{"type":37,"value":91},"gtm.roibase.com.tr",{"type":37,"value":93},") — first-party context için zorunlu, (5) tagging server URL'yi web GTM'e ekle (",{"type":32,"tag":62,"props":95,"children":97},{"className":96},[],[98],{"type":37,"value":99},"serverContainerUrl",{"type":37,"value":101}," parametresi). İlk deploy 15 dakika alır, sonrası CI\u002FCD ile 2 dakikaya düşer.",{"type":32,"tag":40,"props":103,"children":105},{"id":104},"event-deduplication-client-server-sinyalini-tek-idye-bağlamak",[106],{"type":37,"value":107},"Event Deduplication: Client + Server Sinyalini Tek ID'ye Bağlamak",{"type":32,"tag":33,"props":109,"children":110},{},[111,113,119,121,127],{"type":37,"value":112},"Server-side GTM'in kritik sorunu deduplication. Aynı dönüşüm hem tarayıcıdan (client-side GA4 tag) hem server'dan (server-side GA4 client) giderse platform 2 conversion sayar. Meta CAPI ve Google Ads Conversion için event deduplication ID sistemi zorunlu. Nasıl çalışır: her event'a unique bir ",{"type":32,"tag":62,"props":114,"children":116},{"className":115},[],[117],{"type":37,"value":118},"event_id",{"type":37,"value":120}," (veya Meta terminolojisinde ",{"type":32,"tag":62,"props":122,"children":124},{"className":123},[],[125],{"type":37,"value":126},"event_name + event_id",{"type":37,"value":128},") atarsın, hem client hem server aynı ID'yi gönderir, platform 24 saat pencerede ID collision yaparsa duplicate'i drop eder.",{"type":32,"tag":33,"props":130,"children":131},{},[132],{"type":37,"value":133},"Deduplication ID stratejileri:",{"type":32,"tag":135,"props":136,"children":137},"table",{},[138,162],{"type":32,"tag":139,"props":140,"children":141},"thead",{},[142],{"type":32,"tag":143,"props":144,"children":145},"tr",{},[146,152,157],{"type":32,"tag":147,"props":148,"children":149},"th",{},[150],{"type":37,"value":151},"Yöntem",{"type":32,"tag":147,"props":153,"children":154},{},[155],{"type":37,"value":156},"Avantaj",{"type":32,"tag":147,"props":158,"children":159},{},[160],{"type":37,"value":161},"Risk",{"type":32,"tag":163,"props":164,"children":165},"tbody",{},[166,185,203,221],{"type":32,"tag":143,"props":167,"children":168},{},[169,175,180],{"type":32,"tag":170,"props":171,"children":172},"td",{},[173],{"type":37,"value":174},"UUID v4 (random)",{"type":32,"tag":170,"props":176,"children":177},{},[178],{"type":37,"value":179},"Collision riski yok",{"type":32,"tag":170,"props":181,"children":182},{},[183],{"type":37,"value":184},"Client-server sync gerektirir (localStorage\u002Fcookie)",{"type":32,"tag":143,"props":186,"children":187},{},[188,193,198],{"type":32,"tag":170,"props":189,"children":190},{},[191],{"type":37,"value":192},"Transaction ID (e-commerce)",{"type":32,"tag":170,"props":194,"children":195},{},[196],{"type":37,"value":197},"Doğal unique",{"type":32,"tag":170,"props":199,"children":200},{},[201],{"type":37,"value":202},"Non-transaction event'lerde (lead, signup) yok",{"type":32,"tag":143,"props":204,"children":205},{},[206,211,216],{"type":32,"tag":170,"props":207,"children":208},{},[209],{"type":37,"value":210},"Session ID + timestamp",{"type":32,"tag":170,"props":212,"children":213},{},[214],{"type":37,"value":215},"Kolay üretilebilir",{"type":32,"tag":170,"props":217,"children":218},{},[219],{"type":37,"value":220},"Session overlap durumunda çarpışabilir",{"type":32,"tag":143,"props":222,"children":223},{},[224,235,240],{"type":32,"tag":170,"props":225,"children":226},{},[227,233],{"type":32,"tag":62,"props":228,"children":230},{"className":229},[],[231],{"type":37,"value":232},"_ga",{"type":37,"value":234}," client ID + event timestamp",{"type":32,"tag":170,"props":236,"children":237},{},[238],{"type":37,"value":239},"First-party ID'ye dayalı",{"type":32,"tag":170,"props":241,"children":242},{},[243],{"type":37,"value":244},"Clock skew riski (client\u002Fserver saat farkı)",{"type":32,"tag":33,"props":246,"children":247},{},[248,250,256,258,263,265,271,273,279],{"type":37,"value":249},"Roibase production setup: ",{"type":32,"tag":62,"props":251,"children":253},{"className":252},[],[254],{"type":37,"value":255},"SHA-256(_ga + event_name + unix_ms)",{"type":37,"value":257}," — tarayıcıda DataLayer'a push'larken ",{"type":32,"tag":62,"props":259,"children":261},{"className":260},[],[262],{"type":37,"value":118},{"type":37,"value":264}," field'ını bu hash ile dolduruyoruz, server-side GA4 tag'i aynı field'ı okuyup Measurement Protocol'e gönderiyor. Meta CAPI için ek ",{"type":32,"tag":62,"props":266,"children":268},{"className":267},[],[269],{"type":37,"value":270},"event_source_url",{"type":37,"value":272}," ve ",{"type":32,"tag":62,"props":274,"children":276},{"className":275},[],[277],{"type":37,"value":278},"action_source=website",{"type":37,"value":280}," parametrelerini server'da inject ediyoruz çünkü client-side Facebook Pixel bu field'ları göndermez ama server-side validation için zorunlu.",{"type":32,"tag":282,"props":283,"children":287},"pre",{"className":284,"code":285,"language":286,"meta":16,"style":16},"language-javascript shiki shiki-themes github-dark","\u002F\u002F DataLayer push örneği (client-side)\nwindow.dataLayer.push({\n  event: 'purchase',\n  event_id: sha256(_ga + 'purchase' + Date.now()),\n  transaction_id: 'ORD-12345',\n  value: 299.00,\n  currency: 'TRY'\n});\n","javascript",[288],{"type":32,"tag":62,"props":289,"children":290},{"__ignoreMap":16},[291,303,324,344,394,412,431,445],{"type":32,"tag":292,"props":293,"children":296},"span",{"class":294,"line":295},"line",1,[297],{"type":32,"tag":292,"props":298,"children":300},{"style":299},"--shiki-default:#6A737D",[301],{"type":37,"value":302},"\u002F\u002F DataLayer push örneği (client-side)\n",{"type":32,"tag":292,"props":304,"children":306},{"class":294,"line":305},2,[307,313,319],{"type":32,"tag":292,"props":308,"children":310},{"style":309},"--shiki-default:#E1E4E8",[311],{"type":37,"value":312},"window.dataLayer.",{"type":32,"tag":292,"props":314,"children":316},{"style":315},"--shiki-default:#B392F0",[317],{"type":37,"value":318},"push",{"type":32,"tag":292,"props":320,"children":321},{"style":309},[322],{"type":37,"value":323},"({\n",{"type":32,"tag":292,"props":325,"children":327},{"class":294,"line":326},3,[328,333,339],{"type":32,"tag":292,"props":329,"children":330},{"style":309},[331],{"type":37,"value":332},"  event: ",{"type":32,"tag":292,"props":334,"children":336},{"style":335},"--shiki-default:#9ECBFF",[337],{"type":37,"value":338},"'purchase'",{"type":32,"tag":292,"props":340,"children":341},{"style":309},[342],{"type":37,"value":343},",\n",{"type":32,"tag":292,"props":345,"children":347},{"class":294,"line":346},4,[348,353,358,363,369,374,379,384,389],{"type":32,"tag":292,"props":349,"children":350},{"style":309},[351],{"type":37,"value":352},"  event_id: ",{"type":32,"tag":292,"props":354,"children":355},{"style":315},[356],{"type":37,"value":357},"sha256",{"type":32,"tag":292,"props":359,"children":360},{"style":309},[361],{"type":37,"value":362},"(_ga ",{"type":32,"tag":292,"props":364,"children":366},{"style":365},"--shiki-default:#F97583",[367],{"type":37,"value":368},"+",{"type":32,"tag":292,"props":370,"children":371},{"style":335},[372],{"type":37,"value":373}," 'purchase'",{"type":32,"tag":292,"props":375,"children":376},{"style":365},[377],{"type":37,"value":378}," +",{"type":32,"tag":292,"props":380,"children":381},{"style":309},[382],{"type":37,"value":383}," Date.",{"type":32,"tag":292,"props":385,"children":386},{"style":315},[387],{"type":37,"value":388},"now",{"type":32,"tag":292,"props":390,"children":391},{"style":309},[392],{"type":37,"value":393},"()),\n",{"type":32,"tag":292,"props":395,"children":397},{"class":294,"line":396},5,[398,403,408],{"type":32,"tag":292,"props":399,"children":400},{"style":309},[401],{"type":37,"value":402},"  transaction_id: ",{"type":32,"tag":292,"props":404,"children":405},{"style":335},[406],{"type":37,"value":407},"'ORD-12345'",{"type":32,"tag":292,"props":409,"children":410},{"style":309},[411],{"type":37,"value":343},{"type":32,"tag":292,"props":413,"children":415},{"class":294,"line":414},6,[416,421,427],{"type":32,"tag":292,"props":417,"children":418},{"style":309},[419],{"type":37,"value":420},"  value: ",{"type":32,"tag":292,"props":422,"children":424},{"style":423},"--shiki-default:#79B8FF",[425],{"type":37,"value":426},"299.00",{"type":32,"tag":292,"props":428,"children":429},{"style":309},[430],{"type":37,"value":343},{"type":32,"tag":292,"props":432,"children":434},{"class":294,"line":433},7,[435,440],{"type":32,"tag":292,"props":436,"children":437},{"style":309},[438],{"type":37,"value":439},"  currency: ",{"type":32,"tag":292,"props":441,"children":442},{"style":335},[443],{"type":37,"value":444},"'TRY'\n",{"type":32,"tag":292,"props":446,"children":447},{"class":294,"line":26},[448],{"type":32,"tag":292,"props":449,"children":450},{"style":309},[451],{"type":37,"value":452},"});\n",{"type":32,"tag":33,"props":454,"children":455},{},[456,458,464,466,472,474,479,481,487,489,495,497,502,504,509,510,516],{"type":37,"value":457},"Server-side container'da custom variable oluşturarak ",{"type":32,"tag":62,"props":459,"children":461},{"className":460},[],[462],{"type":37,"value":463},"{{Event ID}}",{"type":37,"value":465}," değişkenini hem GA4 hem CAPI tag'lerine map ediyoruz. GA4 Measurement Protocol ",{"type":32,"tag":62,"props":467,"children":469},{"className":468},[],[470],{"type":37,"value":471},"&ep.event_id=",{"type":37,"value":473}," parametresini destekliyor, Meta CAPI'de root-level ",{"type":32,"tag":62,"props":475,"children":477},{"className":476},[],[478],{"type":37,"value":118},{"type":37,"value":480}," field'ı var. Google Ads Conversion için ",{"type":32,"tag":62,"props":482,"children":484},{"className":483},[],[485],{"type":37,"value":486},"gclid",{"type":37,"value":488}," + ",{"type":32,"tag":62,"props":490,"children":492},{"className":491},[],[493],{"type":37,"value":494},"conversion_action_id",{"type":37,"value":496}," kombinasyonu deduplication sağlıyor — ",{"type":32,"tag":62,"props":498,"children":500},{"className":499},[],[501],{"type":37,"value":486},{"type":37,"value":503}," cookie'den okunup server'a POST ediliyor, server tarafında Ads tag'i ",{"type":32,"tag":62,"props":505,"children":507},{"className":506},[],[508],{"type":37,"value":486},{"type":37,"value":488},{"type":32,"tag":62,"props":511,"children":513},{"className":512},[],[514],{"type":37,"value":515},"conversion_value",{"type":37,"value":517},"'yu birleştirip Conversion Tracking API'ye gönderiyor.",{"type":32,"tag":40,"props":519,"children":521},{"id":520},"container-template-ve-custom-client-kurulumu",[522],{"type":37,"value":523},"Container Template ve Custom Client Kurulumu",{"type":32,"tag":33,"props":525,"children":526},{},[527,529,535,537,542,544,549,551,557,559,565,566,572],{"type":37,"value":528},"sGTM container'ı 3 temel bileşenden oluşur: ",{"type":32,"tag":530,"props":531,"children":532},"strong",{},[533],{"type":37,"value":534},"Client",{"type":37,"value":536}," (gelen HTTP request'i parse eder, event object'e dönüştürür), ",{"type":32,"tag":530,"props":538,"children":539},{},[540],{"type":37,"value":541},"Tag",{"type":37,"value":543}," (event'ı dış API'ye gönderir), ",{"type":32,"tag":530,"props":545,"children":546},{},[547],{"type":37,"value":548},"Variable",{"type":37,"value":550}," (tag'ler arası data paylaşımı). Google'ın default \"GA4\" client'ı yeterli değil çünkü sadece ",{"type":32,"tag":62,"props":552,"children":554},{"className":553},[],[555],{"type":37,"value":556},"\u002Fg\u002Fcollect",{"type":37,"value":558}," endpoint'ini dinliyor. Biz custom client yazarak hem GA4 hem custom endpoint'leri (",{"type":32,"tag":62,"props":560,"children":562},{"className":561},[],[563],{"type":37,"value":564},"\u002Fevent",{"type":37,"value":77},{"type":32,"tag":62,"props":567,"children":569},{"className":568},[],[570],{"type":37,"value":571},"\u002Fpurchase",{"type":37,"value":573},") aynı container'da handle ediyoruz.",{"type":32,"tag":33,"props":575,"children":576},{},[577],{"type":37,"value":578},"Custom client template örneği:",{"type":32,"tag":282,"props":580,"children":582},{"className":284,"code":581,"language":286,"meta":16,"style":16},"const claimRequest = require('claimRequest');\nconst getRequestBody = require('getRequestBody');\nconst JSON = require('JSON');\nconst logToConsole = require('logToConsole');\n\nclaimRequest();\n\nconst body = getRequestBody();\nconst eventData = JSON.parse(body);\n\n\u002F\u002F Event object'i normalize et\nconst normalizedEvent = {\n  event_name: eventData.event || 'unknown',\n  user_data: {\n    client_id: eventData.client_id,\n    user_agent: eventData.user_agent,\n    ip_override: eventData.ip_address\n  },\n  event_id: eventData.event_id,\n  timestamp_micros: eventData.timestamp * 1000000\n};\n\nlogToConsole('Normalized event:', normalizedEvent);\nrunContainer(normalizedEvent, () => {\n  returnResponse();\n});\n",[583],{"type":32,"tag":62,"props":584,"children":585},{"__ignoreMap":16},[586,624,657,690,723,732,745,752,776,812,820,829,851,874,883,892,901,910,919,928,947,956,964,987,1010,1023],{"type":32,"tag":292,"props":587,"children":588},{"class":294,"line":295},[589,594,599,604,609,614,619],{"type":32,"tag":292,"props":590,"children":591},{"style":365},[592],{"type":37,"value":593},"const",{"type":32,"tag":292,"props":595,"children":596},{"style":423},[597],{"type":37,"value":598}," claimRequest",{"type":32,"tag":292,"props":600,"children":601},{"style":365},[602],{"type":37,"value":603}," =",{"type":32,"tag":292,"props":605,"children":606},{"style":315},[607],{"type":37,"value":608}," require",{"type":32,"tag":292,"props":610,"children":611},{"style":309},[612],{"type":37,"value":613},"(",{"type":32,"tag":292,"props":615,"children":616},{"style":335},[617],{"type":37,"value":618},"'claimRequest'",{"type":32,"tag":292,"props":620,"children":621},{"style":309},[622],{"type":37,"value":623},");\n",{"type":32,"tag":292,"props":625,"children":626},{"class":294,"line":305},[627,631,636,640,644,648,653],{"type":32,"tag":292,"props":628,"children":629},{"style":365},[630],{"type":37,"value":593},{"type":32,"tag":292,"props":632,"children":633},{"style":423},[634],{"type":37,"value":635}," getRequestBody",{"type":32,"tag":292,"props":637,"children":638},{"style":365},[639],{"type":37,"value":603},{"type":32,"tag":292,"props":641,"children":642},{"style":315},[643],{"type":37,"value":608},{"type":32,"tag":292,"props":645,"children":646},{"style":309},[647],{"type":37,"value":613},{"type":32,"tag":292,"props":649,"children":650},{"style":335},[651],{"type":37,"value":652},"'getRequestBody'",{"type":32,"tag":292,"props":654,"children":655},{"style":309},[656],{"type":37,"value":623},{"type":32,"tag":292,"props":658,"children":659},{"class":294,"line":326},[660,664,669,673,677,681,686],{"type":32,"tag":292,"props":661,"children":662},{"style":365},[663],{"type":37,"value":593},{"type":32,"tag":292,"props":665,"children":666},{"style":423},[667],{"type":37,"value":668}," JSON",{"type":32,"tag":292,"props":670,"children":671},{"style":365},[672],{"type":37,"value":603},{"type":32,"tag":292,"props":674,"children":675},{"style":315},[676],{"type":37,"value":608},{"type":32,"tag":292,"props":678,"children":679},{"style":309},[680],{"type":37,"value":613},{"type":32,"tag":292,"props":682,"children":683},{"style":335},[684],{"type":37,"value":685},"'JSON'",{"type":32,"tag":292,"props":687,"children":688},{"style":309},[689],{"type":37,"value":623},{"type":32,"tag":292,"props":691,"children":692},{"class":294,"line":346},[693,697,702,706,710,714,719],{"type":32,"tag":292,"props":694,"children":695},{"style":365},[696],{"type":37,"value":593},{"type":32,"tag":292,"props":698,"children":699},{"style":423},[700],{"type":37,"value":701}," logToConsole",{"type":32,"tag":292,"props":703,"children":704},{"style":365},[705],{"type":37,"value":603},{"type":32,"tag":292,"props":707,"children":708},{"style":315},[709],{"type":37,"value":608},{"type":32,"tag":292,"props":711,"children":712},{"style":309},[713],{"type":37,"value":613},{"type":32,"tag":292,"props":715,"children":716},{"style":335},[717],{"type":37,"value":718},"'logToConsole'",{"type":32,"tag":292,"props":720,"children":721},{"style":309},[722],{"type":37,"value":623},{"type":32,"tag":292,"props":724,"children":725},{"class":294,"line":396},[726],{"type":32,"tag":292,"props":727,"children":729},{"emptyLinePlaceholder":728},true,[730],{"type":37,"value":731},"\n",{"type":32,"tag":292,"props":733,"children":734},{"class":294,"line":414},[735,740],{"type":32,"tag":292,"props":736,"children":737},{"style":315},[738],{"type":37,"value":739},"claimRequest",{"type":32,"tag":292,"props":741,"children":742},{"style":309},[743],{"type":37,"value":744},"();\n",{"type":32,"tag":292,"props":746,"children":747},{"class":294,"line":433},[748],{"type":32,"tag":292,"props":749,"children":750},{"emptyLinePlaceholder":728},[751],{"type":37,"value":731},{"type":32,"tag":292,"props":753,"children":754},{"class":294,"line":26},[755,759,764,768,772],{"type":32,"tag":292,"props":756,"children":757},{"style":365},[758],{"type":37,"value":593},{"type":32,"tag":292,"props":760,"children":761},{"style":423},[762],{"type":37,"value":763}," body",{"type":32,"tag":292,"props":765,"children":766},{"style":365},[767],{"type":37,"value":603},{"type":32,"tag":292,"props":769,"children":770},{"style":315},[771],{"type":37,"value":635},{"type":32,"tag":292,"props":773,"children":774},{"style":309},[775],{"type":37,"value":744},{"type":32,"tag":292,"props":777,"children":779},{"class":294,"line":778},9,[780,784,789,793,797,802,807],{"type":32,"tag":292,"props":781,"children":782},{"style":365},[783],{"type":37,"value":593},{"type":32,"tag":292,"props":785,"children":786},{"style":423},[787],{"type":37,"value":788}," eventData",{"type":32,"tag":292,"props":790,"children":791},{"style":365},[792],{"type":37,"value":603},{"type":32,"tag":292,"props":794,"children":795},{"style":423},[796],{"type":37,"value":668},{"type":32,"tag":292,"props":798,"children":799},{"style":309},[800],{"type":37,"value":801},".",{"type":32,"tag":292,"props":803,"children":804},{"style":315},[805],{"type":37,"value":806},"parse",{"type":32,"tag":292,"props":808,"children":809},{"style":309},[810],{"type":37,"value":811},"(body);\n",{"type":32,"tag":292,"props":813,"children":815},{"class":294,"line":814},10,[816],{"type":32,"tag":292,"props":817,"children":818},{"emptyLinePlaceholder":728},[819],{"type":37,"value":731},{"type":32,"tag":292,"props":821,"children":823},{"class":294,"line":822},11,[824],{"type":32,"tag":292,"props":825,"children":826},{"style":299},[827],{"type":37,"value":828},"\u002F\u002F Event object'i normalize et\n",{"type":32,"tag":292,"props":830,"children":832},{"class":294,"line":831},12,[833,837,842,846],{"type":32,"tag":292,"props":834,"children":835},{"style":365},[836],{"type":37,"value":593},{"type":32,"tag":292,"props":838,"children":839},{"style":423},[840],{"type":37,"value":841}," normalizedEvent",{"type":32,"tag":292,"props":843,"children":844},{"style":365},[845],{"type":37,"value":603},{"type":32,"tag":292,"props":847,"children":848},{"style":309},[849],{"type":37,"value":850}," {\n",{"type":32,"tag":292,"props":852,"children":854},{"class":294,"line":853},13,[855,860,865,870],{"type":32,"tag":292,"props":856,"children":857},{"style":309},[858],{"type":37,"value":859},"  event_name: eventData.event ",{"type":32,"tag":292,"props":861,"children":862},{"style":365},[863],{"type":37,"value":864},"||",{"type":32,"tag":292,"props":866,"children":867},{"style":335},[868],{"type":37,"value":869}," 'unknown'",{"type":32,"tag":292,"props":871,"children":872},{"style":309},[873],{"type":37,"value":343},{"type":32,"tag":292,"props":875,"children":877},{"class":294,"line":876},14,[878],{"type":32,"tag":292,"props":879,"children":880},{"style":309},[881],{"type":37,"value":882},"  user_data: {\n",{"type":32,"tag":292,"props":884,"children":886},{"class":294,"line":885},15,[887],{"type":32,"tag":292,"props":888,"children":889},{"style":309},[890],{"type":37,"value":891},"    client_id: eventData.client_id,\n",{"type":32,"tag":292,"props":893,"children":895},{"class":294,"line":894},16,[896],{"type":32,"tag":292,"props":897,"children":898},{"style":309},[899],{"type":37,"value":900},"    user_agent: eventData.user_agent,\n",{"type":32,"tag":292,"props":902,"children":904},{"class":294,"line":903},17,[905],{"type":32,"tag":292,"props":906,"children":907},{"style":309},[908],{"type":37,"value":909},"    ip_override: eventData.ip_address\n",{"type":32,"tag":292,"props":911,"children":913},{"class":294,"line":912},18,[914],{"type":32,"tag":292,"props":915,"children":916},{"style":309},[917],{"type":37,"value":918},"  },\n",{"type":32,"tag":292,"props":920,"children":922},{"class":294,"line":921},19,[923],{"type":32,"tag":292,"props":924,"children":925},{"style":309},[926],{"type":37,"value":927},"  event_id: eventData.event_id,\n",{"type":32,"tag":292,"props":929,"children":931},{"class":294,"line":930},20,[932,937,942],{"type":32,"tag":292,"props":933,"children":934},{"style":309},[935],{"type":37,"value":936},"  timestamp_micros: eventData.timestamp ",{"type":32,"tag":292,"props":938,"children":939},{"style":365},[940],{"type":37,"value":941},"*",{"type":32,"tag":292,"props":943,"children":944},{"style":423},[945],{"type":37,"value":946}," 1000000\n",{"type":32,"tag":292,"props":948,"children":950},{"class":294,"line":949},21,[951],{"type":32,"tag":292,"props":952,"children":953},{"style":309},[954],{"type":37,"value":955},"};\n",{"type":32,"tag":292,"props":957,"children":959},{"class":294,"line":958},22,[960],{"type":32,"tag":292,"props":961,"children":962},{"emptyLinePlaceholder":728},[963],{"type":37,"value":731},{"type":32,"tag":292,"props":965,"children":967},{"class":294,"line":966},23,[968,973,977,982],{"type":32,"tag":292,"props":969,"children":970},{"style":315},[971],{"type":37,"value":972},"logToConsole",{"type":32,"tag":292,"props":974,"children":975},{"style":309},[976],{"type":37,"value":613},{"type":32,"tag":292,"props":978,"children":979},{"style":335},[980],{"type":37,"value":981},"'Normalized event:'",{"type":32,"tag":292,"props":983,"children":984},{"style":309},[985],{"type":37,"value":986},", normalizedEvent);\n",{"type":32,"tag":292,"props":988,"children":990},{"class":294,"line":989},24,[991,996,1001,1006],{"type":32,"tag":292,"props":992,"children":993},{"style":315},[994],{"type":37,"value":995},"runContainer",{"type":32,"tag":292,"props":997,"children":998},{"style":309},[999],{"type":37,"value":1000},"(normalizedEvent, () ",{"type":32,"tag":292,"props":1002,"children":1003},{"style":365},[1004],{"type":37,"value":1005},"=>",{"type":32,"tag":292,"props":1007,"children":1008},{"style":309},[1009],{"type":37,"value":850},{"type":32,"tag":292,"props":1011,"children":1013},{"class":294,"line":1012},25,[1014,1019],{"type":32,"tag":292,"props":1015,"children":1016},{"style":315},[1017],{"type":37,"value":1018},"  returnResponse",{"type":32,"tag":292,"props":1020,"children":1021},{"style":309},[1022],{"type":37,"value":744},{"type":32,"tag":292,"props":1024,"children":1026},{"class":294,"line":1025},26,[1027],{"type":32,"tag":292,"props":1028,"children":1029},{"style":309},[1030],{"type":37,"value":452},{"type":32,"tag":33,"props":1032,"children":1033},{},[1034,1036,1041,1043,1049,1051,1057,1059,1065,1067,1073],{"type":37,"value":1035},"Bu client ",{"type":32,"tag":62,"props":1037,"children":1039},{"className":1038},[],[1040],{"type":37,"value":564},{"type":37,"value":1042}," path'ine gelen POST'ları yakalar, JSON body'yi parse eder ve sGTM event model'ine dönüştürür. ",{"type":32,"tag":62,"props":1044,"children":1046},{"className":1045},[],[1047],{"type":37,"value":1048},"runContainer()",{"type":37,"value":1050}," çağrısı tag'lerin çalışmasını tetikler — GA4 tag ",{"type":32,"tag":62,"props":1052,"children":1054},{"className":1053},[],[1055],{"type":37,"value":1056},"event_name=purchase",{"type":37,"value":1058}," gördüğünde Measurement Protocol'e, Meta CAPI tag ",{"type":32,"tag":62,"props":1060,"children":1062},{"className":1061},[],[1063],{"type":37,"value":1064},"user_data.email",{"type":37,"value":1066}," varsa SHA-256 hash'leyip ",{"type":32,"tag":62,"props":1068,"children":1070},{"className":1069},[],[1071],{"type":37,"value":1072},"\u002Fevents",{"type":37,"value":1074}," endpoint'ine gönderir.",{"type":32,"tag":33,"props":1076,"children":1077},{},[1078,1080,1085,1087,1092,1094,1100,1102,1108],{"type":37,"value":1079},"Production setup'ta 4 client çalıştırıyoruz: (1) GA4 default client (",{"type":32,"tag":62,"props":1081,"children":1083},{"className":1082},[],[1084],{"type":37,"value":556},{"type":37,"value":1086},"), (2) custom JSON client (",{"type":32,"tag":62,"props":1088,"children":1090},{"className":1089},[],[1091],{"type":37,"value":564},{"type":37,"value":1093},"), (3) Meta Pixel client (",{"type":32,"tag":62,"props":1095,"children":1097},{"className":1096},[],[1098],{"type":37,"value":1099},"\u002Ftr\u002F",{"type":37,"value":1101}," endpoint — Facebook SDK uyumluluğu için), (4) health check client (",{"type":32,"tag":62,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":37,"value":1107},"\u002Fhealth",{"type":37,"value":1109},") — Cloud Run liveness probe bu endpoint'i ping'leyerek container'ın sağlığını kontrol ediyor. Her client'ın öncelik sırası var (priority number) — aynı path'e iki client claim ederse en yüksek priority kazanır.",{"type":32,"tag":33,"props":1111,"children":1112},{},[1113,1115,1121,1123,1129],{"type":37,"value":1114},"Custom template'leri version control altında tutmak kritik. Google Tag Manager'ın web UI'ında yapılan değişiklikler git history'sinde görünmez. Bizim workflow: template'leri ",{"type":32,"tag":62,"props":1116,"children":1118},{"className":1117},[],[1119],{"type":37,"value":1120},".tpl",{"type":37,"value":1122}," dosyası olarak repo'da tut, CI pipeline'da ",{"type":32,"tag":62,"props":1124,"children":1126},{"className":1125},[],[1127],{"type":37,"value":1128},"gtm-template-push",{"type":37,"value":1130}," CLI tool'u ile sGTM workspace'e deploy et, staging container'da test et, sonra production'a promote et. Bu sayede rollback 1 git revert'le halloluyor.",{"type":32,"tag":40,"props":1132,"children":1134},{"id":1133},"production-monitoring-hangi-metrikler-kritik",[1135],{"type":37,"value":1136},"Production Monitoring: Hangi Metrikler Kritik",{"type":32,"tag":33,"props":1138,"children":1139},{},[1140],{"type":37,"value":1141},"Server-side GTM deploy ettikten sonra karanlıkta kalmamak için 4 katmanda monitoring gerekiyor: (1) container health (uptime, latency, error rate), (2) event throughput (event\u002Fsn, tag success rate), (3) deduplication accuracy (client vs server event count delta), (4) downstream platform validation (Meta Event Quality Score, Google Ads conversion tracking status).",{"type":32,"tag":33,"props":1143,"children":1144},{},[1145],{"type":37,"value":1146},"Cloud Run native metrikleri:",{"type":32,"tag":1148,"props":1149,"children":1150},"ul",{},[1151,1169,1179,1189],{"type":32,"tag":1152,"props":1153,"children":1154},"li",{},[1155,1160,1162,1167],{"type":32,"tag":530,"props":1156,"children":1157},{},[1158],{"type":37,"value":1159},"Request count",{"type":37,"value":1161}," — ",{"type":32,"tag":62,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":37,"value":564},{"type":37,"value":1168}," endpoint'ine gelen POST sayısı, dakikalık breakdown",{"type":32,"tag":1152,"props":1170,"children":1171},{},[1172,1177],{"type":32,"tag":530,"props":1173,"children":1174},{},[1175],{"type":37,"value":1176},"Request latency (p50, p95, p99)",{"type":37,"value":1178}," — median 120ms üzeri ise problem var (normal 40-80ms arası)",{"type":32,"tag":1152,"props":1180,"children":1181},{},[1182,1187],{"type":32,"tag":530,"props":1183,"children":1184},{},[1185],{"type":37,"value":1186},"Container instance count",{"type":37,"value":1188}," — min=1 set ettiyseniz her zaman 1 olmalı, spike'larda auto-scale",{"type":32,"tag":1152,"props":1190,"children":1191},{},[1192,1197],{"type":32,"tag":530,"props":1193,"children":1194},{},[1195],{"type":37,"value":1196},"Error rate (5xx)",{"type":37,"value":1198}," — %0.1 üzeri sürekli hata downstream tag'lerde sorun işareti",{"type":32,"tag":33,"props":1200,"children":1201},{},[1202,1204,1210,1212,1218],{"type":37,"value":1203},"sGTM'in kendi Console'unda \"Logs\" sekmesinde event-level debug log var ama production'da ",{"type":32,"tag":62,"props":1205,"children":1207},{"className":1206},[],[1208],{"type":37,"value":1209},"console.log",{"type":37,"value":1211}," her event için I\u002FO yükü getiriyor. Bizim setup: debug logging sadece ",{"type":32,"tag":62,"props":1213,"children":1215},{"className":1214},[],[1216],{"type":37,"value":1217},"?gtm_debug=1",{"type":37,"value":1219}," query param'ı varsa aktif, production trafikte kapalı. Kritik error'lar (tag HTTP 4xx\u002F5xx) Google Cloud Logging'e JSON structured log olarak gidiyor, oradan Cloud Monitoring alert policy trigger'lıyor — Meta CAPI'den 3 dakika içinde 10+ \"Invalid access token\" hatası gelirse Slack'e ping atıyor.",{"type":32,"tag":33,"props":1221,"children":1222},{},[1223,1225,1231],{"type":37,"value":1224},"Event throughput monitoring için custom metric oluşturuyoruz: sGTM tag'lerinde ",{"type":32,"tag":62,"props":1226,"children":1228},{"className":1227},[],[1229],{"type":37,"value":1230},"sendHttpGet('https:\u002F\u002Fmetrics.roibase.com.tr\u002Fincrement?metric=capi_event')",{"type":37,"value":1232}," çağrısı yapıyoruz, metric service Prometheus formatında counter tutuyor. Bu sayede Grafana dashboard'da real-time event flow görüyoruz — client-side GA4 1000 event\u002Fdk gönderiyor ama server-side CAPI sadece 850 event\u002Fdk alıyorsa deduplication ID collision veya network drop var demektir.",{"type":32,"tag":33,"props":1234,"children":1235},{},[1236,1238,1244,1246,1252],{"type":37,"value":1237},"Downstream platform validation en kritik kısım. Meta Events Manager'da Event Match Quality (EMQ) skoru var — 6.5\u002F10 altı \"düşük kalite\" demek, hash algoritması yanlış veya PII field'ları eksik anlamına geliyor. Google Ads Conversion Tracking'te \"Status: Eligible\" olmalı — \"Rarely used\" veya \"Below threshold\" görünüyorsa conversion volume yeterli değil (minimum 15 conversion\u002F30 gün). GA4 DebugView'da server-side event'ları ",{"type":32,"tag":62,"props":1239,"children":1241},{"className":1240},[],[1242],{"type":37,"value":1243},"traffic_type=server_side",{"type":37,"value":1245}," ile filtrele, ",{"type":32,"tag":62,"props":1247,"children":1249},{"className":1248},[],[1250],{"type":37,"value":1251},"event_count",{"type":37,"value":1253}," metric'i client-side ile kıyasla — %20'den fazla fark varsa investigation gerekiyor.",{"type":32,"tag":40,"props":1255,"children":1257},{"id":1256},"identity-resolution-ve-user-matching-sinyalleri",[1258],{"type":37,"value":1259},"Identity Resolution ve User Matching Sinyalleri",{"type":32,"tag":33,"props":1261,"children":1262},{},[1263,1265,1271,1273,1279,1281,1287,1289,1295,1297,1303,1305,1311,1313,1319,1321,1327,1328,1334,1336,1341,1343,1349,1351,1357,1358,1364],{"type":37,"value":1264},"Server-side ölçümün gücü PII (Personally Identifiable Information) sinyallerini kontrollü şekilde platform'lara iletebilmekte. Meta CAPI 7 farklı user matching parametresi kabul ediyor: ",{"type":32,"tag":62,"props":1266,"children":1268},{"className":1267},[],[1269],{"type":37,"value":1270},"em",{"type":37,"value":1272}," (email hash), ",{"type":32,"tag":62,"props":1274,"children":1276},{"className":1275},[],[1277],{"type":37,"value":1278},"ph",{"type":37,"value":1280}," (phone hash), ",{"type":32,"tag":62,"props":1282,"children":1284},{"className":1283},[],[1285],{"type":37,"value":1286},"fn",{"type":37,"value":1288}," (first name), ",{"type":32,"tag":62,"props":1290,"children":1292},{"className":1291},[],[1293],{"type":37,"value":1294},"ln",{"type":37,"value":1296}," (last name), ",{"type":32,"tag":62,"props":1298,"children":1300},{"className":1299},[],[1301],{"type":37,"value":1302},"ct",{"type":37,"value":1304}," (city), ",{"type":32,"tag":62,"props":1306,"children":1308},{"className":1307},[],[1309],{"type":37,"value":1310},"st",{"type":37,"value":1312}," (state), ",{"type":32,"tag":62,"props":1314,"children":1316},{"className":1315},[],[1317],{"type":37,"value":1318},"zp",{"type":37,"value":1320}," (zip), ",{"type":32,"tag":62,"props":1322,"children":1324},{"className":1323},[],[1325],{"type":37,"value":1326},"country",{"type":37,"value":77},{"type":32,"tag":62,"props":1329,"children":1331},{"className":1330},[],[1332],{"type":37,"value":1333},"external_id",{"type":37,"value":1335}," (CRM ID). Bu sinyaller ne kadar çok gönderilirse EMQ skoru o kadar yüksek çıkıyor — tek ",{"type":32,"tag":62,"props":1337,"children":1339},{"className":1338},[],[1340],{"type":37,"value":1270},{"type":37,"value":1342}," ile 4.2\u002F10, ",{"type":32,"tag":62,"props":1344,"children":1346},{"className":1345},[],[1347],{"type":37,"value":1348},"em + ph + fn + ln",{"type":37,"value":1350}," ile 7.8\u002F10. Google Enhanced Conversions da benzer mantık: ",{"type":32,"tag":62,"props":1352,"children":1354},{"className":1353},[],[1355],{"type":37,"value":1356},"sha256_email_address",{"type":37,"value":272},{"type":32,"tag":62,"props":1359,"children":1361},{"className":1360},[],[1362],{"type":37,"value":1363},"sha256_phone_number",{"type":37,"value":1365}," Ads Conversion tag'ine eklediğinde attribution accuracy %40 artıyor (Google'ın 2025 beta test verisi).",{"type":32,"tag":33,"props":1367,"children":1368},{},[1369,1371,1377,1379,1385],{"type":37,"value":1370},"Roibase'in production identity resolution pipeline: (1) web formunda kullanıcı email\u002Ftelefon giriyor, (2) client-side JS SHA-256 hash'liyor (plain text tarayıcıda tutulmuyor), (3) hash'lenmiş değer DataLayer'a push'lanıyor, (4) sGTM hash'i alıp Meta CAPI'ye ",{"type":32,"tag":62,"props":1372,"children":1374},{"className":1373},[],[1375],{"type":37,"value":1376},"user_data.em",{"type":37,"value":1378}," field'ına, Google'a ",{"type":32,"tag":62,"props":1380,"children":1382},{"className":1381},[],[1383],{"type":37,"value":1384},"user_data.sha256_email_address",{"type":37,"value":1386}," olarak gönderiyor. Bu akış KVKK\u002FGDPR uyumlu çünkü plain PII asla server log'larına düşmüyor — SHA-256 one-way hash, geri döndürülemez.",{"type":32,"tag":33,"props":1388,"children":1389},{},[1390,1392,1398,1400,1406,1408,1413,1415,1420,1422,1428,1430,1435],{"type":37,"value":1391},"Ek sinyal: ",{"type":32,"tag":62,"props":1393,"children":1395},{"className":1394},[],[1396],{"type":37,"value":1397},"fbp",{"type":37,"value":1399}," (Facebook Browser ID) ve ",{"type":32,"tag":62,"props":1401,"children":1403},{"className":1402},[],[1404],{"type":37,"value":1405},"fbc",{"type":37,"value":1407}," (Facebook Click ID) cookie'lerini server-side okuyup CAPI'ye gönderiyoruz. ",{"type":32,"tag":62,"props":1409,"children":1411},{"className":1410},[],[1412],{"type":37,"value":1397},{"type":37,"value":1414}," cookie client-side Pixel tarafından set ediliyor ama ITP nedeniyle 7 gün sonra expire oluyor; biz server-side okuyup 90 gün TTL ile yeniden yazıyoruz (first-party domain'den set edildiği için ITP bypass). ",{"type":32,"tag":62,"props":1416,"children":1418},{"className":1417},[],[1419],{"type":37,"value":1405},{"type":37,"value":1421}," cookie Facebook reklamdan gelen ",{"type":32,"tag":62,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":37,"value":1427},"fbclid",{"type":37,"value":1429}," query param'ını taşıyor — server-side bu ID'yi parse edip CAPI'nin ",{"type":32,"tag":62,"props":1431,"children":1433},{"className":1432},[],[1434],{"type":37,"value":1405},{"type":37,"value":1436}," field'ına ekleyince Meta attribution'ı 24 saat yerine 28 gün penceresine uzatıyor.",{"type":32,"tag":33,"props":1438,"children":1439},{},[1440,1442,1447,1449,1454,1456,1462,1464,1469,1471,1476,1477,1482,1484,1489,1491,1496,1498,1503,1505,1511],{"type":37,"value":1441},"Google'ın ",{"type":32,"tag":62,"props":1443,"children":1445},{"className":1444},[],[1446],{"type":37,"value":486},{"type":37,"value":1448}," (Google Click ID) mekanizması benzer çalışıyor. Client-side GTM ",{"type":32,"tag":62,"props":1450,"children":1452},{"className":1451},[],[1453],{"type":37,"value":486},{"type":37,"value":1455},"'yi URL'den okuyup ",{"type":32,"tag":62,"props":1457,"children":1459},{"className":1458},[],[1460],{"type":37,"value":1461},"_gcl_aw",{"type":37,"value":1463}," cookie'sine yazıyor, expire 90 gün. Server-side bu cookie'yi okuyup Ads Conversion tag'ine ",{"type":32,"tag":62,"props":1465,"children":1467},{"className":1466},[],[1468],{"type":37,"value":486},{"type":37,"value":1470}," parametresi olarak ekliyoruz. Google'ın server-side Conversion Tracking API'si ",{"type":32,"tag":62,"props":1472,"children":1474},{"className":1473},[],[1475],{"type":37,"value":486},{"type":37,"value":488},{"type":32,"tag":62,"props":1478,"children":1480},{"className":1479},[],[1481],{"type":37,"value":494},{"type":37,"value":1483}," kombinasyonunu unique key olarak kullanıyor — aynı ",{"type":32,"tag":62,"props":1485,"children":1487},{"className":1486},[],[1488],{"type":37,"value":486},{"type":37,"value":1490}," ile 2 conversion gönderirsen platform deduplication yapıyor. Bizim setup'ta ",{"type":32,"tag":62,"props":1492,"children":1494},{"className":1493},[],[1495],{"type":37,"value":486},{"type":37,"value":1497}," cookie yoksa (direct traffic) user'ın ",{"type":32,"tag":62,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":37,"value":232},{"type":37,"value":1504}," client ID'sini fallback olarak ",{"type":32,"tag":62,"props":1506,"children":1508},{"className":1507},[],[1509],{"type":37,"value":1510},"gbraid",{"type":37,"value":1512}," parametresine map'liyoruz — bu Google Analytics attribution'ını Ads'e bağlıyor.",{"type":32,"tag":40,"props":1514,"children":1516},{"id":1515},"compliance-ve-consent-orchestration",[1517],{"type":37,"value":1518},"Compliance ve Consent Orchestration",{"type":32,"tag":33,"props":1520,"children":1521},{},[1522,1524,1530,1532,1538],{"type":37,"value":1523},"Server-side tagging Consent Mode v2 ile entegre çalışmazsa GDPR ihlali riski var. Google'ın kuralı: ",{"type":32,"tag":62,"props":1525,"children":1527},{"className":1526},[],[1528],{"type":37,"value":1529},"ad_storage=denied",{"type":37,"value":1531}," consent state'inde sGTM Google Ads Conversion tag'i tetiklenmemeli veya sadece anonymized sinyal göndermeli (IP masking + user ID drop). Meta'nın Limited Data Use (LDU) sistemi benzer: California trafiği için ",{"type":32,"tag":62,"props":1533,"children":1535},{"className":1534},[],[1536],{"type":37,"value":1537},"data_processing_options=['LDU']",{"type":37,"value":1539}," parametresi CAPI request'ine eklenince Meta kişiselleştirilmiş reklam için veriyi kullanmıyor.",{"type":32,"tag":33,"props":1541,"children":1542},{},[1543,1545,1551,1552,1558,1559,1565,1566,1572,1574,1580,1582,1587,1589,1595,1597,1603],{"type":37,"value":1544},"Bizim consent orchestration stack: (1) OneTrust\u002FCookiebot banner'ı user'dan consent alıyor, (2) consent state (",{"type":32,"tag":62,"props":1546,"children":1548},{"className":1547},[],[1549],{"type":37,"value":1550},"ad_storage",{"type":37,"value":77},{"type":32,"tag":62,"props":1553,"children":1555},{"className":1554},[],[1556],{"type":37,"value":1557},"analytics_storage",{"type":37,"value":77},{"type":32,"tag":62,"props":1560,"children":1562},{"className":1561},[],[1563],{"type":37,"value":1564},"ad_user_data",{"type":37,"value":77},{"type":32,"tag":62,"props":1567,"children":1569},{"className":1568},[],[1570],{"type":37,"value":1571},"ad_personalization",{"type":37,"value":1573},") DataLayer'a push'lanıyor, (3) client-side GTM consent sinyalini cookie'ye yazıyor (",{"type":32,"tag":62,"props":1575,"children":1577},{"className":1576},[],[1578],{"type":37,"value":1579},"_consent_state",{"type":37,"value":1581},"), (4) user ",{"type":32,"tag":62,"props":1583,"children":1585},{"className":1584},[],[1586],{"type":37,"value":564},{"type":37,"value":1588}," POST'u atarken cookie header'da geliyor, (5) server-side GTM custom variable ile cookie'yi parse ediyor, (6) Meta\u002FGoogle tag'lerinde conditional trigger: ",{"type":32,"tag":62,"props":1590,"children":1592},{"className":1591},[],[1593],{"type":37,"value":1594},"{{Consent - Ad Storage}} equals \"granted\"",{"type":37,"value":1596}," ise tag ateşleniyor, ",{"type":32,"tag":62,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":37,"value":1602},"denied",{"type":37,"value":1604}," ise tag skip ediliyor.",{"type":32,"tag":33,"props":1606,"children":1607},{},[1608,1610,1616,1618,1623],{"type":37,"value":1609},"Consent Conversion Modeling (CCM) için ek configuration: Google Ads tag'ine ",{"type":32,"tag":62,"props":1611,"children":1613},{"className":1612},[],[1614],{"type":37,"value":1615},"consent_ad_user_data=true",{"type":37,"value":1617}," eklenirse denial durumunda da anonymized sinyal gönderilebiliyor (modeling için gerekli). Meta CCM yoktu 2025'e kadar, 2026'da Advanced Matching v2 ile geldi — ",{"type":32,"tag":62,"props":1619,"children":1621},{"className":1620},[],[1622],{"type":37,"value":1333},{"type":37,"value":1624}," gönderilirse denial durumunda Meta encrypted ID ile cross-device attribution yapabiliyor. Production'da test setup: trafiğin %10'unu force-deny consent moduna sokup conversion rate delta'sını ölçüyoruz — denial durumunda attribution %35 düşüyor ama CCM ile %18'e çıkıyor.",{"type":32,"tag":33,"props":1626,"children":1627},{},[1628,1637],{"type":32,"tag":1629,"props":1630,"children":1634},"a",{"href":1631,"rel":1632},"https:\u002F\u002Fwww.roibase.com.tr\u002Ftr\u002Ffirstparty",[1633],"nofollow",[1635],{"type":37,"value":1636},"First-Party Veri & Ölçüm Mimarisi",{"type":37,"value":1638}," kapsamında server-side GTM sadece ölçüm katmanı — altında identity graph, customer data warehouse ve semantic layer olmalı. sGTM BigQuery'ye event stream atıyor, dbt modeli daily partition'lardan user-level aggregation yapıyor, CDP (Customer Data Platform) bu data'yı okuyup segment'leri Meta Custom Audience ve Google Customer Match'e push'luyor. Bu pipeline'ın orchestration'ı Airflow ile — sGTM log export → BigQuery → dbt → CDP → platform sync tüm zincir 15 dakikada tamamlanıyor.",{"type":32,"tag":1640,"props":1641,"children":1642},"hr",{},[],{"type":32,"tag":33,"props":1644,"children":1645},{},[1646],{"type":37,"value":1647},"Server-side GTM artık \"nice to have\" değil — cookie-less dünyada attribution kurmanın tek yolu. Cloud Run deploy ile başla, deduplication ID'yi doğru kur, PII sinyallerini hash'leyerek gönder, downstream platform metriklerini monitoring et. İlk hafta event volume'u %100 match etmese de iteratif debugging ile production-ready hale gelir. Şu an client-side ölçümle idare ediyorsan 6 ay içinde attribution karanlığına girersin — server-side migration yol haritasını bu hafta oluştur, infra setup'ını 2 sprint'te tamamla.",{"type":32,"tag":1649,"props":1650,"children":1651},"style",{},[1652],{"type":37,"value":1653},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":326,"depth":326,"links":1655},[1656,1657,1658,1659,1660,1661],{"id":42,"depth":305,"text":45},{"id":104,"depth":305,"text":107},{"id":520,"depth":305,"text":523},{"id":1133,"depth":305,"text":1136},{"id":1256,"depth":305,"text":1259},{"id":1515,"depth":305,"text":1518},"markdown","content:tr:data:server-side-gtm-ve-conversion-api-sifirdan-productiona.md","content","tr\u002Fdata\u002Fserver-side-gtm-ve-conversion-api-sifirdan-productiona.md","tr\u002Fdata\u002Fserver-side-gtm-ve-conversion-api-sifirdan-productiona","md",1778277803938]