Proje: Okul Platform · Hub: Okul Platform — Architecture
GA event flow — end-to-end
Bir FE event’i, call site’dan GA4’e ulaşana kadar 5 katman geçer. Her biri ayrı dosyada yaşıyor; birinin eksik/yanlış yüklenmesi tüm zincirin patlamasına neden olur.
Zincir
┌─────────────────────────────────────────────────────────┐
│ 1. Call site │
│ general.js / app.js / inline blade script │
│ → gaSendEventOtp('Submit', 'OTPRequest') │
└───────────────────┬─────────────────────────────────────┘
│ (function call)
▼
┌─────────────────────────────────────────────────────────┐
│ 2. Typed helper │
│ resources/assets/scripts/gaEvents.js │
│ gaSendEventOtp(...) / gaSendEventLogin(...) / ... │
│ → ga4EventParseAndSend('Login', 'gaEventLogin', {}) │
└───────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 3. Generic dispatcher │
│ resources/assets/scripts/gaEvents.js │
│ ga4EventParseAndSend(name, customName, params) │
│ → strips null/empty params │
│ → ga4Event(name, customName, params) │
└───────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 4. dataLayer push (Blade-inline) │
│ resources/views/includes/events/base.blade.php │
│ ga4Event(eventName, customEventName, parameters) │
│ → parameters.event = eventName │
│ → parameters.customEventName = customEventName │
│ → dataLayer.push(parameters) │
│ (admin user'larda console.log yapar, push ETMEZ) │
└───────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ 5. GTM snippet consumer │
│ resources/views/includes/gtm.blade.php │
│ GTM loader (only if $gtmContainerId is set) │
│ → GTM yakalar, GA4 tag'ine forward eder │
│ → GA4 event kaydı │
└─────────────────────────────────────────────────────────┘
Katman detayları + gotcha’lar
Katman 1: Call site
- Desktop:
resources/assets/scripts/frontend/general.js(bundle:main.min.js) - Mobile:
resources/assets/scripts/mobile/app.js(bundle:mobile.min.js) - Page-specific: blade içinde inline
<script>(customer login örneği) - Kural: helper DEFINE etmez, yalnızca CALL eder.
gaSendEventXxxhelper’ları gaEvents.js’te olmalı. Bkz. 2026-04-14-ga-event-helper-location.
Katman 2 & 3: gaEvents.js (typed helpers + dispatcher)
- Dosya:
resources/assets/scripts/gaEvents.js - webpack.mix.js’te iki yerde:
main.min.jsbundle’ına dahil (desktop)mobile.min.jsbundle’ına dahil (mobile)mix.copy(...)ilepublic/assets/scripts/gaEvents.jsstandalone kopya (customer panel gibi ayrı pipeline kullanan sayfalar için, 2026-04-14 eklendi)
- Tipik helper pattern:
function gaSendEventYyy(pageType_, action_, ...) { ga4EventParseAndSend('Yyy', 'gaEventYyy', { ... }); } - Bağımlılık:
ga4Eventfonksiyonuna global erişim. Bu fonksiyon gaEvents.js’te YOK → katman 4’te.
Katman 4: includes.events.base (ga4Event + gaEvent)
- Dosya:
resources/views/includes/events/base.blade.php - İçerik: inline
<script>bloğu —gaEvent(eski Universal Analytics format’ı) vega4Event(GA4 custom event format’ı). ga4Event:function ga4Event(eventName, customEventName, parameters) { parameters.customEventName = customEventName; parameters.event = eventName; dataLayer.push(parameters); // ← dataLayer undefined ise ReferenceError! }- Admin user özel davranış:
@if(Auth::check() && Auth::user()->isAdmin())→console.logyapar, dataLayer.push ETMEZ. Admin test session’ında event’ler GA’ya gitmez, sadece console’a düşer. - Gotcha 1 (incident 2026-04-14): gaEvents.js’in çalışması için bu blade mutlaka önce include edilmiş olmalı. Public site layout’ları onu otomatik include ediyor; customer login gibi ayrı pipeline’larda manuel
@include('includes.events.base')gerekli. Bkz. 2026-04-14-gaevents-missing-base.
Katman 5: GTM loader + iframe
- Dosya:
resources/views/includes/gtm.blade.php(head script) +gtm-iframe.blade.php(body noscript fallback) - Container ID env’den okunur:
- Public school site (B2C):
GTM_B2C_CONTAINER_ID→config('services.gtm.b2c_container_id') - Customer/kurumsal (B2B):
GTM_B2B_CONTAINER_ID→config('services.gtm.b2b_container_id')
- Public school site (B2C):
@empty(!$gtmContainerId)guard: env var boşsa GTM snippet HİÇ render edilmez,dataLayerinitialize edilmez.- Gotcha 2 (incident 2026-04-14): local/dev ortamlarda env var yoksa
ga4Event’indataLayer.pushçağrısıReferenceError: dataLayer is not definedfırlatır. Çözüm:<script>window.dataLayer = window.dataLayer || [];</script>shim’i gtm include’dan ÖNCE veya en azından events.base’den önce eklemek — env boş olsa bile boş array yaratır, push sessizce no-op olur.
Doğru yükleme sırası (page head)
{{-- 1. dataLayer shim (GTM config boş olsa bile güvenli) --}}
<script>window.dataLayer = window.dataLayer || [];</script>
{{-- 2. GTM snippet (config doluysa render eder) --}}
@include('includes.gtm', ['gtmContainerId' => config('services.gtm.xxx_container_id')])
{{-- 3. ga4Event / gaEvent inline tanımı --}}
@include('includes.events.base')
{{-- 4. Tipli helper'lar --}}
<script src="{{ asset('assets/scripts/gaEvents.js') }}"></script>
{{-- 5. pageType globali (isteğe bağlı ama event'lerde default olarak kullanılıyor) --}}
<script>var _gaEventCat = 'PageName';</script>
{{-- Body'de GTM noscript iframe --}}
@include('includes.gtm-iframe', ['gtmContainerId' => config('services.gtm.xxx_container_id')])Bundle edilmiş sayfalar (public/mobile) için 3, 4 zaten main.min.js/mobile.min.js içinde — sadece 1, 2 ve 5 layout tarafından sağlanır.
Hata fırlatma özeti
| Hata | Olası neden |
|---|---|
ReferenceError: ga4Event is not defined | includes.events.base include EDİLMEMİŞ. |
ReferenceError: dataLayer is not defined | GTM snippet render edilmemiş (env var boş) VE shim eklenmemiş. |
ReferenceError: gaSendEventLogin is not defined | gaEvents.js yüklenmemiş (bundle dahil değil, standalone <script src> eksik). |
ReferenceError: _csrfToken / _gaEventCat is not defined | Layout’ın <script>var _xxx = '...'</script> init’i eksik. |
Debugging
dataLayerarray’ini console’da incele:dataLayer.push’lar görünüyor mu?- Admin user değilsen push’lar GA’ya gitmeli. Admin isen sadece console.log.
- GTM Preview mode açıp browser’da
gtm.jsyüklenip yüklenmediğini ve event’leri dinle. - GA4 DebugView’da real-time event kaydını izle.
Related
- 2026-04-14-ga-event-helper-location — gaEvents.js’teki helper konvansiyonu
- 2026-04-14-gaevents-missing-base — ga4Event undefined incident
- 2026-04-14-customer-project-separate-bundle — customer sayfaları neden manuel include gerektiriyor
- 2026-04-14-fe-style-js-locations — hangi bundle hangi sayfada yüklü