Ana içeriğe geç

02 · POST_CONSENT — Onay Kayıt Sözleşmesi

Görev: Kullanıcının onay ekranındaki seçimini (Tümünü Kabul Et / Zorunlu Olanlar / Tercihleri Düzenle) sunucuya iletir. Sunucu karşılığında onay kaydını oluşturur/günceller, etkinleşen onay kararlarını döndürür ve yeni cihaz durumunu (localState) verir.

Ne zaman çalışır: Kullanıcı onay ekranında bir seçim yaptığında (AUTH → config → ekran → burada).

Bu dosya iki şeyi kapsar: (A) sözleşme (istek/yanıt, doğrulama, hata) ve (B) onayın etiketlere (GA4/GTM) dağıtımı + iOS ATT katmanı.


1. Genel Bakış​

POST_CONSENT, açılış döngüsünün son halkasıdır ve döngüyü kapatır: kullanıcının seçimi kaydedilir, sunucu otoriter son durumu döndürür, SDK bu durumu etiketlerine uygular ve yeni localState'ı önbelleğe yazar — bir sonraki açılışta AUTH'a geri beslenir.

Tasarım felsefesi: Onay, grubun kimliği (groupId) seviyesinde verilir. Bir grup onaylanınca, config'deki o grubun consentKeys listesindeki etiketlerin tümü birlikte açılır; grup kapalıysa tümü birlikte kapanır. Item/teknoloji seviyesinde ayrı onay durumu yoktur. Sunucu yalnız grubun kimliği + son durumu ({ [groupId]: state }) taşır; bu haritanın etiketlere çevrilmesi SDK/entegrasyon tarafında yapılır.

AUTH (00) GET /config (01) POST_CONSENT (BU)
kimlik + localState ▶ token ─▶ tam config ────▶ onay kaydı
│ token │ parse → ekrandaki seçim │ request: actionType + consent map
└── decision.updateRequired ┘ (aynı token) │
│
bir sonraki AUTH ◀─────────── response: consentRecordId + consent + localState

2. Endpoint & Güvenlik​

2.1 Endpoint​

ÖzellikDeğer
MethodPOST
Path/v2/consent/{consentId}/consent
Base URL{{SDK_BASE_URL}}
Gövde formatıapplication/json (UTF-8)
Timeout15 sn
IdempotentEvet — aynı eventId/onay eylemi tekrar gönderilirse aynı kaydı günceller, mükerrer kayıt üretmez.

2.2 Güvenlik (imza + token)​

POST_CONSENT bir YAZMA işlemidir (durumu değiştirir) → bu yüzden hem AUTH'tan alınan token hem HMAC imza birlikte kullanılır:

HeaderDeğer / Formül
Content-Typeapplication/json
X-Consent-TokenAUTH yanıtındaki token (imzalı, oturum bazlı). Bu yazma çağrısıyla oturum kapanır/tüketilir (bkz. 01 §6).
X-Consent-SignatureHMAC-SHA256(token, consentId + actionType + requestTimestamp + nonce) — hex kodlanmış
X-Request-Timestampepoch milliseconds
X-NonceTek kullanımlık rastgele string
  • Algoritma: HMAC-SHA256 (anahtar = AUTH token'ı)
  • İmza girdisi (canonical): consentId + actionType + requestTimestamp + nonce
  • Replay penceresi: ±300 sn; dışında kalan istek → 401 REPLAY_DETECTED.
  • Token geçersiz/süresi dolmuşsa → 401 INVALID_TOKEN (SDK yeniden AUTH yapar).

Neden token + imza birlikte? Token, kimliği (hangi consent oturumu) taşır; HMAC imzası ise bu yazma isteğinin o token sahibi tarafından, taze ve tam olarak üretildiğini kanıtlar — sahte/mükerrer yazma karşı koruma sağlar.


3. İstek (request)​

Kullanıcı onay eylemini temsil eden gövde. camelCase zorunludur.

AlanTipZorunluAçıklama
consentIdstringEvetOnay kaydı kimliği (örn. ck_mobildev_0001). Hangi consent setine yazılacağını belirtir; path'tekine birebir eşit olmalıdır.
actionTypeenum accept_all | reject_all | modifyEvetBasılan buton / onay tipi. Config'deki buton id'leriyle (banner.buttons.list, manager.footer.actions) birebir örtüşür.
consentobjectEvetGRUBUN kimliği seviyesinde onay haritası: { [groupId]: state } düz map (aşağıda detay).
freshUserbooleanEvetBu cihaz/kullanıcı için ilk onay mı? Telemetri + raporlama (ilk-onay oranı).
contentVersionstringEvetOnayın verildiği config içerik sürümü (config.meta.contentVersion). Bir sonraki AUTH'ta remote contentVersion'la karşılaştırılıp reprompt kararı üretilir.
localestring (BCP-47)HayırOnayın verildiği kullanıcı dili (örn. tr-TR). Audit/çeviri referansı.
sdkVersionstring (semver)HayırSDK sürümü. Audit + uyumluluk korelasyonu.
deviceTimestring (ISO 8601 UTC)HayırCihaz saati. Drift/manipülasyon kontrolü.
attentionobject | nullHayıriOS ATT durumu. Android'de null (uygulanmaz). iOS'ta ve promptATTdialog: true iken dolu olur (§7).

consent, düz bir haritadır: anahtar = groupId, değer = state (örn. {"essential":"granted","targeting":"denied"}).

BileşenTipAçıklama
Anahtar (groupId)stringconfig.manager.groups[].id (örn. essential, functionality, targeting, tracking). Hangi grubun durumunun iletildiğini belirtir.
Değer (state)enum granted | deniedGrubun son durumu (yalnız bu iki değer). granted → grubun tüm consentKeys'i etkinleşir; denied → tümü kapatılır (çeviri SDK tarafında, §6).

Neden item-seviye state yok? GTM/etiket API'leri key bazlı çalışır; eski item-bazlı {title, state} yapısı bu modelle çelişiyordu. Bu sözleşmede onay durumu yalnızca grup (groupId) seviyesinde düz bir map olarak taşınır; item'lar (teknoloji/vendor) config tarafında yalnız bilgilendirme amaçlıdır ve grupla birlikte açılıp kapanır.

3.2 Örnek İstek (modify + karma durum)​

{
"consentId": "ck_mobildev_0001",
"actionType": "modify",
"freshUser": true,
"contentVersion": "2",
"locale": "tr-TR",
"sdkVersion": "1.4.0",
"deviceTime": "2026-09-20T11:33:29Z",
"attention": null,
"consent": {
"essential": "granted",
"functionality": "granted",
"targeting": "denied",
"tracking": "denied"
}
}

Ayrıca header'da: X-Consent-Token + X-Consent-Signature + X-Nonce + X-Request-Timestamp (§2.2). attention örnekte null çünkü platform Android. iOS'ta ATT'ye tabi bir grup onaylanacaksa dolu gönderilir (§7). Bu örneğin aynısı ayrıca [02-postconsent.request.json](./02-postconsent.request.json) dosyasında yer alır.


4. Yanıt (response)​

4.1 Gövde Alanları (200)​

AlanTipAçıklama
successbooleanOnay eyleminin başarılı işlendiği.
codestringDurum kodu (başarıda OK).
consentRecordIdstringOluşturulmuş/güncellenmiş onay kaydının benzersiz kimliği. Telemetri/raporlama + audit korelasyonunun anahtarıdır.
storedAtstring (ISO 8601 UTC)Kaydın işlendiği sunucu zamanı.
actionTypestringÇözülen onay tipi (eko; audit).
consentobjectOtoriter onay haritası: { [groupId]: granted | denied } — sunucunun doğruladığı son sonuç. SDK bunu §6'daki eşlemeyle etiket key'lerine yayarak uygular.
localStateobjectYeni cihaz durumu. SDK bunu önbelleğe yazar; bir sonraki AUTH istek girdisi olarak geri besler (retrigger zinciri).

4.2 localState Alt Alanları​

localState, 00 · AUTH isteğindeki localState ile birebir aynı yapıdadır — döngünün geri beslemesidir:

AlanTipAçıklama
hasConsentbooleanArtık true (bu cihazda onay saklı).
installedUiVersionstringCihaza yazılan UI versiyonu.
installedLegalVersionstringCihaza yazılan legal/metin versiyonu.
installedContentVersionstringOnayın verildiği içerik versiyonu (request.contentVersion).
lastShownAtstring (ISO 8601)Onay ekranının gösterildiği/saklandığı an (interval retrigger için).
consentobjectGövdedeki consent haritasının aynısı (groupId → state); bir sonraki AUTH'ın localState.consent'i.

İki consent alanı neden var? Gövdedeki consent, SDK'ın etiketlere uygulayacağı sonuç; localState.consent, depolanacak geri besleme. İkisi de { [groupId]: state } haritasıdır ve içerik aynıdır; ayrım, "uygula" ile "hatırla" amaçlarının farklı olmasındandır.

4.3 Örnek Yanıt (200)​

{
"success": true,
"code": "OK",
"consentRecordId": "cr_9f2e6a4b8c1d",
"storedAt": "2026-09-20T11:33:31Z",
"actionType": "modify",
"consent": {
"essential": "granted",
"functionality": "granted",
"targeting": "denied",
"tracking": "denied"
},
"localState": {
"hasConsent": true,
"installedUiVersion": "2.4",
"installedLegalVersion": "1.0",
"installedContentVersion": "2",
"lastShownAt": "2026-09-20T11:33:31Z",
"consent": {
"essential": "granted",
"functionality": "granted",
"targeting": "denied",
"tracking": "denied"
}
}
}

Bu örneğin aynısı ayrıca [02-postconsent.response.json](./02-postconsent.response.json) dosyasında yer alır.


5. actionType → Karar Matrisi​

actionType, grup durumlarını belirler. modify dışında durumlar implicittir (buton mantığı); modify explicittir (kullanıcının grup bazlı toggle'ları). essential her durumda granted'tir (kilitli, §6).

actionTypeessentialfunctionalitytargetingtrackingconsent map
accept_allgrantedgrantedgrantedgrantedimplicit (hepsi granted)
reject_allgranteddenieddenieddeniedimplicit (yalnız essential granted)
modifygranted*kullanıcıkullanıcıkullanıcıexplicit (kullanıcının state'leri)

* essential içindeki security_storage asla denied yapılamaz — kilitlidir.

Config buton eşlemesi: banner.buttons.list → accept_all / reject_all / modify; manager.footer.actions → accept_all / save (save ≡ modify); detail.actions → save (≡ modify). Yani üç davranış: hepsi, yalnız zorunlu, düzenle.


6. Onay → Etiket (GA4 / GTM) Dağıtımı​

Bu bölüm, onayın gerçek etkisini tanımlar: kullanıcının grup bazlı tercihinin, uygulamanızdaki etiketlere granted/denied olarak nasıl yansıtılacağı. Dağıtımın sorumluluğu SDK/entegrasyon tarafındadır; sunucu yalnız { [groupId]: state } döndürür.

6.1 Config'deki grup → etiket key eşleşmesi​

Config'deki her grup, bir consentKeys[] listesi taşır. Tipik dört grup ve karşılık gelen etiket key'leri:

Config group.idKategoriconsentKeys[] (etiket key'leri)Varsayılan
essentialZorunlusecurity_storagegranted (kilitli)
functionalityİşlevsellikpersonalization_storage, functionality_storagedenied
targetingHedefleme / reklamad_storage, ad_user_data, ad_personalizationdenied
trackingİzleme / performansanalytics_storagedenied

7 key'in tamamı, GTM Consent Mode v2'de built-in'dir. ad_user_data ve ad_personalization, v2'de zorunludur (default state'leri denied). Bu 7 key için ek "custom" Consent Setting tanımlamak gerekmez — yalnızca §6.4'teki Consent Command + tetikleyici trigger'ları kurmanız yeterlidir.

İsim farkına dikkat: personalization_storage (içerik/deneyim kişiselleştirme, reklam dışı) ≠ ad_personalization (reklam kişiselleştirme/yeniden pazarlama). İkisi farklı key'lerdir; isim benzerliğine düşmeyin.

6.2 Dağıtım mantığı (SDK tarafında)​

SDK, response consent haritasındaki her groupId'yi, yerel config'deki o grubun consentKeys[] kümesine yayarak etiketlere uygular:

// groupId → GTM consentKeys dağıtımı (SDK / entegrasyon tarafı)
function applyConsentToGTM(config, consentMap) {
const consent = {};
for (const group of config.manager.groups) {
const state = consentMap[group.id]; // "granted" | "denied"
const effective = group.lockState === true ? "granted" : (state || "denied");
for (const key of group.consentKeys) {
consent[key] = effective; // grup state'i → o grubun tüm key'lerine
}
}
// security_storage (lock) her zaman granted; diğerleri kullanıcı tercihine göre
// Config'de yer almayan bir key için varsayılan "denied" (güvenli taraf)
window.dataLayer.push({ event: 'consent_update', ...consent });
}

Kural seti:

  • Grup onaylı (granted) → o grubun consentKeys'indeki tüm key'ler granted.
  • Grup kapalı (denied) → o gruptaki tüm key'ler denied.
  • essential (→ security_storage) → her zaman granted (kilitli; lockState: true). Kullanıcı kapatamaz.
  • Config'de yer almayan key → varsayılan denied (güvenli taraf).
  • Önemli ayrım: Onay durumu grupta tutulur; item'lar etiket key taşımaz. Dağıtım her zaman group.consentKeys[] üzerinden yapılır.

6.3 Durum değerleri & gönderim​

Her key yalnız granted veya denied değerini alır — ara durum yoktur. Gönderim, projenize göre iki eşdeğer yoldan biridir:

YolKomutNot
GA4 gtag.jsgtag('consent', 'default' | 'update', <states>)wait_for_update yalnız default komutundadır.
GTM dataLayerwindow.dataLayer.push({ 'event': 'default_consent' | 'consent_update', ...flat keys })Eşdeğer; GTM tag/trigger'ları consent state'lerine bakar.

<states> objesi iki yolda da aynıdır: 7 key'in tamamı + her birinin granted/denied değeri.

Komutlar:

  • default (ilk yükleme): Varsayılan state'leri set eder. Non-essential key'ler denied, security_storage granted. wait_for_update (ms) eklenirse etiketler, gerçek tercih gelene dek bu süre kadar bekletilir → rızasız veri işlemesi önlenir, config gecikmesine karşı denge kurulur (pratik başlangıç 300–1000 ms).
  • update (kullanıcı tercihini verince veya iznini geri çekince): State'leri günceller. Opt-out (izin geri çekme) da update + ilgili key'leri denied yapılır. remove diye bir komut yoktur.

Örnek state gövdeleri:

// default: ilk yükleme (kullanıcı tercih bildirmedi)
{ ad_storage:'denied', analytics_storage:'denied', ad_user_data:'denied',
ad_personalization:'denied', functionality_storage:'denied',
personalization_storage:'denied', security_storage:'granted' }

// update · "Tümünü Kabul Et": hepsi granted
{ ad_storage:'granted', analytics_storage:'granted', ad_user_data:'granted',
ad_personalization:'granted', functionality_storage:'granted',
personalization_storage:'granted', security_storage:'granted' }

// update · "Zorunlu Olanlar": yalnız security_storage granted, diğerleri denied
{ ad_storage:'denied', analytics_storage:'denied', ad_user_data:'denied',
ad_personalization:'denied', functionality_storage:'denied',
personalization_storage:'denied', security_storage:'granted' }

Çerez silme uyarısı: Bir key'i denied yapmak, Google etiketlerinin o andan itibaren çerez okuma/yazmasını durdurur; tarayıcıda daha önce oluşturulmuş çerezleri ise silmez. Çerezleri tamamen temizlemek gerekiyorsa bu, SDK tarafında document.cookie üzerinden manuel yapılır — Consent Mode bunu yapmaz.

6.4 GTM Console'da kurulacaklar (özet)​

  • 7 key built-in → ek custom Consent Setting gerekmez.
  • dataLayer yolunu seçtiyseniz: Console'da default_consent → Default ve consent_update → Update Consent Command'larını ve bunları dinleyen trigger'ları tanımlayın. Event ↔ Command eşleşmesi kurulmazsa dataLayer push'ı sonuçsuz gider. (GA4 gtag yolunu kullanıyorsanız bu gerekmez — gtag('consent', …) doğrudan çalışır.)
  • Key adları birebir aynı olmalı (küçük harf): ad_storage, analytics_storage, ad_user_data, ad_personalization, functionality_storage, personalization_storage, security_storage. Büyük harf veya eski/farklı ad kullanmayın.

7. Doğrulama (Sunucu tarafında)​

Sunucu kaydı işlemekten önce aşağıdaki kontrolleri yapar; ihlalde ilgili hata kodu döner:

#Kuralİhlal → Hata
V1essential'in state ≠ denied (kilit)ESSENTIAL_LOCKED (sunucu granted'e zorlar + uyarı)
V2Her consent anahtarı (= groupId), config groups[].id içinde olmalıUNKNOWN_GROUP
V3state ∈ deniedINVALID_STATE
V4actionType === "modify" ise consent haritası non-empty olmalıMISSING_CUSTOM_STATES
V5actionType ∈ {accept_all, reject_all} + explicit grup state'leri aksi yönde ise tutarsızACTION_STATE_MISMATCH
V6iOS + promptATTdialog === true + onay ≥1 ATT'ye tabi gruba granted + attention.status == notDetermined → kayıt REDDEDİLİR (SDK önce ATT'yi çözmeli). denied/restricted reddedilmez (terminal/kullanıcı tercihi) → ATT'ye tabi gruplar GTM'de AND gate ile denied (§7.4)ATT_REQUIRED

contentVersion kontrolü: request.contentVersion, config'in mevcut contentVersion'ından farklı (daha eski) bir sürümse kayıt tutulur, ancak çıktı reprompt gerektirebileceğini işaret eder (kullanıcı eski içeriğe onay verdi, içerik değişti → bir sonraki açılışta tekrar sor).


8. Hata Kodları​

Hatalarda ortak gövde döner: { success:false, code, message, retryable, requestId }. message teşhis metnidir; UI'da gösterilmez (kullanıcıya gösterilecek metin config localization'ından gelir).

codeHTTPretryableAçıklama / SDK müdahalesi
OK200—Onay eylemi başarılı işlendi.
INVALID_TOKEN401Evettoken geçersiz/süresi dolmuş → yeniden AUTH.
SIGNATURE_MISMATCH401HayırHMAC imza doğrulanamadı → imza girdisi/token kontrolü.
REPLAY_DETECTED401HayırNonce tekrar/timestamp replay penceresi dışı → cihaz saati + nonce.
CONSENT_NOT_FOUND404HayırconsentId kaydı yok.
ESSENTIAL_LOCKED400Hayıressential denied olarak gönderildi → sunucu granted'e zorlar.
UNKNOWN_GROUP400HayırGeçersiz groupId → config groups[].id'lerle karşılaştır.
INVALID_STATE400Hayırstate granted/denied dışı.
MISSING_CUSTOM_STATES400Hayırmodify gönderildi ama consent haritası boş → SDK grup durumlarını üretmeli.
ACTION_STATE_MISMATCH400HayıractionType ile explicit group state'leri tutarsız.
ATT_REQUIRED400EvetiOS + ATT'ye tabi grup onaylanıyor + attention.status == notDetermined. → SDK ATT'yi çöz (requestTrackingAuthorization) ve yeniden post. denied/restricted bu kodu üretmez (§7.3/§7.4).
RATE_LIMITED429EvetHız sınırı → Retry-After kadar bekle.
SERVER_ERROR500EvetSunucu iç hata → onay önbellekte bekletilir, arka planda yeniden denenebilir.

Önemli (KRİTİK): Onay eylemi başarısız olursa (500/429/ağ), SDK onay kararını yalnızca cihazda (localState) saklar ve bağlantı gelince yeniden post eder — kullanıcının onayı kaybolmaz. Sunucu 500 dönerse mükerrer kayıt riski eventId-tabanlı idempotency ile önlenir.


9. iOS ATT Katmanı (kısa)​

iOS'ta reklam/hedefleme takibi, cookie consent yanında işletim sisteminin ATT (App Tracking Transparency) iznini de gerektirir. Bu bölüm, ana akışın iOS özel yan dallarını özetler.

Android'de ATT karşılığı yoktur → attention: null, bu bölüm devre dışıdır (no-op). ATT bir HTTP endpoint'i değil, iOS sistem iznidir. Sunucuyla tek temas noktası, isteğe attention alanı eklemektir; sistem prompt'u SDK tarafından AppTrackingTransparency (ATTrackingManager) ile atılır.

9.1 İki ayrı izin katmanı​

KatmanNe izlerKim yönetir
Cookie consent (bu SDK)Depolama + teknoloji kullanımıSDK / CMP
ATT (iOS sistemi)IDFA ile çapraz-uygulama reklam takibiİşletim sistemi

Kullanıcı consent'te targeting'i onaylasa bile ATT verilmediyse reklam sağlayıcıları IDFA'yı okuyamaz → takip fiilen yapılamaz. Bu yüzden onay akışıyla ATT uyumlu çalıştırılır ve sonuç GTM'e doğru yansıtılır.

9.2 Durum modeli (4 durum)​

SDK, ham ATT sonucunu 4 duruma haritalar. İstekteki attention.status:

statusAnlamOnaya etkisi
notDeterminedHenüz sorulmadıATT'ye tabi grup onaylanacaksa sistem prompt atılmalıdır; çözülmeden takip onayı kaydolunmaz (V6).
authorizedKullanıcı takibi izinlediATT'ye tabi gruplar onaylanabilir → takip çalışır.
deniedKullanıcı takibi reddettiKayıt engelLENMEZ; ATT'ye tabi gruplar GTM'de denied (§9.4) + danışma mesajı.
restrictedEbeveyn/MDM sistemi takibi engellediKullanıcı kendi başına değiştiremez; kayıt engelLENMEZ; ATT'ye tabi gruplar GTM'de denied + bilgilendirme.

9.3 Ne zaman sistem prompt atılır? (just-in-time)​

Sistem dialog'u açılışta herkese değil, gerektiği anda atılır (çift-sorma yorgunluğunu önler). Prompt atılır yalnızca aşağıdakilerin tümü sağlanırsa:

  1. platform === "iOS" VE
  2. behavior.promptATTdialog === true VE
  3. attention.status === "notDetermined" VE
  4. Kullanıcının onayı ≥1 ATT'ye tabi grubu granted yapıyor (§9.5'teki ATT'ye tabi key setiyle kesişimi var).

Bu koşullar sağlanmıyorsa (örn. reject_all, ya da targeting kapalı modify) prompt atılmaz; ATT notDetermined kalır ve bu sorun değildir (takip istenmedi, V6 tetiklenmez).

9.4 AND gate (onay ↔ ATT birleşimi)​

ATT'ye tabi bir grubun GTM'de fiilen geçerli olması için kullanıcının tercihi VE sistem ATT izni birlikte granted olmalıdır:

effective(grup) = granted → user_choice(grup)==granted VE attention.status==authorized
effective(grup) = denied → yukarıdaki koşul sağlanmazsa
(ATT'ye tabi olmayan gruplar: effective = user_choice; ATT'den etkilenmez)
Kullanıcı (targeting)attention.statusGTM'de etkiliKullanıcıya gösterilen
deniedherhangidenied(normal)
grantedauthorizedgranted(normal)
granteddenieddeniedDanışma: "Ayarlar'da takibi kapattınız; tercih kaydınızda ama takip sistemi gereği devre dışı." + Settings kısayolu
grantedrestricteddeniedBilgi: "Takip, ebeveyn/sistem ayarı nedeniyle engelleniyor."

Böylece kullanıcı "Tümünü Kabul Et" dese bile ATT verilmediyse reklam key'leri GTM'de denied kalır → izinsiz takip gerçekleşmez. Tercihi kaydetmek (audit) ile takibi fiilen bloklamak (ATT) ayrı halledilir; displayATTStatus: true ise bunu kullanıcıya şeffafça gösterir.

9.5 ATT'ye tabi key'ler (kod tarafı)​

ATT yalnız IDFA/çapraz-uygulama reklam takibini kapsar:

const ATT_GATED_KEYS = new Set(["ad_storage", "ad_user_data", "ad_personalization"]);
function isATTGated(group) {
return group.consentKeys.some(k => ATT_GATED_KEYS.has(k));
}

Kural: "ATT'ye tabi grup" = consentKeys ∩ {ad_storage, ad_user_data, ad_personalization} ≠ ∅ olan gruptur (tipik olarak targeting). tracking (analitik), functionality ve essential ATT'den bağımsızdır — kullanıcı analitiği onaylasa bile ATT reddetse analitik çalışır. Bu ayrım, ATT prompt'unu yalnızca gerçekten reklam takibi gerektiğinde atmak için kritiktir.

9.6 iOS kurulum notları​

  • @import / import AppTrackingTransparency; durum ATTrackingManager.trackingAuthorizationStatus, prompt ATTrackingManager.requestTrackingAuthorization(completion:).
  • NSTrackingUsageDescription (Info.plist) ZORUNLUDUR — yoksa requestTrackingAuthorization() uygulama crash'er. Kullanıcıya "neden soruyoruz" metnidir.
  • Apple once-only kuralı: sistem dialog'u yalnız bir kez (durum notDetermined iken) gösterilir. Kullanıcı reddettiyse dialog yeniden açılmaz; bu durumda SDK kendi yeniden-soru UI'ı + Settings derin bağlantısı ile kullanıcıyı yönlendirir.
  • restricted türetimi: restricted bir Apple enum'ı değildir; ebeveyn/MDM engeli ham .denied'i verir. SDK bu durumu yardımcı sinyalle ayırarak restricted olarak modeler (kullanıcı geri alamaz → kayıt bloklamaz).
  • ATT durumunu cihazda kalıcı saklayın; sonraki her POST_CONSENT'te attention.status'u taşıyın (audit + V6 doğruluğu + retrigger tutarlılığı).

10. Developer Notları​

  1. Onay, grubun kimliğinde (groupId) taşınır — istekte ve yanıttan aynı düz map formatı: { [groupId]: state }. Item/teknoloji bazında ayrı state YOKTUR. Etiketlere çevirimi SDK tarafında yapar (6.2).
  2. state yalnız granted / denied. Ara durumlar desteklenmez.
  3. essential kilitli. security_storage her zaman granted; kullanıcı kapatamaz. Sunucu gerekirse granted'e zorlar (V1).
  4. Kimlik = token + HMAC. Her onay post'unda ayrı API key taşımak yerine, açılışta alınan tek token kullanılır (§2.2).
  5. Geri besleme döngüsü: Yanıt localState, bir sonraki AUTH'ın girdisidir. installedContentVersion ≠ remote contentVersion ise reprompt tetiklenir. Bu zincir "onay ver → içerik değişsin → yeniden sor" davranışının omurgasıdır.
  6. Idempotency: Aynı onay eylemi (ağ tekrarında) eventId/nonce ile tek kayıt olarak işlenir; mükerrer consent record üretilmez. consentRecordId raporlama/audit akışına akar.
  7. groupId → consentKeys çevirimi SDK sorumluluğudur: Her groupId'yi yerel config'deki groups[].consentKeys kümesine yayın. Bir groupId yerel config'de karşılık bulamazsa (config/içerik sürüm farkı) o key'i uygulayamazsınız → güvenli yığın/uyarı üretin; kullanıcının onayı localState sayesinde kaybolmaz.
  8. IOS'ta ATT'yi çöz, sonra post: ATT_REQUIRED alırsanız requestTrackingAuthorization ile ATT'yi çözün (notDetermined → authorized/denied) ve yeniden post edin. denied/restricted kaydı bloklamaz; yalnızca AND gate (9.4) reklam key'lerini kapatır.

Bu doküman size yardımcı oldu mu?

Değerlendirmeniz, dokümanı geliştirmemize yardımcı olur.

Değerlendirme yapmak için giriş yapmalısınız.

Destek soruları ve yorumlar

Bu dokümanla ilgili soru sorabilir veya deneyiminizi paylaşabilirsiniz.