
Oyun (Gaming) Sektöründe KVKK Kabusu ve Veribenim Çözümü: Global Oyuncu Verisi, Çerezsiz Takip ve GDPR/KVKK Çakışması
Oyun (Gaming) Sektöründe KVKK Kabusu ve Veribenim Çözümü: Global Oyuncu Verisi, Çerezsiz Takip ve GDPR/KVKK Çakışması
Giriş: Gaming'in Sessiz Veri Canavarı — Bir Mobil Oyun Kaç Veri Noktası Topluyor?
Birkaç saniye düşün: Kullanıcı app store'dan bir mobil oyun indirir. Oyunu açar. 5 dakikalık intro animasyonundan sonra login ekranına ulaşır.
O 5 dakika içinde oyun kaç veri noktası toplamıştır?
Cihaz Kimliği: IDFA (iOS), GAID (Android)
Coğrafi Konum: IP Adresi → Ülke/Şehir
Cihaz Bilgisi: Model, OS versiyonu, ekran boyutu
Ağ Bilgisi: WiFi/Cellular, hız
App Store Verileri: Kurulum tarihi, güncelleme geçmişi
Dokunuş Haritası: Ekrana hangi noktaları dokundu
Harf Basma Süresi: Her seçeneğe ne kadar bakıştı
Kütüphaneler: Cihazda hangi uygulamalar yüklü (fingerprinting)
Ve kullanıcı henüz bir tuşa basmadı.
Oyuncu giriş yaptığında (username + password) ve ilk satın alma yaptığında (ödeme kartı bilgileri):
Hesap başlama tarihi
Oyun başındaki harcadığı süreler (davranışsal meta-data)
Satın alınan item'ler (finansal veri)
Ödeme yöntemi (hassas)
Sonuç: Ortalama bir mobil oyun, ilk gün içinde 500+ veri noktası toplamıştır.
Peki, bu veriler nerede tutuluyor? Kimin erişimi var? Nasıl GDPR/KVKK uyumlu hale geliyor?
Cevap: Çoğu oyun stüdyosu bilmiyor.
Bu makale, Gaming Compliance Kabusu'nu açıyor ve Veribenim'in nasıl çözüm sunduğunu anlatıyor.
1. GDPR vs. KVKK vs. COPPA Üçgen Çakışması: Küresel Oyun Stüdyosu Ne Yapacak?
Türkiye'de bir oyun şirketi hayal edin. Ancak oyuncuları küreseldir:
50% Avrupa (GDPR)
30% Türkiye (KVKK)
15% USA (COPPA + State Laws)
5% Diğer (China, Japan, India)
Sorun: Üç yargı alanının farklı kuralları var.
📊 Üç Yargının Karşılaştırması
Konu | GDPR (EU) | KVKK (TR) | COPPA (USA) |
|---|---|---|---|
Yaşı 13'ten Küçük Çocuklar | 13+ (Madde 8) | Özel koşul yok (13+) | 8-12 İzin Gerekli |
Rıza Yönetimi | Explicit + Granular | Explicit + Açık | Parental Consent |
Cookieless Tracking | Consent Zorunlu | Consent Zorunlu | Yok/Minimal |
Veri Silme (DSAR) | 30 gün | 30 gün | 30 gün |
Cezalandırma | €20M veya %4 Turnover | ₺1.5M + Kapatma | $42K + FTC |
Aktarım (Data Transfer) | Adequacy Gerekli | Yurt Dışı Yasak | State Laws |
🎮 GAMING NOTU: Oyuncu 12 yaşında Türk ve ABD'de IP alias varsa? COPPA + KVKK ikisi de geçerli. Hangisi daha katı? COPPA. Hangisini uygulamalısınız? İkisinin kesişimi (intersection compliance).
Senaryo: Cross-Border Gaming
Türkiye Oyun Şirketi "Dragon Legends" → Global Publishing
├─ Sunucu: AWS Dublin (EU)
├─ Ödeme: Stripe (USA)
├─ Analytics: Firebase (Google/USA)
├─ CDN: Cloudflare (USA/EU)
└─ Oyuncu: 12 yaşında Türkiye + ABD VPN
Sorun:
1. Veri Dublin'de (GDPR) ✓
2. Ödeme Stripe'e (USA) → Adequacy gerekli ✗
3. Analytics Firebase'e (USA) → GDPR Chapter 5 gerekli ✗
4. Oyuncu 12 yaşında (COPPA) → Ebeveyn Consent ✗
5. Ebeveyn Türkiye'de → KVKK Madde 8 (Veri Aktarımı) İhlaları ✗
Sonuç: **4 İhlal Aynı Oyunda.**
2. Cookieless Tracking Dönemi: Fingerprinting ve KVKK
Google, Safari ve Firefox son yaşanda third-party cookies'i kaldırıyor.
Oyun şirketi "tamam, o zaman fingerprinting yaparız" diyor. Hata.
Fingerprinting Nedir?
// Geleneksel Cookie
document.cookie = "user_id=12345; path=/";
// Fingerprinting (Cookie-Free)
const fingerprint = hash([
navigator.userAgent, // "Mozilla/5.0..."
navigator.language, // "tr-TR"
navigator.hardwareConcurrency, // 8 (CPU cores)
screen.resolution, // "1920x1080"
screen.colorDepth, // 32
navigator.getGPUTier(), // GPU model
navigator.battery.level, // 85%
timezone.getOffset(), // +3
installed_fonts.count(), // 142
]);
// Sonuç: Deterministik ID
// → Üçüncü taraf cookies olmadan oyuncuyu izleyebilirsin
⚠️ Fingerprinting KVKK İhlaline Gider
KVKK Madde 5(1)(c) — Meşru Hedef:
Geleneksel cookie: "Oyun deneyimini kişiselleştir" ✓
Fingerprinting: "Gizli takip et" ✗
GDPR Recital 24:
"... online izleme araçları (cookies, fingerprinting) KURAL olarak rıza gerektirir. Deceptive tracking = İ hlal."
⚖️ HUKUKİ NOT: Cookieless tracking = Fingerprinting. Veribenim otomatik olarak Fingerprint Detection yapıyor. Eğer fingerprinting yapılıyorsa, express consent toplanıyor.
3. Oyun İçi Satın Alma: Ödeme Verisi + Oyuncu Profili = Çifte Risk
Mobil oyunlar IAP (In-App Purchase) ile para kazanıyor.
Oyuncu "100 Diamond" satın aldığında:
Ödeme Kartı Bilgisi: Last 4 digits, expiry (Payment Card Industry Data Security Standard)
Oyuncu Profili: Kimin aldığı (KVKK)
Satın Alma Davranışı: Ne tür item aldığı, ne kadar harcadığı
Cihaz Bilgisi: Hangi cihazdan satın aldı
Coğrafi Veri: Nerede satın aldı (IP adresinden)
Sorun: Ödeme kartı ≠ Oyuncu Profili
Payment Gateway (Stripe, Apple Pay)
├─ KAYıTLI: Ödeme Kartı Bilgisi (PCI-DSS)
│ └─ Şifreli, izole, 3. taraf
│
└─ RISKLI: Oyun Sunucusu
├─ Ödeme Onayı Kaydı
├─ Oyuncu ID
├─ Satılan Item
├─ Harcadığı Para
└─ Davranışsal Meta-data
Risk: Oyun şirketi, satın alınan diamond'ı oyuncu profiline bağlıyor ve:
"Bu oyuncu 5 ay içinde $500 harcadı" profili oluşturuyor
Bu davranışsal profil üçüncü taraf analytics'e gönderiliyor
Üçüncü taraf "bu oyuncu yüksek-spender" olarak profilini oluşturuyor
Reklamcılara satıyor
KVKK İhlaline Gider (Madde 8 - Veri Aktarımı, Madde 5 - Meşru Hedef).
💡 PRO TIP: Veribenim ile, ödeme verisi ve oyuncu profili tamamen izole tutunur. Ödeme gateway Stripe ile, oyuncu profili ayrı. Bağlantı sadece "satın alma başarılı/başarısız" logudur.
4. Battlepass ve Abonelik: Tekrarlayan Ödemede Rıza Yönetimi
Battlepass modeli: Oyuncu aylık abonelik başlatıyor. Her ay otomatik ödeme.
Türkiye'de Ödeme Hizmetleri Yönetmeliği ve KVKK Madde 9 altında:
Gereklilik | KVKK | Ödeme Yönetmeliği |
|---|---|---|
Başlangıç Rızası | Explicit ("Evet" tıkla) | Explicit Signature |
Aylık Onay | Optional (ilk onay yeter) | Optional (tekrar onay gereklidir) |
İptal Hakkı | 30 gün | 14 gün (Tüketiciye Hak Tanıma) |
Özgür İptal | Zor olmamalı | Kolay olmalı |
Yenileme Aydınlatması | Gerekli | Gerekli (SMS/Email) |
Senaryo: Battlepass İhlaline Gider
Oyuncu: "Battlepass başlatırım."
└─ "Her ay ₺99.99. Dilediğin zaman iptal edebilirsin."
✓ Rıza Alındı, Ilk Ödeme Alındı
✗ Ama Oyuncu Ayın 15'inde İptal Etmek İstiyor
└─ Settings → Account → Cancelation
└─ Button yok, chat desteğine yönlendiriliyor
└─ KVKK İhlaline Gider (Madde 9 - Rıza Yönetimi)
Doğru Uygulama:
Settings → Subscription
├─ "Battlepass Aktif (₺99.99/ay)"
├─ "Sonraki Ödeme: 15.04.2026"
├─ 🔴 CANCEL SUBSCRIPTION (Tek Tık)
│ └─ "Emin misin? [İptal] [Devam Et]"
│ └─ İptal → Hemen devre dışı
└─ "İptal edebilirsin 14 gün içinde para iadesi ile"
5. Nasıl Entegre Edilir? — @veribenim/core ile Gaming
Şimdi kodda görelim.
Adım 1: Oyun Başlangıcında Consent Onboarding
// unity-webgl-consent-manager.js
// Unity WebGL oyununa gömülü, index.html'de yüklenecek
import { init } from '@veribenim/core';
class GameConsentManager {
constructor() {
this.veribenim = null;
this.playerLocale = 'en'; // Unite'ten gelecek
this.playerId = null;
}
/**
* Oyun Unity'den şu komutla çağıracak:
* SendMessage('ConsentManager', 'InitializeConsent', playerId);
*/
async InitializeConsent(playerId) {
this.playerId = playerId;
// Oyun dilini algıla (Steam, Epic, iOS)
this.playerLocale = this.detectGameLocale();
// Veribenim init
this.veribenim = init({
token: window.VERIBENIM_TOKEN, // HTML'de inject edilecek
lang: this.mapGameLocaleToVBLang(this.playerLocale),
debug: false,
});
// Var olan onay var mı kontrol
const savedPrefs = await this.veribenim.getPreferences(playerId);
if (!savedPrefs) {
// İlk kez oynuyor - Consent Overlay göster
this.showFirstTimeConsentOverlay();
} else {
// Preferences yüklendi - Analytics ve Ads aktif et
this.applyStoredPreferences(savedPrefs);
}
}
detectGameLocale() {
// Unity WebGL'den gelen platform bilgisi
if (window.unityGame?.gameLauncher === 'steam') {
return navigator.language || 'en'; // Steam locale
} else if (window.unityGame?.gameLauncher === 'epic') {
return window.epicLocale || 'en';
} else if (window.unityGame?.platform === 'mobile') {
return navigator.language || 'en';
}
return 'en';
}
mapGameLocaleToVBLang(locale) {
const langMap = {
'tr': 'tr', 'tr-TR': 'tr',
'en': 'en', 'en-US': 'en', 'en-GB': 'en',
'de': 'de', 'de-DE': 'de',
'fr': 'fr', 'fr-FR': 'fr',
'es': 'es', 'es-ES': 'es',
'pt': 'pt', 'pt-BR': 'pt',
'ru': 'ru', 'ru-RU': 'ru',
'ja': 'ja', 'ja-JP': 'ja',
'zh': 'zh', 'zh-CN': 'zh',
'ar': 'ar', 'ar-SA': 'ar',
};
return langMap[locale] || 'en';
}
showFirstTimeConsentOverlay() {
// HTML5/WebGL konsent overlay UI
const overlay = document.createElement('div');
overlay.id = 'veribenim-consent-overlay';
overlay.innerHTML = `
<div class="consent-modal">
<h2>🎮 Oyuna Hoş Geldin!</h2>
<p>Daha iyi bir oyun deneyimi için bazı verilerinizi kullanmak istiyoruz.</p>
<div class="consent-toggle">
<label>
<input type="checkbox" id="toggle-analytics" checked />
<span>
<strong>📊 Oyun Analitiği</strong><br/>
Oyun performansını iyileştirmemize yardımcı olur (anonim)
</span>
</label>
</div>
<div class="consent-toggle">
<label>
<input type="checkbox" id="toggle-marketing" />
<span>
<strong>🎯 Oyun İçi Teklifler</strong><br/>
Size özel item ve kampanya önerileri gösterelim mi?
</span>
</label>
</div>
<div class="consent-toggle">
<label>
<input type="checkbox" id="toggle-preferences" checked />
<span>
<strong>⚙️ Oyun Tercihleri</strong><br/>
Dil, ses, grafik ayarlarınız ve ilerlemeniz kaydedilsin mi?
</span>
</label>
</div>
<div class="consent-buttons">
<button id="btn-accept-all" class="btn-primary">
Tümünü Kabul Et
</button>
<button id="btn-minimal" class="btn-secondary">
Minimal Mod (Zorunlu Yalnızca)
</button>
<button id="btn-settings" class="btn-tertiary">
Özel Ayarla
</button>
</div>
<p class="legal-note">
<a href="<https://yoursgame.com/privacy>" target="_blank">Gizlilik Politikası</a> ·
<a href="<https://yoursgame.com/kvkk>" target="_blank">KVKK Aydınlatma</a>
</p>
</div>
`;
document.body.appendChild(overlay);
// Event listeners
document.getElementById('btn-accept-all').addEventListener('click', () => {
this.saveConsentAndClose({
analytics: true,
marketing: true,
preferences: true,
});
});
document.getElementById('btn-minimal').addEventListener('click', () => {
this.saveConsentAndClose({
analytics: false,
marketing: false,
preferences: true,
});
});
document.getElementById('btn-settings').addEventListener('click', () => {
// Custom consent ekranı aç
});
}
async saveConsentAndClose(preferences) {
await this.veribenim.savePreferences(this.playerId, preferences);
// Unity'ye geri raporla
SendMessageToUnity('ConsentCallback', JSON.stringify(preferences));
// Overlay kapat
const overlay = document.getElementById('veribenim-consent-overlay');
overlay?.remove();
this.applyStoredPreferences(preferences);
}
applyStoredPreferences(preferences) {
if (preferences.analytics) {
// Analytics aktif et
window.unityGame?.SendMessage('AnalyticsManager', 'EnableAnalytics');
}
if (preferences.marketing) {
// Mediation ads'i aktif et (rewarded, interstitial)
window.unityGame?.SendMessage('AdManager', 'EnableAds');
}
if (preferences.preferences) {
// Cloud save aktif et
window.unityGame?.SendMessage('SaveManager', 'EnableCloudSave');
}
}
}
// Global olarak erişilebilir
window.gameConsentManager = new GameConsentManager();
// Unity WebGL çağrıları
function SendMessageToUnity(methodName, args) {
if (window.unityGame?.Module?.dynCall_vii) {
// Unity 2020 LTS veya yeni
SendMessage('GameManager', methodName, args);
}
}
Adım 2: Oyun İçi Satın Alma Consent Gate
// GameManager.cs (Unity Script)
using UnityEngine;
using UnityEngine.Purchasing;
using System.Runtime.InteropServices;
public class PurchaseManager : MonoBehaviour, IStoreListener
{
private IStoreController controller;
private IExtensionProvider extensionProvider;
private bool analyticsConsent = false;
void Start()
{
// Unity IAP initialize
InitializePurchasing();
// Consent manager'dan onay durumunu sor
#if UNITY_WEBGL
analyticsConsent = GetConsentFromJavaScript("analytics");
#endif
}
#if UNITY_WEBGL
[DllImport("__Internal")]
private static extern void GetConsentFromJS(string callback);
public void OnConsentReceived(string json)
{
var prefs = JsonUtility.FromJson<ConsentPreferences>(json);
analyticsConsent = prefs.analytics;
}
#endif
public void OnPurchaseClicked(string productId)
{
// 1. Ödeme öncesi consent kontrol et
if (!HasRequiredConsent())
{
ShowConsentRequiredDialog(productId);
return;
}
// 2. Ödeme başlat
controller.InitiatePurchase(productId);
}
private bool HasRequiredConsent()
{
// "Necessary" consent her zaman var olmalı (satın alma = temel fonksiyon)
return true; // Zorunlu onay
}
private void ShowConsentRequiredDialog(string productId)
{
// Consent ekranını göster
// Oyuncu "Devam Et"e basarsa OnPurchaseClicked yeniden çalışır
}
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
this.controller = controller;
this.extensionProvider = extensions;
}
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
if (args.purchasedProduct.definition.id == "diamond_100")
{
// Ödeme başarılı
LogPurchaseToVeribenim(args);
AddGemsToPlayer(100);
return PurchaseProcessingResult.Complete;
}
return PurchaseProcessingResult.Pending;
}
private void LogPurchaseToVeribenim(PurchaseEventArgs args)
{
#if UNITY_WEBGL
string purchaseLog = JsonUtility.ToJson(new
{
event_type = "in_app_purchase",
product_id = args.purchasedProduct.definition.id,
price = args.purchasedProduct.metadata.localizedPrice,
currency = args.purchasedProduct.metadata.isoCurrencyCode,
receipt = args.purchasedProduct.receipt,
timestamp = System.DateTime.UtcNow.ToIso8601String(),
});
SendMessageToConsent("LogPurchaseConsent", purchaseLog);
#endif
}
}
Adım 3: Oyuncu Profili DSAR (Data Subject Access Request)
// account-settings-controller.ts
// Veribenim React ile oyuncu hesap ayarları paneli
import React, { useState } from 'react';
import { useVeribenim } from '@veribenim/react';
import { useAuthContext } from '@/hooks/useAuthContext';
export function AccountSettingsPanel() {
const { user } = useAuthContext();
const { submitDsar } = useVeribenim();
const [dsarLoading, setDsarLoading] = useState(false);
const [dsarMessage, setDsarMessage] = useState('');
const handleExportData = async () => {
setDsarLoading(true);
try {
await submitDsar({
requestType: 'portability',
fullName: user.username,
email: user.email,
description: `
GDPR Article 20 & KVKK Madde 11/ç -
Oyun hesabımın ve tüm verilerimin (ilerleme, satın almalar, ayarlar,
istatistikler) makine okunabilir formatta (JSON) indirilmesini talep ediyorum.
`.trim(),
});
setDsarMessage('Veri talebiniz işlemeye alındı. 30 gün içinde indirebileceğiniz bir bağlantı e-postanıza gönderilecek.');
} catch (error) {
setDsarMessage('Hata: Veri talebi gönderilemedi. Lütfen daha sonra deneyin.');
} finally {
setDsarLoading(false);
}
};
const handleDeleteAccount = async () => {
const confirmed = window.confirm(
'Hesabınızı kalıcı olarak silmek istediğinizden emin misiniz? ' +
'Tüm ilerleme, item'ler ve veriler silinecektir. Bu işlem geri alınamaz.'
);
if (!confirmed) return;
setDsarLoading(true);
try {
await submitDsar({
requestType: 'erasure',
fullName: user.username,
email: user.email,
description: `
Hesabımın ve tüm kişisel verilerimin silinmesini talep ediyorum.
GDPR Article 17 & KVKK Madde 11/e - Veri Silme Hakkı.
Silinecek veriler:
- Hesap bilgileri (username, email, password hash)
- Oyun ilerlemesi ve istatistikler
- Satın alım geçmişi (anonim olarak tutulacak)
- Cihaz bilgileri ve cookies
- Tercihler ve ayarlar
`.trim(),
});
setDsarMessage('Silme talebiniz alındı. 30 gün içinde hesabınız tamamen silinecektir.');
} catch (error) {
setDsarMessage('Hata: Silme talebi gönderilemedi.');
} finally {
setDsarLoading(false);
}
};
const handleEditConsent = async () => {
// Consent ayarlarını yeniden görüntüle
window.open('/settings/privacy', '_self');
};
return (
<div className="account-settings">
<section className="privacy-section">
<h3>🔐 Gizlilik ve Veri</h3>
<div className="setting-item">
<h4>Veri Taleplerini Yönet</h4>
<p>
GDPR ve KVKK kapsamında hesabınızla ilgili tüm verileri görebilir,
indirebilir veya silebilirsiniz.
</p>
<button onClick={handleEditConsent} disabled={dsarLoading}>
Consent Ayarlarını Düzenle
</button>
<button onClick={handleExportData} disabled={dsarLoading}>
{dsarLoading ? 'İşleniyor...' : '📥 Verilerimi İndir (JSON)'}
</button>
<button onClick={handleDeleteAccount} disabled={dsarLoading} className="btn-danger">
{dsarLoading ? 'İşleniyor...' : '🗑️ Hesabı Sil'}
</button>
{dsarMessage && (
<p className="message" style={{ marginTop: '1rem' }}>
{dsarMessage}
</p>
)}
</div>
<div className="setting-item">
<h4>Oyun Analitikleri</h4>
<label>
<input type="checkbox" defaultChecked={true} onChange={(e) => {
// Analytics toggle handle
}} />
Oyun performansı verilerini paylaşmak için izin ver
</label>
<small>
Anonim olarak tutulur. Oyun iyileştirmelerine yardımcı olur.
</small>
</div>
<div className="setting-item">
<h4>Kişiselleştirilmiş İçerik</h4>
<label>
<input type="checkbox" onChange={(e) => {
// Marketing consent toggle
}} />
Size özel item ve kampanya teklifleri göstersem mi?
</label>
<small>
Oyun içi harcama davranışınıza göre kişiselleştirilmiş öneriler.
</small>
</div>
</section>
</div>
);
}
Adım 4: Battlepass Subscription Yönetimi
// BattlepassService.php (Laravel Backend)
<?php
use Veribenim\\Laravel\\VeribenimFacade as Veribenim;
class BattlepassService
{
/**
* Battlepass aboneliğini başlat
* KVKK Madde 9 - Tekrarlayan Ödeme Rızası
*/
public function startBattlepass(User $player, string $billingPeriod = 'monthly')
{
if ($player->battlepass_active) {
throw new \\Exception('Zaten aktif battlepass var.');
}
// 1. Consent Log - Tekrarlayan ödeme için express rıza
$consentLog = Veribenim::logFormConsent(
formName: 'battlepass_subscription',
consented: true,
consentText: sprintf(
'Battlepass aboneliğini başlatıyorum. ' .
'Her %s %s fiyatında otomatik ödeme yapılmasını onaylıyorum. ' .
'Dilediğim zaman iptal edebilirim. KVKK Madde 9, Ödeme Hizmetleri Yönetmeliği. ' .
'İptal etmek için Settings → Subscription → Cancel Subscription bölümünü kullan.',
$billingPeriod,
currency_symbol() . config('battlepass.price.' . $billingPeriod)
),
metadata: [
'billing_period' => $billingPeriod,
'renewal_day' => now()->addMonth()->day,
'cancellation_url' => route('battlepass.cancel'),
'cancellation_easy'=> 'true', // KVKK Madde 9 - Rıza yönetimi kolay olmalı
]
);
// 2. Abonelik kaydını oluştur
$subscription = BattlepassSubscription::create([
'user_id' => $player->id,
'billing_period' => $billingPeriod,
'started_at' => now(),
'renewal_at' => now()->addMonth(),
'consent_id' => $consentLog['id'],
'status' => 'active',
'auto_renew' => true,
'cancellation_easy' => true, // Türk hukuku
]);
// 3. İlk ödemeyi al (Stripe)
try {
$charge = $this->processFirstPayment($player, $subscription);
$subscription->update([
'stripe_subscription_id' => $charge->id,
'last_payment_at' => now(),
]);
} catch (\\Exception $e) {
$subscription->delete();
throw $e;
}
return $subscription;
}
/**
* Battlepass iptal (KVKK Madde 9 - Kolay İptal)
*/
public function cancelBattlepass(User $player)
{
$subscription = BattlepassSubscription::where('user_id', $player->id)
->where('status', 'active')
->first();
if (!$subscription) {
throw new \\Exception('Aktif battlepass aboneliği bulunamadı.');
}
// 1. Stripe aboneliğini iptal et
$this->stripeCancelSubscription($subscription->stripe_subscription_id);
// 2. DB kaydını güncelle
$subscription->update([
'status' => 'cancelled',
'cancelled_at' => now(),
'cancellation_reason' => 'User initiated', // KVKK Madde 9 - İzlenebilirlik
]);
// 3. Veribenim'e iptal logu kaydet
Veribenim::submitDsar(
requestType: 'withdrawal',
fullName: $player->username,
email: $player->email,
description: sprintf(
'Battlepass aboneliğinin iptal edildiğini log kaydet. ' .
'KVKK Madde 9/4 - Rızadan Çekilme. ' .
'Abonelik: %s. ' .
'Başlangıç: %s. ' .
'İptal: %s.',
$subscription->billing_period,
$subscription->started_at->format('d.m.Y'),
now()->format('d.m.Y H:i')
)
);
return ['message' => 'Aboneliğiniz iptal edildi.'];
}
/**
* Aylık yenileme notifikasyonu (KVKK Madde 9 - Aydınlatma)
*/
public function sendRenewalReminder(BattlepassSubscription $subscription)
{
$player = $subscription->user;
// 3 gün öncesinden hatırlat
if ($subscription->renewal_at->diffInDays(now()) === 3) {
$price = config('battlepass.price.' . $subscription->billing_period);
Mail::send('emails.battlepass-renewal', [
'player_name' => $player->username,
'price' => $price,
'renewal_at' => $subscription->renewal_at->format('d.m.Y'),
'cancel_url' => route('battlepass.cancel'),
], function ($mail) use ($player) {
$mail->to($player->email)
->subject('Battlepass Yenileme Hatırlatması - 3 Gün Kaldı');
});
// Oyun içi notification
Notification::create([
'user_id' => $player->id,
'title' => 'Battlepass Yenileniyor',
'body' => "Battlepass aboneliğiniz {$subscription->renewal_at->format('d.m.Y')}'de yenilenecektir.",
'action_url' => '/settings/battlepass',
]);
\\Log::info('[Battlepass] Yenileme hatırlatması gönderildi', [
'user_id' => $player->id,
'renewal_at' => $subscription->renewal_at,
'price' => $price,
]);
}
}
}
6. Cookieless Analytics: Consent Bazlı Tracking
// analytics-manager.ts (Unity WebGL)
class AnalyticsManager {
private hasAnalyticsConsent = false;
/**
* Consent alındıktan sonra analytics başlat
*/
public async InitializeAnalytics(preferences: ConsentPreferences) {
this.hasAnalyticsConsent = preferences.analytics;
if (!this.hasAnalyticsConsent) {
console.log('[Analytics] Consent yok - Analytics deaktif');
return;
}
// Fireabse initialization (anonim şekilde)
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
// Oyuncu IP'si ASLA log'lanmaz
// Analytics: {
// session_id: hash(deviceId + timestamp),
// level_completed: 5,
// time_played: 3600,
// tutorial_skipped: true,
// }
logEvent(analytics, 'game_session_start', {
game_version: '1.2.3',
device_type: 'mobile',
// Dikkat: Oyuncu ID = ASLA
});
}
/**
* Fingerprinting ASLA yapılmaz
*/
private getClientFingerprint() {
// ✗ KVKK İhlaline Gider
// const fingerprint = hash([
// navigator.userAgent,
// navigator.language,
// navigator.hardwareConcurrency,
// screen.resolution,
// ]);
// ✓ KVKK Uyumlu: Session-based ID
return `session_${Date.now()}_${Math.random().toString(36)}`;
}
}
7. Data Sovereignty: Türk Oyuncuların Verisi Nerede Saklanmalı?
🌍 GLOBAL UYUM: KVKK Madde 8 - "Kişisel veriler, yurt dışına aktarılamaz."
Oyun şirketi Türkiye'de. Sunucu AWS'de mi, Google Cloud'da mı, kendi veri merkezinde mi?
✅ KVKK Uyumlu Mimarisi
Türkiye Oyuncusu
↓
└─ Istanbul AWS Region (eu-central-1 equivalent)
├─ Oyuncu Profili
├─ Satın Alma Geçmişi (Ödeme Kartı Metadata Yok)
├─ Oyun İlerleme
└─ Consent Logları
❌ KVKK İhlaline Gider
Türkiye Oyuncusu
↓
└─ Firebase (USA, Google Cloud)
├─ Realtime Database
├─ Analytics
├─ Cloud Storage (CVs, Screenshots)
└─ Automation Engine
Sorun: Firebase default'ta USA'da. Türkiye → USA = Veri aktarımı = İHLAL
Çözüm: Multi-region setup yapı:
// Laravel - Region-based storage
class GameDataRepository {
private $regionStorage;
public function __construct() {
// Oyuncu IP'sine göre region belirle
if ($this->isPlayerInTurkey()) {
$this->regionStorage = Storage::disk('aws-turkey'); // Istanbul
} else if ($this->isPlayerInEU()) {
$this->regionStorage = Storage::disk('aws-eu'); // Frankfurt
} else {
$this->regionStorage = Storage::disk('aws-global'); // Nearest
}
}
public function savePlayerProfile(User $player, array $data) {
// KVKK Madde 8 uyumlu
$this->regionStorage->put(
"players/{$player->id}/profile.json",
json_encode($data)
);
}
}
8. Automated Privacy: Hesap Silme ve Veri Portability
// DeleteAccountJob.php (Laravel Queue)
class DeleteAccountJob implements ShouldQueue {
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $player;
public function __construct(User $player) {
$this->player = $player;
}
/**
* GDPR Article 17 & KVKK Madde 11/e - 30 gün içinde gerçekleştir
*/
public function handle() {
\\Log::info('[DeleteAccount] Başlıyor', ['player_id' => $this->player->id]);
// 1. Oyun İlerleme Sil
GameProgress::where('player_id', $this->player->id)->delete();
// 2. Satın Alma Geçmişi (Anonim tut, vergi sebebiyle)
Purchase::where('player_id', $this->player->id)->update([
'player_id' => null, // Bağlantısını kes
'email' => null,
'display_name' => "ANONYMOUS_" . hash('sha256', $this->player->id),
'anonymized_at' => now(),
]);
// 3. Profil Alanlarını Sil
$this->player->update([
'username' => "DELETED_" . hash('sha256', $this->player->id),
'email' => null,
'phone' => null,
'birthdate' => null,
'country' => null,
'avatar_path' => null,
'biography' => null,
'social_links' => null,
'deleted_at' => now(),
'deletion_reason' => 'User requested (GDPR Article 17)',
]);
// 4. Cihaz Bağlantılarını Sil
Device::where('player_id', $this->player->id)->delete();
// 5. Consent Loglarını Sil
ConsentLog::where('email', $this->player->email)->delete();
// 6. Veribenim'e Silme Raporu
Veribenim::submitDsar(
requestType: 'erasure_confirmation',
fullName: 'System',
email: 'noreply@' . config('app.domain'),
description: sprintf(
'Oyun hesabı silme işlemi tamamlandı. ' .
'Oyuncu ID: %d. ' .
'Silinme Tarihi: %s. ' .
'Saklanan Veriler: Satın alımlar (anonim), vergi kayıtları. ' .
'GDPR Article 17 & KVKK Madde 11/e.',
$this->player->id,
now()->format('d.m.Y H:i')
)
);
\\Log::info('[DeleteAccount] Tamamlandı', ['player_id' => $this->player->id]);
}
}
9. Sonuç: Veribenim ile Global Gaming Compliance
Veribenim Compliance as a Service platformu, oyun stüdyolarının:
Üç Yargı (GDPR, KVKK, COPPA) Kesişimini otomatik yönet
Cookieless Tracking ile fingerprinting'i engelle
IAP Consent Gate ile ödeme verisi ve oyuncu profilini izole tut
Battlepass Abonelikleri KVKK Madde 9 uyumlu yönet
Data Sovereignty ile Türk verilerini Türkiye'de tut
DSAR (veri erişim, silme, portability) 30 gün içinde otomatik yap
Veribenim Gaming Stack
┌─────────────────────────────────────────────┐
│ Unity WebGL / React Native / Mobile Game │
├─────────────────────────────────────────────┤
│ @veribenim/core (Consent Manager) │
│ @veribenim/react (UI Components) │
│ @veribenim/unity (C# SDK) │
├─────────────────────────────────────────────┤
│ Veribenim Backend (Laravel) │
│ ├─ Consent Log Store │
│ ├─ DSAR Processor │
│ ├─ Region-Based Data Storage │
│ └─ Automated Privacy Jobs │
├─────────────────────────────────────────────┤
│ Compliance Dashboard │
│ ├─ Consent Analytics │
│ ├─ DSAR History │
│ ├─ Regional Data Compliance Report │
│ └─ Audit Trail │
└─────────────────────────────────────────────┘
Sonuç: Veribenim ile oyun stüdyosu "kompliyans için kodlamaz, konfigüre eder." GDPR/KVKK/COPPA uyumluluğu otomatik.
📚 Teknik Dokümantasyon: Tüm SDK referans dökümanlarına veribenim.com/documents adresinden ulaşabilirsiniz.
Sonraki Adım
Veribenim'in bu sektör için sunduğu çözümleri görmek ve KVKK/GDPR uyumlu pazarlama başlamak için aşağıdaki butona tıklayın.
Ücretsiz Hesap Oluştur