Tüm Yazılar
KategoriPrivacy
Okuma Süresi
24 dk okuma
Yayın Tarihi
...
Kelime Sayısı
1.998kelime

Kahveni hazırla - bu içerikli bir makale!

App Tracking Transparency, Privacy Manifest, Required Reason API ve Apple Privacy Label uyumluluğu. GDPR, KVKK ve App Store Review süreçleri.

iOS Privacy Compliance & ATT: Eksiksiz Rehber

# iOS Privacy Compliance & ATT: Eksiksiz Rehber

Dijital gizlilik artik bir tercih degil, yasal zorunluluk. Apple'in App Tracking Transparency (ATT) framework'u ile kullanicilarin izlenmesi konusu tamamen degisti. 2024 itibariyle Privacy Manifest zorunlulugu, Required Reason API'ler ve siki App Store Review surecleri ile uyumlu olmak her iOS gelistiricinin gorevidir. Bu rehberde tum sureci bastan sona ele alacagiz.

Not: Bu rehber Apple'in resmi dokumantasyonu, WWDC session'lari ve gercek App Store Review deneyimlerine dayanmaktadir.

Icindekiler


1. Privacy Neden Onemli?

Apple'in privacy-first yaklasimi sadece bir pazarlama stratejisi degil. iOS 14.5'ten bu yana ATT framework'u zorunlu hale geldi ve kullanicilarin sadece %25-35'i izlemeye izin veriyor. Bu da reklam gelirlerini, attribution'i ve analytics'i dogrudan etkiliyor.

Tarihsel Surecin Ozeti

Yil
Gelisme
Etki
**iOS 14.5**
ATT zorunlu
IDFA erisimi izne bagli
**iOS 15**
Mail Privacy Protection
Email tracking engellendi
**iOS 16**
Lockdown Mode
Ekstra koruma katmani
**iOS 17**
Link Tracking Protection
URL tracker parametreleri temizleniyor
**iOS 17**
Privacy Manifest zorunlu
3rd-party SDK'lar manifest sunmali
**iOS 18**
Required Reason API
Belirli API'ler icin neden belirtme zorunlu

Kullanici Guveni Istatistikleri

  • Kullanicilarin %78'i gizlilik politikasini okuyor (Apple arastirmasi)
  • %89: 'u izlemeyi reddettikten sonra uygulamayi kullanmaya devam ediyor
  • Privacy label'da "Data Not Collected" yazan uygulamalar %32 daha fazla indiriliyor

2. App Tracking Transparency (ATT)

ATT, kullanicinin IDFA'sina (Identifier for Advertisers) erismeden once izin istemek icin kullanilir.

Temel Implementasyon

swift
1import AppTrackingTransparency
2import AdSupport
3 
4final class TrackingManager {
5 static let shared = TrackingManager()
6 
7 /// ATT izin durumunu kontrol et
8 var currentStatus: ATTrackingManager.AuthorizationStatus {
9 ATTrackingManager.trackingAuthorizationStatus
10 }
11 
12 /// IDFA'yi guvenli sekilde al
13 var advertisingIdentifier: String? {
14 guard currentStatus == .authorized else { return nil }
15 let idfa = ASIdentifierManager.shared().advertisingIdentifier
16 // Sifir UUID kontrolu - izin verilmemis demektir
17 guard idfa.uuidString != "00000000-0000-0000-0000-000000000000" else {
18 return nil
19 }
20 return idfa.uuidString
21 }
22 
23 /// Izin iste - SADECE uygun zamanda cagir
24 func requestPermission() async -> ATTrackingManager.AuthorizationStatus {
25 // iOS 17.4+ icin kontrol
26 guard #available(iOS 14.5, *) else {
27 return .authorized // Eski iOS'larda IDFA serbest
28 }
29 
30 return await ATTrackingManager.requestTrackingAuthorization()
31 }
32 
33 /// Izin durumuna gore analytics yapilandir
34 func configureAnalytics() {
35 switch currentStatus {
36 case .authorized:
37 enableFullTracking()
38 case .denied, .restricted:
39 enablePrivacyFriendlyAnalytics()
40 case .notDetermined:
41 // Henuz sorulmadi - daha sonra sor
42 break
43 @unknown default:
44 enablePrivacyFriendlyAnalytics()
45 }
46 }
47 
48 private func enableFullTracking() {
49 // Firebase Analytics, Adjust, AppsFlyer vb. tam izleme
50 }
51 
52 private func enablePrivacyFriendlyAnalytics() {
53 // Anonim metrikler, aggregate data, SKAdNetwork
54 }
55}

ATT Dialog Zamanlama Stratejisi

ATT dialog'unu hemen gostermek en kotu yaklasimdir. Kullaniciya once deger gosterin:

swift
1import SwiftUI
2 
3struct OnboardingATTView: View {
4 @State private var showATTExplanation = false
5 
6 var body: some View {
7 VStack(spacing: 24) {
8 Image(systemName: "hand.raised.fill")
9 .font(.system(size: 60))
10 .foregroundStyle(.blue)
11 
12 Text("Deneyiminizi Kisisellestirmek Istiyoruz")
13 .font(.title2.bold())
14 
15 // Kullaniciya NEDEN izin istediginizi aciklayin
16 VStack(alignment: .leading, spacing: 12) {
17 BenefitRow(icon: "star.fill", text: "Size ozel icerik onerileri")
18 BenefitRow(icon: "bell.fill", text: "Ilginizi cekecek bildirimler")
19 BenefitRow(icon: "shield.fill", text: "Verileriniz guvendedir")
20 }
21 .padding()
22 .background(.ultraThinMaterial)
23 .cornerRadius(16)
24 
25 Button("Devam Et") {
26 Task {
27 let status = await TrackingManager.shared.requestPermission()
28 handleTrackingResult(status)
29 }
30 }
31 .buttonStyle(.borderedProminent)
32 
33 Button("Daha Sonra") {
34 // Kullaniciyi zorlamayin
35 navigateToHome()
36 }
37 .foregroundStyle(.secondary)
38 }
39 .padding()
40 }
41 
42 private func handleTrackingResult(_ status: ATTrackingManager.AuthorizationStatus) {
43 TrackingManager.shared.configureAnalytics()
44 navigateToHome()
45 }
46 
47 private func navigateToHome() {
48 // Ana sayfaya yonlendir
49 }
50}
51 
52struct BenefitRow: View {
53 let icon: String
54 let text: String
55 
56 var body: some View {
57 HStack(spacing: 12) {
58 Image(systemName: icon)
59 .foregroundStyle(.blue)
60 Text(text)
61 .font(.subheadline)
62 }
63 }
64}

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?


3. Privacy Manifest Dosyasi

iOS 17'den itibaren tum uygulamalar ve 3rd-party SDK'lar PrivacyInfo.xcprivacy dosyasi icermek zorunda.

Privacy Manifest Yapisi

swift
1// PrivacyInfo.xcprivacy ornegi (XML/Plist formati)
2// Xcode'da Privacy Manifest olarak eklenir
3//
4// Ornek yapi:
5// NSPrivacyTracking: false
6// NSPrivacyTrackingDomains: []
7// NSPrivacyCollectedDataTypes:
8// - NSPrivacyCollectedDataType: NSPrivacyCollectedDataTypeDeviceID
9// NSPrivacyCollectedDataTypeLinked: false
10// NSPrivacyCollectedDataTypeTracking: false
11// NSPrivacyCollectedDataTypePurposes:
12// - NSPrivacyCollectedDataTypePurposeAnalytics
13// NSPrivacyAccessedAPITypes:
14// - NSPrivacyAccessedAPIType: NSPrivacyAccessedAPICategoryUserDefaults
15// NSPrivacyAccessedAPITypeReasons: ["CA92.1"]
16 
17// Swift'te Privacy Manifest icerigini kontrol etme
18import Foundation
19 
20struct PrivacyManifestValidator {
21 struct ValidationResult {
22 let isValid: Bool
23 let warnings: [String]
24 let errors: [String]
25 }
26 
27 static func validate(manifestPath: String) -> ValidationResult {
28 var warnings: [String] = []
29 var errors: [String] = []
30 
31 guard let data = FileManager.default.contents(atPath: manifestPath),
32 let plist = try? PropertyListSerialization.propertyList(
33 from: data, format: nil
34 ) as? [String: Any] else {
35 return ValidationResult(isValid: false, warnings: [], errors: ["Manifest okunamiyor"])
36 }
37 
38 // NSPrivacyTracking kontrolu
39 if plist["NSPrivacyTracking"] == nil {
40 errors.append("NSPrivacyTracking alani eksik")
41 }
42 
43 // Tracking true ise domain listesi olmali
44 if let tracking = plist["NSPrivacyTracking"] as? Bool, tracking {
45 if let domains = plist["NSPrivacyTrackingDomains"] as? [String], domains.isEmpty {
46 errors.append("Tracking aktif ama domain listesi bos")
47 }
48 }
49 
50 // Required Reason API kontrolu
51 if let apiTypes = plist["NSPrivacyAccessedAPITypes"] as? [[String: Any]] {
52 for api in apiTypes {
53 if let reasons = api["NSPrivacyAccessedAPITypeReasons"] as? [String], reasons.isEmpty {
54 let apiType = api["NSPrivacyAccessedAPIType"] as? String ?? "Bilinmeyen"
55 warnings.append("API tipi icin neden belirtilmemis: \(apiType)")
56 }
57 }
58 }
59 
60 return ValidationResult(
61 isValid: errors.isEmpty,
62 warnings: warnings,
63 errors: errors
64 )
65 }
66}

Zorunlu Privacy Manifest Alanlari

Alan
Aciklama
Zorunlu mu?
**NSPrivacyTracking**
Uygulama izleme yapiyor mu
Evet
**NSPrivacyTrackingDomains**
Izleme domainleri
Tracking true ise evet
**NSPrivacyCollectedDataTypes**
Toplanan veri turleri
Evet
**NSPrivacyAccessedAPITypes**
Kullanilan Required Reason API'ler
Evet

4. Required Reason API

Apple, belirli API'lerin kullanilmasi icin gercek bir neden (reason code) belirtilmesini zorunlu kildi.

API Kategorisi
Ornek Kullanim
Neden Kodu
**UserDefaults**
Ayar saklama
CA92.1
**File timestamp**
Dosya degisiklik tarihi
DDA9.1
**System boot time**
Uptime olcumu
35F9.1
**Disk space**
Bos alan kontrolu
E174.1
**Active keyboard**
Klavye listesi
54BD.1

5. Privacy Nutrition Label

App Store Connect'te Privacy Label'i dogru doldurmak kritik oneme sahiptir. Yanlis beyan App Store reddi ile sonuclanir.

Veri Turu
Ornek
Linked / Not Linked
Contact Info
Email, telefon
Genelde Linked
Identifiers
IDFA, Device ID
Tracking ise Linked
Usage Data
Urun etkilesimi
Not Linked olabilir
Diagnostics
Crash log
Genelde Not Linked
Location
GPS, IP-based
Kullanima bagli

6. GDPR ve KVKK Uyumu

Avrupa'da GDPR ve Turkiye'de KVKK, kullanici verileri konusunda siki kurallar getirir.

swift
1// GDPR/KVKK uyumlu consent yonetimi
2protocol ConsentManager {
3 func hasConsent(for purpose: ConsentPurpose) -> Bool
4 func requestConsent(for purposes: [ConsentPurpose]) async -> ConsentResult
5 func revokeConsent(for purpose: ConsentPurpose)
6 func exportUserData() async -> UserDataExport
7 func deleteUserData() async throws
8}
9 
10enum ConsentPurpose: String, CaseIterable {
11 case analytics = "analytics"
12 case advertising = "advertising"
13 case personalization = "personalization"
14 case thirdPartySharing = "third_party_sharing"
15 case crashReporting = "crash_reporting"
16 
17 var isRequired: Bool {
18 // Crash reporting genelde legitimate interest altinda
19 self == .crashReporting
20 }
21 
22 var description: String {
23 switch self {
24 case .analytics: return "Uygulama kullanim istatistikleri"
25 case .advertising: return "Kisisellestrilmis reklamlar"
26 case .personalization: return "Icerik kisisellestirme"
27 case .thirdPartySharing: return "Ucuncu taraf veri paylasimi"
28 case .crashReporting: return "Hata raporlama"
29 }
30 }
31}
32 
33final class GDPRConsentManager: ConsentManager {
34 private let storage: UserDefaults
35 private let apiClient: APIClient
36 
37 init(storage: UserDefaults = .standard, apiClient: APIClient) {
38 self.storage = storage
39 self.apiClient = apiClient
40 }
41 
42 func hasConsent(for purpose: ConsentPurpose) -> Bool {
43 if purpose.isRequired { return true }
44 return storage.bool(forKey: "consent_\(purpose.rawValue)")
45 }
46 
47 func requestConsent(for purposes: [ConsentPurpose]) async -> ConsentResult {
48 // UI goster ve kullanici secimini kaydet
49 let result = await showConsentUI(purposes: purposes)
50 for (purpose, granted) in result.decisions {
51 storage.set(granted, forKey: "consent_\(purpose.rawValue)")
52 }
53 // Server'a da bildir
54 try? await apiClient.syncConsent(result)
55 return result
56 }
57 
58 func revokeConsent(for purpose: ConsentPurpose) {
59 storage.set(false, forKey: "consent_\(purpose.rawValue)")
60 // Ilgili verileri sil
61 Task { try? await apiClient.revokeConsent(purpose) }
62 }
63 
64 /// GDPR Article 20 - Data portability
65 func exportUserData() async -> UserDataExport {
66 await apiClient.requestDataExport()
67 }
68 
69 /// GDPR Article 17 - Right to erasure
70 func deleteUserData() async throws {
71 try await apiClient.requestDataDeletion()
72 // Lokal verileri de temizle
73 clearLocalData()
74 }
75 
76 private func clearLocalData() {
77 let domain = Bundle.main.bundleIdentifier ?? ""
78 storage.removePersistentDomain(forName: domain)
79 }
80 
81 private func showConsentUI(purposes: [ConsentPurpose]) async -> ConsentResult {
82 // Consent UI implementasyonu
83 fatalError("UI implementasyonu gerekli")
84 }
85}
86 
87struct ConsentResult {
88 let decisions: [(ConsentPurpose, Bool)]
89 let timestamp: Date
90 let version: String // Consent policy versiyonu
91}
92 
93struct UserDataExport {
94 let data: Data
95 let format: String // JSON
96 let generatedAt: Date
97}

Kullaniciya seffaf ve anlasilir bir consent ekrani sunmak hem yasal zorunluluk hem de guven insasi acisindan kritiktir. Cookie banner yerine, mobilde "Privacy Settings" ekrani olusturulmalidir.


8. Server-Side Tracking Alternatifleri

ATT sonrasi dunyanin en buyuk degisikliklerinden biri: client-side tracking yerine server-side attribution modelleri.

  • SKAdNetwork 4.0: Apple'in privacy-friendly attribution sistemi
  • Aggregated Measurement: Meta, Google'in toplu olcum API'leri
  • Probabilistic Attribution: IP + User Agent bazli (Apple onaylamaz)
  • First-Party Data: Kendi toplanan veri en degerli kaynak

9. App Store Review Sureci

Privacy konusunda en sik reddedilme nedenleri:

Red Nedeni
Cozum
Privacy label yanlis
Tum SDK'lari ve veri toplamalarini dogru beyan edin
ATT dialog oncesi aciklama yok
Pre-ATT ekrani ekleyin
Gereksiz veri toplama
Minimum veri prensibi uygulayin
Privacy Manifest eksik
xcprivacy dosyasi ekleyin
Purpose string yetersiz
Kullaniciya faydayi aciklayin

10. Test ve Dogrulama

ATT ve privacy ozelliklerini test etmek icin:

  1. Simulatorde ATT testi: Settings > Privacy > Tracking
  2. Privacy Report: Settings > Privacy > App Privacy Report
  3. Network Inspector: Charles/Proxyman ile tracking domain kontrolu
  4. Xcode Privacy Report: Product > Analyze ile privacy sorunu taramasi

11. Sonuc ve Oneriler

Privacy compliance sureci tek seferlik bir is degil, surekli bir surectir. Her iOS guncellemesi yeni gereksinimler getirebilir.

Aksiyon Plani

  • Privacy Manifest dosyasini olusturun veya guncelleyin
  • Tum Required Reason API kullanim nedenlerini belgeleyin
  • ATT dialog zamanlamasini optimize edin
  • Privacy Nutrition Label'i dogru doldurun
  • GDPR/KVKK consent mekanizmasini entegre edin
  • 3rd-party SDK'larin privacy manifest'lerini kontrol edin
  • Server-side attribution'a gecis planlayin
  • Duzgun test ve dogrulama yapin

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

Etiketler

#Privacy#ATT#GDPR#KVKK#App Store#Compliance#iOS
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz