304a344955
Yeni component'ler:
- CookieBanner (sağ alt banner + tam ekran ayarlar modal)
- 'Tümünü kabul', 'Tümünü reddet', 'Ayarları yönet'
- 4 kategori toggle: Zorunlu / Analitik / Reklam / Tercih
- Zorunlu kategori her zaman açık (KVKK)
- localStorage + cookie persistence (12 ay TTL)
- Versionlı (CONSENT_VERSION=1) — şema değişince yeniden sorma
- window.openCookieSettings() global helper (footer/policy sayfasından çağrılabilir)
- ConsentInit (Google Consent Mode v2 default deny)
- beforeInteractive Script ile gtag default deny yüklenir
- User onayladığında banner gtag('consent','update', ...) çağırır
- seo_settings.gtm_id doluysa GTM injection (asenkron)
- CookieSettingsButton (politika sayfasında 'ayarları değiştir')
Yeni sayfa:
- /cerez-politikasi — KVKK uyumlu çerez politikası metni
- 4 kategori detaylı açıklama + örnek çerez isimleri
- KVKK Madde 11 kapsamındaki kullanıcı hakları
- İletişim bilgileri site_settings'ten
Layout entegrasyonu:
- app/layout.tsx — ConsentInit head'e, CookieBanner body sonuna
- Footer'a 'Çerez Politikası' linki
Consent flag mapping (Consent Mode v2):
- Zorunlu → functionality_storage + security_storage (her zaman granted)
- Analitik → analytics_storage
- Reklam → ad_storage + ad_user_data + ad_personalization
- Tercih → personalization_storage
Önemli: Default state 'denied' — kullanıcı seçim yapmadan
hiçbir analytics/ads çerezi tetiklenmez. Google Ads Consent Mode v2 uyumlu.
31 route, public sayfalar static (1m revalidate).
53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import Script from "next/script";
|
||
|
||
/**
|
||
* Google Consent Mode v2 — defaults set to "denied" before any tag loads.
|
||
* After the user makes a choice, CookieBanner calls gtag('consent','update', ...).
|
||
*
|
||
* GTM/GA inject sadece site_settings.gtm_id doluysa yapılır.
|
||
*/
|
||
export function ConsentInit({ gtmId }: { gtmId?: string | null }) {
|
||
return (
|
||
<>
|
||
<Script id="consent-default" strategy="beforeInteractive">
|
||
{`
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag(){dataLayer.push(arguments);}
|
||
window.gtag = gtag;
|
||
gtag('consent', 'default', {
|
||
ad_storage: 'denied',
|
||
ad_user_data: 'denied',
|
||
ad_personalization: 'denied',
|
||
analytics_storage: 'denied',
|
||
functionality_storage: 'granted',
|
||
personalization_storage: 'denied',
|
||
security_storage: 'granted',
|
||
wait_for_update: 500,
|
||
});
|
||
`}
|
||
</Script>
|
||
|
||
{gtmId && (
|
||
<>
|
||
<Script id="gtm-script" strategy="afterInteractive">
|
||
{`
|
||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});
|
||
var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';
|
||
j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||
})(window,document,'script','dataLayer','${gtmId}');
|
||
`}
|
||
</Script>
|
||
<noscript>
|
||
<iframe
|
||
src={`https://www.googletagmanager.com/ns.html?id=${gtmId}`}
|
||
height="0"
|
||
width="0"
|
||
style={{ display: "none", visibility: "hidden" }}
|
||
/>
|
||
</noscript>
|
||
</>
|
||
)}
|
||
</>
|
||
);
|
||
}
|