Next.js, Gatsby ve Statik Siteler için Çerez İzni: Geliştiriciler İçin Entegrasyon Rehberi
Statik Site İzin Sorunu
Next.js, Gatsby ve Nuxt.js gibi modern JavaScript framework’leri, web sayfalarının oluşturulma ve sunulma biçiminde bir paradigma değişimi getirdi. Sayfalar, derleme anında veya sunucuda önceden oluşturulur, ardından istemci tarafında hydrate edilir. Bu durum çerez izni için benzersiz bir zorluk yaratır: izin banner’ı, herhangi bir takip script’i çalışmadan önce hazır olmalıdır, ancak sayfanın kendisi çoktan oluşturulmuş ve edge’de cache’lenmiş olabilir.
Geleneksel CMP’ler, belgenin yukarıdan aşağıya doğrusal biçimde yüklendiği, sunucu taraflı render edilen PHP veya basit HTML sayfalar için tasarlandı. Kod bölme, lazy loading ve streaming server-side rendering kullanılan bir framework dünyasında bu varsayımlar bozulur. Bu ortamlarda doğru izin yönetimi için render hattını (rendering pipeline) anlamak gerekir.
Zamanlamanın Düşündüğünüzden Daha Önemli Olmasının Nedeni
Standart bir HTML sayfasında, bir CMP script’ini diğer script’lerden önce <head> içine yerleştirmek basittir. Next.js App Router veya Gatsby’de durum daha karmaşıktır:
- Önceden oluşturulmuş HTML önce gelir: Tarayıcı, CDN veya sunucudan tam HTML alır. Bu HTML içine gömülü herhangi bir inline script veya üçüncü taraf etiketi varsa, izin mantığınız yüklenmeden önce çalışabilir.
- Hydration boşluğu: React hydration, HTML boyandıktan sonra gerçekleşir. İzin bileşeniniz bir React bileşeniyse, hydration tamamlanana kadar işlevsel bir durumda değildir. Bu boşluk sırasında Google etiketleri veya analitik script’leri izinsiz tetiklenebilir.
- Edge cache karmaşıklıkları: ISR (Incremental Static Regeneration) veya edge fonksiyonları kullanıyorsanız HTML cache’lenir. İstemci taraflı bir mekanizma olmadan, izin durumuna bağlı mantığı cache’lenmiş HTML’ye dinamik olarak enjekte edemezsiniz.
Temel ilke şudur: izin, bileşen seviyesinde değil, script seviyesinde tesis edilmelidir. Bir izin banner’ı render eden React bileşeni, yalnızca hydration’dan sonra etkileşimli hale geliyorsa çok geç kalmış demektir.
Next.js App Router Entegrasyonu
App Router’lı Next.js 13+ script’leri ele almak için yeni bir yol sundu. İzin entegrasyonu için önerilen yaklaşım şöyledir:
Adım 1: CMP Script’ini Kök Layout’ta Yükleyin
Kök layout.tsx dosyanızda, Next.js Script bileşenini beforeInteractive stratejisiyle kullanın. Bu, Next.js’e script’i, hydration başlamadan önce, ilk HTML belgesine enjekte etmesini söyler:
beforeInteractive stratejisi kritiktir. Varsayılan afterInteractive stratejisi script’leri hydration’dan sonra yükler; bu da izin için çok geçtir. beforeInteractive ile CMP script’i sunucu taraflı oluşturulan HTML’ye dahil edilir ve sayfa yüklenirken çalışır.
Adım 2: Google Etiketlerinden Önce Varsayılan İzinleri Ayarlayın
Google Tag Manager veya gtag.js snippet’inizden önce, varsayılan izin durumlarını ayarlayan bir inline script ekleyin. Böylece GTM, CMP banner’ı görünmeden önce bile yüklense, reddedilmiş varsayılanlara saygı duyar:
Bu inline script, kök layout’unuzun <head> kısmına, CMP ve GTM script’lerinden önce yerleştirilmelidir. Next.js’te bu amaçla layout’unuzun <head> elemanı içinde normal bir <script> etiketi kullanabilirsiniz.
Adım 3: Route Değişimlerini Yönetin
Single-page application gezinmesinde CMP script’i bir kez yüklenir, ancak route değişimleri tam sayfa yenilemesi tetiklemez. CMP’niz istemci taraflı gezinmeler boyunca kalıcı olmalıdır. FlexyConsent bunu otomatik olarak halleder — bir kez yüklendikten sonra, yeniden başlatmaya gerek kalmadan tüm route değişimlerinde etkin kalır.
Next.js Pages Router Entegrasyonu
Hâlâ Pages Router kullanan projeler için yaklaşım benzerdir, ancak kök layout yerine _document.tsx kullanılır. CMP script’ini özel Document sınıfınızın <Head> bileşenine yerleştirin. beforeInteractive stratejisi Pages Router’da da aynı şekilde çalışır.
Temel fark, _document.tsx’in yalnızca sunucuda render edilmesidir; bu nedenle buradaki tüm izin mantığının ilk HTML yükünde yer alacağı garanti edilir.
Gatsby Statik Site Entegrasyonu
Gatsby, derleme anında tamamen statik HTML üretir. İstek anında sunucu taraflı render yoktur; bu bazı yönleri basitleştirirken bazılarını zorlaştırır:
- CMP script’ini her sayfanın
<head>kısmına enjekte etmek içingatsby-ssr.tsxkullanın.onRenderBodyAPI’si, her statik HTML dosyasında bulunacak script’leri head’e eklemenize olanak tanır. - İzni lazy-load eden Gatsby eklentilerinden kaçının: Bazı topluluk eklentileri, yalnızca hydration’dan sonra mount olan React bileşenleri içinde izin mantığını sarar. Bu, daha önce bahsedilen zamanlama boşluğunu oluşturur.
- Varsayılan izinleri inline yerleştirin: Varsayılan izin durumlarını ayarlayan bir inline script eklemek için
gatsby-ssr.tsxiçindekisetHeadComponentsfonksiyonunu kullanın. Bu script statik HTML’de yer alır ve anında çalışır.
Gatsby’nin derleme zamanı yaklaşımı, CDN’nizdeki her HTML dosyasının izin script’ini içereceği anlamına gelir. Bu aslında idealdir — bozulacak veya yanlış cache’lenecek bir sunucu mantığı yoktur.
Nuxt.js İçin Dikkat Edilecekler
Vue tabanlı Nuxt.js’in kendine özgü kalıpları vardır. Nuxt 3’te, CMP script’ini global olarak eklemek için useHead composable’ını veya nuxt.config.ts içindeki app head yapılandırmasını kullanın. Nuxt, script’leri head’e yerleştiren body: false seçeneğini ve engelleyici olmayan yükleme için async özniteliğini destekler.
Nuxt’ün server-side rendering modunda da aynı ilke geçerlidir: CMP script’i, mount sonrası bir Vue bileşeni tarafından dinamik olarak enjekte edilmek yerine, ilk HTML yanıtında yer almalıdır.
Layout Shift’ten Kaçınma
İzin banner’ları, SEO sıralamalarını etkileyen bir Core Web Vital olan Cumulative Layout Shift (CLS)’e neden olmalarıyla ünlüdür. Banner sayfa render edildikten sonra ortaya çıktığında, içeriği aşağı iter veya beklenmedik şekilde üzerine biner.
İzin banner’larından kaynaklanan CLS’yi en aza indirme stratejileri:
- Alt konumlu bir banner kullanın: Görünüm alanının (viewport) altında yer alan banner’lar sayfa içeriğini kaydırmaz. CLS açısından en uygun yaklaşımdır.
- Alan ayırın: Üst banner kullanmak zorundaysanız, sayfa yerleşimi banner render edilmeden önce onu hesaba katsın diye CSS’inizde dikey alan ayırın.
- Yüklemede modal overlay’lerden kaçının: Sayfa render edildikten sonra görünen tam ekran izin duvarları, algılanan yerleşim dengesizliğine neden olur. Bir duvara ihtiyacınız varsa, onu ilk sayfa durumunun parçası olarak render edin.
- CMP’yi head içinde senkron olarak yükleyin: CMP, head içinde render’ı engelleyen bir script olarak yüklendiğinde, banner daha sonra aniden belirmek yerine ilk boyamanın parçası olarak görünebilir.
FlexyConsent’in Framework’ten Bağımsız Yaklaşımı
FlexyConsent, bileşen seviyesinde değil script seviyesinde çalışarak, herhangi bir framework ile — hatta hiçbir framework olmadan — çalışacak şekilde tasarlandı. Bunun neden önemli olduğuna bakalım:
- Tek async script etiketi:
<head>içinde tek bir<script>etiketi yeterlidir. Kurulacak npm paketi yok, framework’e özel wrapper yok, build yapılandırması yok. - Varsayılan izinler anında tetiklenir: Script, ilk eylemi olarak, herhangi bir callback veya DOM manipülasyonundan önce Consent Mode V2 varsayılanlarını ayarlar. Bu, Google etiketlerinin daha ilk milisaniyeden itibaren izne saygı duyduğu anlamına gelir.
- DOM bağımlılığı yoktur: İzin mantığı, React, Vue veya Svelte’in hydrate olmasını beklemez. Framework yaşam döngüsünden bağımsız çalışır.
- SSG, SSR, ISR ve CSR ile çalışır: Düz bir script olduğu için, sayfa statik olarak oluşturulmuş, sunucu taraflı render edilmiş, artımlı olarak yeniden oluşturulmuş veya istemci taraflı render edilmiş olsun, aynı şekilde çalışır.
Geliştirici ipucu: Doğru CMP entegrasyonunun en basit testi, tarayıcınızın Network sekmesini açmak, Google alan adlarına göre filtrelemek ve sayfayı yeniden yüklemektir. İzin varsayılan komutu konsolda görünmeden önce hiçbir Google isteği tetiklenmemelidir. Eğer tetikleniyorsa, CMP’niz çok geç yükleniyor demektir.
FlexyConsent’in ücretsiz planı, sınırsız sayfa görüntülemesini destekler ve Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix ve düz HTML ile çalışır. Entegrasyon hepsinde aynıdır: doğru yere yerleştirilmiş tek bir script etiketi.