feat(kvkk): çerez politikası, ölçümü kapatma ve ilk ziyaret bilgi bandı
All checks were successful
Deploy / deploy (push) Successful in 6m27s

- /cerez-politikasi: çerez aydınlatma metni (ad, amaç, süre, taraf),
  Rybbit ölçümünün kapsamı ve hukuki dayanağı (KVKK md. 5/2-f,
  Çerez Rehberi Temmuz 2025 §5.9)
- OlcumTercihi: Rybbit'i tarayıcıda kapatan düğme (disable-rybbit)
- CerezBilgi: ilk ziyarette bir kez görünen bilgilendirme (onay
  penceresi değil; rıza gerektiren çerez yok)
- gizlilik: analitik bölümü kodla eşitlendi (e-posta/ad gönderilmiyor)
- alt bilgi ve sitemap'e sayfa eklendi
- docs: hukuki analiz ve meşru menfaat denge testi

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-05 10:11:38 +03:00
parent ff86176d9e
commit 9e4c5608eb
8 changed files with 629 additions and 13 deletions

View File

@@ -0,0 +1,133 @@
# Çerez ve analitik uyumu (5 Ekim 2026)
Soru: Rybbit ile ölçüm yapıyoruz, çerez izni istemiyoruz. Yasal mı, ne eksik?
**Sonuç:** Onay penceresi (kabul/ret) gerekmiyor. Ama aydınlatma eksikti ve Rybbit
panelinde üç ayar politikanın söylediğiyle uyuşmalı. Kod tarafı yapıldı; panel
tarafı Bilal'de (en altta).
> Bu bir avukat görüşü değildir. Kaynak metinler okunarak hazırlandı; yayından önce
> bir KVKK avukatına 30 dakikalık okuma yaptırmak makul.
## 1. Hukuki çerçeve
| Kaynak | Bize etkisi |
|---|---|
| **5809 sayılı Elektronik Haberleşme Kanunu md. 51/3** (cihaza bilgi yazma → açık rıza) | **Uygulanmaz.** Yalnız BTK yetkili "işletmeciler" için. Rehber bunu açıkça söylüyor (§3): site operatörleri kapsam dışı. Türkiye'de AB'deki ePrivacy md. 5/3'ün genel karşılığı yok. |
| **KVKK (6698) md. 4, 5, 10, 11, 12** | **Uygulanır.** Çerez ya da ölçümle kişisel veri işleniyorsa hukuki sebep (md. 5) ve aydınlatma (md. 10) gerekir. |
| **KVKK Çerez Uygulamaları Hakkında Rehber, Temmuz 2025 (Yayın No 69)** | Asıl referans. Bağlayıcı değil ama Kurul kararları bunu izliyor. |
| **Kurul kararı 2020/173** ve 2022'deki 300 bin TL'lik çerez cezası | İkisi de rızasız **reklam/üçüncü taraf analitik** çerezi + aydınlatma yokluğu. Bizim durumumuz değil. |
| **GDPR / ePrivacy** | Site Türkçe, Türkiye'deki YKS adaylarına yönelik; AB'ye hizmet sunma ya da AB'dekileri izleme yok → GDPR md. 3/2 kapsamında değiliz. AB'ye açılırsak `rybbit-user-id` yazımı ePrivacy'de rıza ister; o gün yeniden bakılır. |
### Rehberin bizi ilgilendiren üç hükmü
1. **§5.9 — Birinci taraf analitik çerezler "Kriter B" (rıza gerekmeyen) sayılır.**
2022 sürümünde analitik rıza istiyordu; Temmuz 2025 güncellemesi bunu değiştirdi.
Şartları: yalnız kitle ölçümü, veri ölçülü olmalı ve IP maskelenmeli, **yalnız
anonim istatistik** üretilmeli, siteler arası takip olmamalı, süre makul olmalı,
veri üçüncü tarafa gitmemeli.
2. **§1.2 — local storage, parmak izi, piksel için rehber yönlendirme yapmıyor.**
Yani "çerezsiz" olmak bizi kapsam dışına çıkarmaz ama rıza da doğurmaz; genel
KVKK md. 5 değerlendirmesi yapılır (aşağıdaki denge testi).
3. **§9 — Aydınlatma, hukuki sebepten bağımsız olarak siteye girişte yapılmalı**
("pop-up gibi bir bilgilendirme yoksa aydınlatma yükümlülüğüne aykırılık gündeme
gelebilir") ve çerezin adı, amacı, süresi, birinci/üçüncü taraf oluşu yazılmalı.
Gizlilik metninin içine gömülü tek paragraf yeterli sayılmıyor.
## 2. Sitede gerçekte ne var (koddan ve canlı betikten doğrulandı)
- **Çerezler (hepsi birinci taraf, zorunlu):** better-auth oturum çerezleri,
`kolaytercih.profil`, `kolaytercih.liste-sayi`. Reklam/üçüncü taraf çerez yok.
- **Rybbit:** kendi sunucumuzda, sunucu Türkiye'de (178.211.130.206, Pentech/Bursa)
→ yurt dışı aktarım yok. Çerez yazmıyor. Ama canlı betik (`/api/script.js`)
incelendiğinde:
- Her ziyaretçide localStorage'a `rybbit-visitor-id` yazıyor (yalnız feature flag
açıkken gönderilir; bizde kapalı → gönderilmiyor).
- Girişte localStorage'a `rybbit-user-id` yazıyor ve her olaya ekliyor.
- Anonim ziyaretçiyi IP + tarayıcı bilgisinin özetiyle tanıyor.
- Panel ayarı (herkese açık `tracking-config` ucundan okundu): `trackCopy: true`,
`trackFormInteractions: true`, `trackButtonClicks: true`, `trackUrlParams: true`,
`trackErrors: true`, `webVitals: true`, `sessionReplay: false`.
- **Bulgu A — kopyalama izleme açık.** Kullanıcının kopyaladığı metnin ilk 500
karakteri Rybbit'e gidiyor. Danışman cevabını ya da kendi mesajını kopyalayan
öğrencinin metni analitiğe düşer. "Kitle ölçümü" sınırını aşar; **kapatılmalı.**
- **Bulgu B — gizlilik metni eskimişti.** "E-posta adresin ve adın analitiğe
kaydedilir" diyordu; kod 21 Eylül'den beri (c055e82) yalnız kimlik numarası
gönderiyor. Metin düzeltildi. Rybbit'te o tarihten önce yazılmış e-posta/ad
kayıtları duruyorsa silinmeli.
- **Bulgu C — form izleme zararsız.** Yalnız alan adı/türü gidiyor, değer gitmiyor.
- Ham sıralama: sayfa adreslerinde artık `?sira=` taşınmıyor (yalnız `/api/…`
çağrılarında; Rybbit bunları görmez), `/sonuc` maskeli. Eski satırlar panelde
duruyor olabilir (BACKLOG #31).
## 3. Meşru menfaat denge testi (KVKK md. 5/2-f)
Rehber §4 bu testi yapmayı tavsiye ediyor; kayıt olarak burada dursun.
- **Menfaat:** sitenin hangi sayfalarının kullanıldığını, sihirbazın nerede
bırakıldığını ve hataları görmek. Gerçek, güncel, hukuka uygun.
- **Zorunluluk:** bu bilgi ölçüm olmadan elde edilemiyor; daha az veriyle çalışan
bir yol seçildi (çerez yok, IP saklanmıyor, sıralama bantlı, hassas adresler
maskeli, ekran kaydı kapalı, veri kendi sunucumuzda).
- **Kişiye etkisi:** düşük. Siteler arası takip yok, reklam yok, profil
çıkarılmıyor, üçüncü tarafa aktarım yok. Makul beklenti içinde.
- **Güvenceler:** ayrı çerez politikası, ilk ziyarette bilgilendirme, tek tıkla
kapatma (itiraz hakkı), e-posta/ad analitikte yok.
- **Zayıf nokta:** girişli kullanıcının ziyareti hesap kimliğiyle eşleşiyor. Bu
"anonim istatistik" değil, takma adlı veri; §5.9'un en dar okumasının dışında.
Savunması: yalnız hesabı olan kullanıcıda, yalnız kendi sitemizde, açıkça
bildirilmiş, kapatılabilir. **Kalan risk: düşük-orta.** Sıfıra indirmek istersek
`RybbitIdentify` kaldırılır; bedeli "sihirbaz → giriş → ödeme" hunisinin kişi
bazında birleşmemesi.
- **18 yaş altı:** kitlenin bir kısmı 17 yaşında. Ölçüm pazarlama için
kullanılmadığından ek rıza doğmuyor; metin sade dille yazıldı (Rehber §9).
## 4. Yapılanlar (kod)
- `src/app/cerez-politikasi/page.tsx` — çerez politikası + çerez aydınlatma metni
(ad, amaç, süre, taraf; ölçümün ne topladığı; hukuki dayanak; yönetim).
- `src/components/olcum-tercihi.tsx` — "Ölçümü kapat" düğmesi (Rybbit'in kendi
`disable-rybbit` kapısı; kimlik kayıtlarını da siler).
- `src/components/cerez-bilgi.tsx` + `layout.tsx` — ilk ziyarette bir kez görünen
bilgi bandı. Kabul/ret yok, çünkü sorulan rıza yok.
- `src/app/gizlilik/page.tsx` — "Çerezler ve analitik" bölümü gerçeğe göre düzeltildi.
- Alt bilgiye ve `sitemap.ts`'e sayfa eklendi.
## 5. Bilal'in yapacakları
**Yayından önce (politika bunları doğru varsayıyor):**
1. Rybbit paneli → site ayarları → **kopyalama izlemeyi (Copy) kapat.** Doğrulama:
`curl -s https://rybbit.kolaytercih.com/api/site/tracking-config/f2cb042c657e`
çıktısında `"trackCopy":false` görünmeli.
2. Aynı ekranda **IP adresi saklama (Track IP Address) kapalı** mı bak (varsayılan
kapalı). Açıksa kapat.
3. **Oturum kaydı (Session Replay) kapalı kalsın.** Açılacaksa önce politika ve
denge testi güncellenir.
**Yakın zamanda:**
4. Rybbit kullanıcılar ekranında 21 Eylül öncesinden kalan **e-posta/ad** kayıtları
varsa sil.
5. "User ID Salting" ayarı: açılırsa anonim ziyaretçi kimliği her gün sıfırlanır
(en temiz hâl), bedeli girişsiz ziyaretçide "geri dönen" ölçümünün kaybı. Karar
senin; politika iki hâlde de doğru.
6. Ölçüm verisi için saklama süresi belirle (öneri: 24 ay) ve belirleyince
politikaya yaz.
7. Gizlilik sayfasındaki `[şirket unvanı ve adresi eklenecek]` hâlâ boş; çerez
politikası veri sorumlusu için o sayfaya atıf yapıyor.
8. Bilgi bandını telefonda bir kez gözle kontrol et (alt kenarda, `KaydetBanner`
ile aynı yerde, onun üstünde açılır).
## 6. Ne zaman onay penceresi gerekir
Şunlardan biri eklendiği gün: Google Analytics / Meta Pixel / TikTok Pixel, reklam
ya da yeniden hedefleme, gömülü YouTube/sosyal eklenti, Rybbit oturum kaydı, Rybbit
bulut sürümüne geçiş (üçüncü taraf + yurt dışı). O gün "Kabul et" ile "Reddet"
eşit görünürlükte olmalı ve rıza verilmeden betik yüklenmemeli.
## Kaynaklar
- KVKK, Çerez Uygulamaları Hakkında Rehber (Temmuz 2025): https://www.kvkk.gov.tr/Icerik/7353/Cerez-Uygulamalari-Hakkinda-Rehber
- Erdem & Erdem, rehber güncellemesi notu (28.07.2025): https://www.erdem-erdem.av.tr/bilgi-bankasi/kisisel-verileri-koruma-kurumu-cerez-uygulamalari-hakkinda-rehberi-guncelledi
- Rybbit site ayarları: https://rybbit.com/docs/site-settings

View File

@@ -0,0 +1,312 @@
import type { Metadata } from "next";
import Link from "next/link";
import { Parallax } from "@/components/parallax";
import { PagePixelDivider } from "@/components/pixel-decor";
import { SiteFooter } from "@/components/site-footer";
import { OlcumTercihi } from "@/components/olcum-tercihi";
import { sayfaMetadata } from "@/lib/seo";
export const metadata: Metadata = sayfaMetadata({
title: "Çerez Politikası",
description:
"KolayTercih çerez politikası ve çerez aydınlatma metni: hangi çerezler kullanılır, ziyaret ölçümü nasıl çalışır ve nasıl kapatılır.",
path: "/cerez-politikasi",
});
// Bu metin kodun ve Rybbit panel ayarlarının GERÇEKTE yaptığıyla birebir
// örtüşmek zorunda. Aşağıdakilerden biri değişirse aynı commit'te güncellenir:
// - çerez / localStorage / sessionStorage anahtarı eklenir ya da süresi değişir
// (auth.ts, sihirbaz-profil.ts, liste-store.ts, tema-saglayici.tsx),
// - layout.tsx'teki Rybbit betiğinin ayarı ya da paneldeki izleme ayarı
// (kopyalama izleme, oturum kaydı, IP saklama) değişir,
// - yeni bir üçüncü taraf betiği / gömülü içerik eklenir.
// Açık rıza gerektiren bir çerez (reklam, yeniden hedefleme, üçüncü taraf
// analitik, sosyal eklenti) eklenecekse ÖNCE onay penceresi kurulur.
// Hukuki dayanak ve denge testi: docs/ekip-raporlari/2026-10-05/cerez-uyum.md
type Kayit = { ad: string; amac: string; sure: string };
const CEREZLER: Kayit[] = [
{
ad: "better-auth.session_token, better-auth.session_data",
amac: "Giriş yaptığında oturumunu açık tutar. Giriş yapmadıysan oluşmaz.",
sure: "Oturum çerezi 7 gün (kullandıkça yenilenir); önbellek çerezi 5 dakika",
},
{
ad: "kolaytercih.profil",
amac: "Sihirbazda girdiğin sıralama ve seçimleri (puan türü, alan, il, devlet/vakıf) taşır; sonuç sayfası senin sıralamana göre hazırlanır.",
sure: "1 yıl ya da sen profilini silene kadar",
},
{
ad: "kolaytercih.liste-sayi",
amac: "Listende kaç program olduğunu taşır; sayfa açılırken liste düğmesi doğru sayıyla gelir.",
sure: "1 yıl",
},
];
const DEPO: Kayit[] = [
{
ad: "kolaytercih.sihirbaz",
amac: "Sıralaman ve sihirbaz seçimlerin; yeniden girmek zorunda kalmaman için.",
sure: "Sen silene kadar",
},
{
ad: "kolaytercih.manuel-liste.v1",
amac: "Kendi eklediğin tercih listesi; giriş yapmadan da listen kaybolmasın diye.",
sure: "Sen silene kadar",
},
{
ad: "kt-tema",
amac: "Açık / koyu tema tercihin.",
sure: "Sen değiştirene kadar",
},
{
ad: "kolaytercih.cerez-bilgi",
amac: "Çerez bilgilendirmesini gördüğünü hatırlar; tekrar tekrar çıkmaz.",
sure: "Sen silene kadar",
},
{
ad: "disable-rybbit",
amac: "Ölçümü kapattıysan bu tercihini hatırlar.",
sure: "Sen ölçümü yeniden açana kadar",
},
{
ad: "rybbit-user-id",
amac: "Yalnız giriş yaptığında oluşur: hesabının rastgele kimlik numarası. Sihirbazdan girişe uzanan yolculuğun tek ziyaret olarak sayılmasını sağlar. E-postan ve adın bu kayda yazılmaz.",
sure: "Çıkış yapana ya da ölçümü kapatana kadar",
},
{
ad: "rybbit-visitor-id",
amac: "Ölçüm betiğinin tarayıcında ürettiği rastgele sayı. Bugünkü ayarlarımızda sunucuya gönderilmez.",
sure: "Sen silene ya da ölçümü kapatana kadar",
},
{
ad: "Sekme süresince tutulanlar (kolaytercih.olay.*, kolaytercih.kaydet-banner-kapali, kolaytercih.liste-senkron.*, kolaytercih.liste-taban.*)",
amac: "Aynı görüntülemenin iki kez sayılmaması, kapattığın hatırlatmanın geri gelmemesi ve listenin hesabınla bir kez eşitlenmesi için.",
sure: "Sekmeyi kapatınca silinir",
},
];
function KayitListesi({ kayitlar }: { kayitlar: Kayit[] }) {
return (
<dl className="mt-3 space-y-3">
{kayitlar.map((k) => (
<div
key={k.ad}
className="rounded-2xl border border-slate-200 bg-card p-4"
>
<dt className="font-mono text-xs font-semibold break-words text-slate-900">
{k.ad}
</dt>
<dd className="mt-1">{k.amac}</dd>
<dd className="mt-1 text-slate-500">Süre: {k.sure}</dd>
</div>
))}
</dl>
);
}
export default function CerezPolitikasiPage() {
const baslik = "font-heading text-lg font-bold text-slate-900";
return (
<>
<main className="mx-auto w-full max-w-2xl px-4 py-16">
<Parallax fromStart strength={10}>
<h1 className="font-heading text-3xl font-bold">Çerez Politikası</h1>
<p className="mt-2 text-sm text-slate-500">
Son güncelleme: 5 Ekim 2026
</p>
</Parallax>
<PagePixelDivider seed={53} className="mt-6" />
<div className="mt-8 space-y-6 text-sm leading-7 text-slate-700">
<section className="rounded-2xl border border-slate-200 bg-slate-50 p-5">
<h2 className={baslik}>Kısa özet</h2>
<ul className="mt-2 list-disc space-y-1 pl-5">
<li>
Reklam çerezi, izleme çerezi ya da başka şirketlerin analitik
çerezi kullanmıyoruz. Seni başka sitelerde takip eden hiçbir
şey yok.
</li>
<li>
Yalnız sitenin çalışması için gerekli çerezler var: oturumunu
açık tutan, sıralamanı ve listeni hatırlayan çerezler.
</li>
<li>
Hangi sayfaların okunduğunu saymak için kendi sunucumuzda
çalışan, çerez kullanmayan bir ölçüm aracı (Rybbit)
kullanıyoruz. İstersen aşağıdan tek tıkla kapatırsın.
</li>
<li>
Bu yüzden karşına &ldquo;çerezleri kabul et&rdquo; penceresi
çıkmıyor: onayını gerektiren bir çerez yok.
</li>
</ul>
</section>
<section>
<h2 className={baslik}>Bu metin neyi anlatıyor?</h2>
<p className="mt-2">
Çerez, bir sitenin tarayıcına bıraktığı küçük bir metin
dosyasıdır. Bu sayfa, kolaytercih.com&rsquo;un tarayıcına ne
yazdığını, ziyaretini nasıl ölçtüğünü ve bunları nasıl
yönetebileceğini anlatır; 6698 sayılı Kişisel Verilerin Korunması
Kanunu&rsquo;nun (KVKK) 10. maddesi kapsamındaki çerez aydınlatma
metnidir. Veri sorumlusu, diğer kişisel verilerin ve hakların
için{" "}
<Link href="/gizlilik" className="text-primary underline">
Gizlilik ve KVKK
</Link>{" "}
sayfasına bak.
</p>
</section>
<section>
<h2 className={baslik}>Zorunlu çerezler</h2>
<p className="mt-2">
Bunlar olmadan giriş yapamaz, listeni göremezsin; senin istediğin
hizmetin çalışması için gereklidir. Hepsi kolaytercih.com
tarafından yazılır (birinci taraf). Hukuki dayanak: seninle
kurulan hizmet sözleşmesinin ifası ve meşru menfaatimiz (KVKK md.
5/2-c ve 5/2-f).
</p>
<KayitListesi kayitlar={CEREZLER} />
<p className="mt-3">
Google ile ya da e-postandaki bağlantıyla giriş yaparken, giriş
tamamlanana kadar yaşayan kısa ömürlü güvenlik çerezleri de
kullanılabilir. Tarayıcın güvenli bağlantıda bu adların başına{" "}
<span className="font-mono text-xs">__Secure-</span> ekler.
</p>
</section>
<section>
<h2 className={baslik}>Tarayıcında tutulan diğer kayıtlar</h2>
<p className="mt-2">
Bunlar çerez değildir; tarayıcının kendi deposunda durur ve
çerezlerden farklı olarak her istekte sunucuya gitmez. Yine de
bilmen için listeliyoruz.
</p>
<KayitListesi kayitlar={DEPO} />
</section>
<section>
<h2 className={baslik}>Ziyaret ölçümü (Rybbit)</h2>
<p className="mt-2">
Siteyi geliştirebilmek için hangi sayfaların açıldığını ve
sihirbazın hangi adımında bırakıldığını sayıyoruz. Bunun için
açık kaynaklı Rybbit yazılımını Türkiye&rsquo;deki kendi
sunucumuzda çalıştırıyoruz; veriler başka bir şirkete, reklam
ağına ya da yurt dışına gitmez.
</p>
<p className="mt-2">
<strong>Ne kaydedilir:</strong> açtığın sayfanın adresi, hangi
siteden geldiğin, tarayıcın, işletim sistemin, cihaz türün, ekran
boyutun, tarayıcı dilin, yaklaşık konumun (ülke ve şehir
düzeyinde), tıkladığın düğmeler ve dış bağlantılar, doldurduğun
form alanının adı (içine yazdığın değer değil), sayfa hızı
ölçümleri, tarayıcıda oluşan hata kayıtları ve sihirbaz adımı,
liste oluşturma, ödeme başlatma gibi adımların gerçekleşip
gerçekleşmediği.
</p>
<p className="mt-2">
<strong>Ne kaydedilmez:</strong> IP adresin saklanmaz; ziyaretleri
sayabilmek için IP adresin ve tarayıcı bilginden geri
döndürülemeyen bir özet üretilir. Başarı sıralaman ham hâliyle
gönderilmez, yalnız &ldquo;50-100 bin&rdquo; gibi geniş bir
aralık olarak kaydedilir; sıralamanı ve sipariş numaranı taşıyan
sayfa adresleri maskelenir. Forma ya da danışmana yazdıkların,
kopyaladığın metinler ve ekran kaydı alınmaz. E-postan ve adın
ölçüm aracına gönderilmez.
</p>
<p className="mt-2">
<strong>Giriş yaptıysan:</strong> ziyaretin hesabının rastgele
kimlik numarasıyla eşleştirilir. Böylece &ldquo;sihirbazı
dolduranların kaçı liste oluşturdu&rdquo; gibi soruları
yanıtlayabilir, bir sorun bildirdiğinde ne olduğunu
inceleyebiliriz. Bu kayıt reklam, pazarlama ya da profilleme için
kullanılmaz.
</p>
<p className="mt-2">
<strong>Hukuki dayanak:</strong> siteyi yönetmek ve geliştirmek
için ziyaretçi sayısını ve performansı ölçmeye yönelik meşru
menfaatimiz (KVKK md. 5/2-f). Ölçüm yalnız bu sitede yapılır;
başka sitelerdeki gezinmenle birleştirilmez. Bu ölçüme itiraz
edebilirsin: aşağıdaki düğme ölçümü bu tarayıcıda tamamen kapatır.
</p>
<OlcumTercihi />
</section>
<section>
<h2 className={baslik}>Başka şirketlerin çerezleri</h2>
<ul className="mt-2 list-disc space-y-2 pl-5">
<li>
<strong>iyzico (ödeme).</strong> Yalnız ödeme sayfasında, kart
bilgilerini girdiğin form iyzico tarafından gösterilir. iyzico
bu formda ödemenin güvenliği ve dolandırıcılığın önlenmesi için
kendi çerezlerini kullanabilir. Paket satın almıyorsan bu
sayfayı hiç görmezsin.
</li>
<li>
<strong>Google ile giriş.</strong> Bu seçeneği kullanırsan
Google&rsquo;ın giriş sayfasına yönlendirilirsin; orada
Google&rsquo;ın kendi çerez politikası geçerlidir. Sitemizin
içine Google betiği yüklenmez.
</li>
</ul>
<p className="mt-2">
Yazı tipleri, görseller ve ölçüm betiği kendi sunucularımızdan
gelir. Sitede sosyal medya eklentisi, gömülü video ya da reklam
yoktur.
</p>
</section>
<section>
<h2 className={baslik}>Çerezleri nasıl yönetirsin?</h2>
<ul className="mt-2 list-disc space-y-1 pl-5">
<li>Ölçümü yukarıdaki düğmeyle kapatabilirsin.</li>
<li>
Tarayıcının ayarlarından çerezleri ve site verilerini
silebilir ya da tümüyle engelleyebilirsin. Silersen oturumun
kapanır; giriş yapmadan oluşturduğun liste ve sihirbaz
seçimlerin de silinir.
</li>
<li>
Çerezleri tümüyle engellersen giriş yapamazsın; katalog ve
rehber sayfalarını okumaya devam edebilirsin.
</li>
</ul>
</section>
<section>
<h2 className={baslik}>Hakların ve iletişim</h2>
<p className="mt-2">
KVKK&rsquo;nın 11. maddesindeki haklarını (bilgi isteme,
düzeltme, silme, itiraz) kullanmak ya da bu sayfayla ilgili bir
şey sormak için{" "}
<Link href="/iletisim" className="text-primary underline">
iletişim sayfasındaki
</Link>{" "}
e-posta adresine yaz; en geç 30 gün içinde yanıtlarız. Hakların
tam listesi{" "}
<Link href="/gizlilik" className="text-primary underline">
Gizlilik ve KVKK
</Link>{" "}
sayfasında.
</p>
</section>
<section>
<h2 className={baslik}>Değişiklikler</h2>
<p className="mt-2">
Yeni bir çerez ya da ölçüm yöntemi eklersek bu sayfayı aynı gün
güncelleriz. Onayını gerektiren bir çerez eklemeye karar verirsek
önce sana sorarız; onay vermeden o çerez çalışmaz.
</p>
</section>
</div>
</main>
<SiteFooter />
</>
);
}

View File

@@ -233,19 +233,24 @@ export default function GizlilikPage() {
<section>
<h2 className={baslik}>Çerezler ve analitik</h2>
<p className="mt-2">
Yalnızca oturumunu açık tutmak için zorunlu çerezler kullanılır;
reklam veya izleme çerezi kullanılmaz. Siteyi geliştirebilmek için
hangi sayfaların görüntülendiğini ve hangi adımların tamamlandığını
ölçen, çerez kullanmayan bir analitik aracı (Rybbit) çalıştırıyoruz;
bu araç kendi sunucumuzda barındırılır, veriler üçüncü taraf bir
reklam ağına gitmez. Giriş yaptığında ziyaretin hesabınla
eşleştirilir; bunun için e-posta adresin ve hesabındaki adın
(varsa) kendi sunucumuzdaki bu analitik aracına kaydedilir ve
yalnızca sorun giderme ile destek amacıyla kullanılır. Başarı
sıralaman analitiğe ham hâliyle
gönderilmez; yalnızca &ldquo;50-100 bin&rdquo; gibi geniş bir
aralık olarak kaydedilir. Danışman profilindeki değerler
analitiğe gitmez; yalnız hangi alanın kaydedildiği sayılır.
Yalnızca sitenin çalışması için zorunlu çerezler kullanılır
(oturumun, sıralaman ve listen); reklam veya izleme çerezi
kullanılmaz. Siteyi geliştirebilmek için hangi sayfaların
görüntülendiğini ve hangi adımların tamamlandığını ölçen, çerez
kullanmayan bir analitik aracı (Rybbit) çalıştırıyoruz; bu araç
Türkiye&rsquo;deki kendi sunucumuzda barındırılır, veriler üçüncü
taraf bir reklam ağına ya da yurt dışına gitmez. IP adresin
saklanmaz. Giriş yaptığında ziyaretin hesabının rastgele kimlik
numarasıyla eşleştirilir; e-posta adresin ve adın analitiğe
gönderilmez. Başarı sıralaman analitiğe ham hâliyle gönderilmez;
yalnızca &ldquo;50-100 bin&rdquo; gibi geniş bir aralık olarak
kaydedilir. Danışman profilindeki değerler analitiğe gitmez;
yalnız hangi alanın kaydedildiği sayılır. Çerezlerin tam listesi,
ölçümün ayrıntıları ve ölçümü kapatma düğmesi{" "}
<Link href="/cerez-politikasi" className="text-primary underline">
Çerez Politikası
</Link>{" "}
sayfasındadır.
</p>
</section>
</Parallax>

View File

@@ -11,6 +11,7 @@ import { TercihProfiliKapisiLazy } from "@/features/liste/components/tercih-prof
import { HeaderGate } from "@/components/header-gate";
import { DevPanelMount } from "@/components/dev/dev-panel-mount";
import { ConsoleAsr } from "@/components/console-asr";
import { CerezBilgi } from "@/components/cerez-bilgi";
import { JsonLd, organizationJsonLd, webSiteJsonLd, SITE_URL } from "@/lib/seo";
import "./globals.css";
@@ -117,6 +118,8 @@ export default function RootLayout({
<KaydetBannerLazy />
{/* İlk "+" için sıra + sihirbaz kapısı */}
<TercihProfiliKapisiLazy />
{/* İlk ziyarette bir kez: çerez bilgilendirmesi (onay penceresi değil) */}
<CerezBilgi />
<Toaster position="top-center" />
{/* DevTools'u açan meraklıya piksel kum saati + Asr Sûresi */}
<ConsoleAsr />

View File

@@ -44,6 +44,11 @@ const staticEntries: MetadataRoute.Sitemap = [
{ url: `${SITE_URL}/meraklisina`, priority: 0.6, changeFrequency: "monthly" },
{ url: `${SITE_URL}/iletisim`, priority: 0.3, changeFrequency: "yearly" },
{ url: `${SITE_URL}/gizlilik`, priority: 0.2, changeFrequency: "yearly" },
{
url: `${SITE_URL}/cerez-politikasi`,
priority: 0.2,
changeFrequency: "yearly",
},
{ url: `${SITE_URL}/kosullar`, priority: 0.2, changeFrequency: "yearly" },
];

View File

@@ -0,0 +1,80 @@
"use client";
// İlk ziyarette bir kez görünen çerez bilgilendirmesi. Onay penceresi DEĞİL:
// sitede açık rıza gerektiren çerez yok (zorunlu çerezler + kendi
// sunucumuzdaki ölçüm; bkz. /cerez-politikasi). KVKK Çerez Rehberi (Temmuz
// 2025) §9, veri işleme şartından bağımsız olarak siteye girişte
// bilgilendirme bekliyor; bu bant onu karşılar. Kabul/ret düğmesi yoktur,
// çünkü sorulan bir rıza yoktur — ölçümü kapatma anahtarı politika
// sayfasındadır. Kapatma kalıcıdır (localStorage).
import { useEffect, useState } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { Button } from "@/components/ui/button";
import { ViewportPortal } from "@/components/viewport-portal";
import { kromGizliMi } from "@/components/header-gate";
const GORULDU_KEY = "kolaytercih.cerez-bilgi";
export function CerezBilgi() {
const pathname = usePathname();
// SSR/ilk boyada gizli başla; durum mount'ta okunur.
const [goruldu, setGoruldu] = useState(true);
useEffect(() => {
try {
// eslint-disable-next-line react-hooks/set-state-in-effect
setGoruldu(Boolean(localStorage.getItem(GORULDU_KEY)));
} catch {
// Depolama kapalıysa "görüldü" saklanamaz; her sayfada çıkmasın.
setGoruldu(true);
}
}, []);
if (goruldu) return null;
// Giriş/ödeme gibi kromsuz akışlarda ve politikanın kendisinde gösterilmez.
if (pathname && kromGizliMi(pathname)) return null;
if (pathname === "/cerez-politikasi") return null;
function kapat() {
setGoruldu(true);
try {
localStorage.setItem(GORULDU_KEY, "1");
} catch {}
}
return (
<ViewportPortal>
{/* z-45: KaydetBanner'ın (z-40) üstünde, modalların (z-50) altında */}
<div className="pointer-events-none fixed inset-x-0 bottom-4 z-45 px-4 print:hidden">
<section
aria-label="Çerez bilgilendirmesi"
className="pointer-events-auto mx-auto flex max-w-xl flex-wrap items-center gap-3 rounded-2xl border border-slate-200 bg-card p-4 shadow-xl sm:flex-nowrap sm:gap-4"
>
<p className="min-w-0 flex-1 text-sm leading-snug text-slate-700">
Bu sitede reklam ya da izleme çerezi yok. Yalnız oturumun ve listen
için gerekli çerezleri ve kendi sunucumuzda çalışan çerezsiz
ziyaret ölçümünü kullanıyoruz.{" "}
<Link
href="/cerez-politikasi"
onClick={kapat}
className="font-semibold text-primary underline"
>
Ayrıntılar ve ölçümü kapatma
</Link>
</p>
<Button
type="button"
variant="outline"
size="lg"
onClick={kapat}
className="w-full cursor-pointer px-6 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97] sm:w-auto"
>
Tamam
</Button>
</section>
</div>
</ViewportPortal>
);
}

View File

@@ -0,0 +1,72 @@
"use client";
// Kullanım ölçümünü (Rybbit) bu tarayıcıda kapatan/açan anahtar — KVKK
// md. 11 itiraz hakkının arayüzü, /cerez-politikasi sayfasında durur.
//
// Rybbit betiği yüklenirken localStorage'da `disable-rybbit` anahtarını
// görürse hiçbir şey göndermez (betiğin kendi vazgeçme kapısı). Betik
// yüklendikten sonra durdurulamadığı için tercih değişince sayfa yenilenir.
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
const KAPALI_KEY = "disable-rybbit";
// Rybbit'in bu tarayıcıya yazdığı kimlikler; ölçüm kapanınca silinir.
const RYBBIT_KIMLIK_KEYLERI = ["rybbit-user-id", "rybbit-visitor-id"];
export function OlcumTercihi() {
// null = henüz okunmadı (SSR/ilk boya)
const [kapali, setKapali] = useState<boolean | null>(null);
const [hata, setHata] = useState(false);
useEffect(() => {
try {
// eslint-disable-next-line react-hooks/set-state-in-effect
setKapali(localStorage.getItem(KAPALI_KEY) !== null);
} catch {
setKapali(false);
}
}, []);
function degistir() {
try {
if (kapali) {
localStorage.removeItem(KAPALI_KEY);
} else {
localStorage.setItem(KAPALI_KEY, "1");
for (const k of RYBBIT_KIMLIK_KEYLERI) localStorage.removeItem(k);
}
} catch {
setHata(true);
return;
}
window.location.reload();
}
return (
<div className="mt-3 flex flex-wrap items-center gap-3 rounded-2xl border border-slate-200 bg-card p-4 sm:flex-nowrap sm:gap-4">
<div className="min-w-0 flex-1">
<p className="font-heading text-base font-bold text-slate-900">
{kapali ? "Ölçüm bu tarayıcıda kapalı" : "Ölçüm bu tarayıcıda açık"}
</p>
<p className="text-sm leading-snug text-slate-500" role="status">
{hata
? "Tarayıcın bu tercihi saklamaya izin vermiyor."
: kapali
? "Ziyaretlerin sayılmıyor. Site aynı şekilde çalışır."
: "Kapatırsan ziyaretlerin sayılmaz; site aynı şekilde çalışır."}
</p>
</div>
<Button
type="button"
variant="outline"
size="lg"
disabled={kapali === null}
onClick={degistir}
className="w-full cursor-pointer px-6 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97] sm:w-auto"
>
{kapali ? "Ölçümü aç" : "Ölçümü kapat"}
</Button>
</div>
);
}

View File

@@ -180,6 +180,12 @@ export function SiteFooter() {
>
Gizlilik & KVKK
</Link>
<Link
href="/cerez-politikasi"
className="hover:text-slate-700 hover:underline"
>
Çerez politikası
</Link>
<Link
href="/kosullar"
className="hover:text-slate-700 hover:underline"