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
| Özellik | Değer |
|---|---|
| Method | POST |
| Path | /v2/consent/{consentId}/consent |
| Base URL | {{SDK_BASE_URL}} |
| Gövde formatı | application/json (UTF-8) |
| Timeout | 15 sn |
| Idempotent | Evet — 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:
| Header | Değer / Formül |
|---|---|
Content-Type | application/json |
X-Consent-Token | AUTH yanıtındaki token (imzalı, oturum bazlı). Bu yazma çağrısıyla oturum kapanır/tüketilir (bkz. 01 §6). |
X-Consent-Signature | HMAC-SHA256(token, consentId + actionType + requestTimestamp + nonce) — hex kodlanmış |
X-Request-Timestamp | epoch milliseconds |
X-Nonce | Tek 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.
| Alan | Tip | Zorunlu | Açıklama |
|---|---|---|---|
consentId | string | Evet | Onay kaydı kimliği (örn. ck_mobildev_0001). Hangi consent setine yazılacağını belirtir; path'tekine birebir eşit olmalıdır. |
actionType | enum accept_all | reject_all | modify | Evet | Basılan buton / onay tipi. Config'deki buton id'leriyle (banner.buttons.list, manager.footer.actions) birebir örtüşür. |
consent | object | Evet | GRUBUN kimliği seviyesinde onay haritası: { [groupId]: state } düz map (aşağıda detay). |
freshUser | boolean | Evet | Bu cihaz/kullanıcı için ilk onay mı? Telemetri + raporlama (ilk-onay oranı). |
contentVersion | string | Evet | Onayı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. |
locale | string (BCP-47) | Hayır | Onayın verildiği kullanıcı dili (örn. tr-TR). Audit/çeviri referansı. |
sdkVersion | string (semver) | Hayır | SDK sürümü. Audit + uyumluluk korelasyonu. |
deviceTime | string (ISO 8601 UTC) | Hayır | Cihaz saati. Drift/manipülasyon kontrolü. |
attention | object | null | Hayır | iOS ATT durumu. Android'de null (uygulanmaz). iOS'ta ve promptATTdialog: true iken dolu olur (§7). |
3.1 consent Map Yapısı
consent, düz bir haritadır: anahtar = groupId, değer = state (örn. {"essential":"granted","targeting":"denied"}).
| Bileşen | Tip | Açıklama |
|---|---|---|
Anahtar (groupId) | string | config.manager.groups[].id (örn. essential, functionality, targeting, tracking). Hangi grubun durumunun iletildiğini belirtir. |
Değer (state) | enum granted | denied | Grubun 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örnektenullçü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)
| Alan | Tip | Açıklama |
|---|---|---|
success | boolean | Onay eyleminin başarılı işlendiği. |
code | string | Durum kodu (başarıda OK). |
consentRecordId | string | Oluşturulmuş/güncellenmiş onay kaydının benzersiz kimliği. Telemetri/raporlama + audit korelasyonunun anahtarıdır. |
storedAt | string (ISO 8601 UTC) | Kaydın işlendiği sunucu zamanı. |
actionType | string | Çözülen onay tipi (eko; audit). |
consent | object | Otoriter onay haritası: { [groupId]: granted | denied } — sunucunun doğruladığı son sonuç. SDK bunu §6'daki eşlemeyle etiket key'lerine yayarak uygular. |
localState | object | Yeni 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:
| Alan | Tip | Açıklama |
|---|---|---|
hasConsent | boolean | Artık true (bu cihazda onay saklı). |
installedUiVersion | string | Cihaza yazılan UI versiyonu. |
installedLegalVersion | string | Cihaza yazılan legal/metin versiyonu. |
installedContentVersion | string | Onayın verildiği içerik versiyonu (request.contentVersion). |
lastShownAt | string (ISO 8601) | Onay ekranının gösterildiği/saklandığı an (interval retrigger için). |
consent | object | Gövdedeki consent haritasının aynısı (groupId → state); bir sonraki AUTH'ın localState.consent'i. |
İki
consentalanı neden var? Gövdedekiconsent, 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).
actionType | essential | functionality | targeting | tracking | consent map |
|---|---|---|---|---|---|
accept_all | granted | granted | granted | granted | implicit (hepsi granted) |
reject_all | granted | denied | denied | denied | implicit (yalnız essential granted) |
modify | granted* | 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.id | Kategori | consentKeys[] (etiket key'leri) | Varsayılan |
|---|---|---|---|
essential | Zorunlu | security_storage | granted (kilitli) |
functionality | İşlevsellik | personalization_storage, functionality_storage | denied |
targeting | Hedefleme / reklam | ad_storage, ad_user_data, ad_personalization | denied |
tracking | İzleme / performans | analytics_storage | denied |
7 key'in tamamı, GTM Consent Mode v2'de built-in'dir.
ad_user_datavead_personalization, v2'de zorunludur (default state'leridenied). 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 grubunconsentKeys'indeki tüm key'lergranted. - Grup kapalı (
denied) → o gruptaki tüm key'lerdenied. essential(→security_storage) → her zamangranted(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:
| Yol | Komut | Not |
|---|---|---|
| GA4 gtag.js | gtag('consent', 'default' | 'update', <states>) | wait_for_update yalnız default komutundadır. |
| GTM dataLayer | window.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'lerdenied,security_storagegranted.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) daupdate+ ilgili key'lerideniedyapılır.removediye 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
deniedyapmak, 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ındadocument.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 veconsent_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 |
|---|---|---|
| V1 | essential'in state ≠ denied (kilit) | ESSENTIAL_LOCKED (sunucu granted'e zorlar + uyarı) |
| V2 | Her consent anahtarı (= groupId), config groups[].id içinde olmalı | UNKNOWN_GROUP |
| V3 | state ∈ denied | INVALID_STATE |
| V4 | actionType === "modify" ise consent haritası non-empty olmalı | MISSING_CUSTOM_STATES |
| V5 | actionType ∈ {accept_all, reject_all} + explicit grup state'leri aksi yönde ise tutarsız | ACTION_STATE_MISMATCH |
| V6 | iOS + 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 mevcutcontentVersion'ı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).
code | HTTP | retryable | Açıklama / SDK müdahalesi |
|---|---|---|---|
OK | 200 | — | Onay eylemi başarılı işlendi. |
INVALID_TOKEN | 401 | Evet | token geçersiz/süresi dolmuş → yeniden AUTH. |
SIGNATURE_MISMATCH | 401 | Hayır | HMAC imza doğrulanamadı → imza girdisi/token kontrolü. |
REPLAY_DETECTED | 401 | Hayır | Nonce tekrar/timestamp replay penceresi dışı → cihaz saati + nonce. |
CONSENT_NOT_FOUND | 404 | Hayır | consentId kaydı yok. |
ESSENTIAL_LOCKED | 400 | Hayır | essential denied olarak gönderildi → sunucu granted'e zorlar. |
UNKNOWN_GROUP | 400 | Hayır | Geçersiz groupId → config groups[].id'lerle karşılaştır. |
INVALID_STATE | 400 | Hayır | state granted/denied dışı. |
MISSING_CUSTOM_STATES | 400 | Hayır | modify gönderildi ama consent haritası boş → SDK grup durumlarını üretmeli. |
ACTION_STATE_MISMATCH | 400 | Hayır | actionType ile explicit group state'leri tutarsız. |
ATT_REQUIRED | 400 | Evet | iOS + 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_LIMITED | 429 | Evet | Hız sınırı → Retry-After kadar bekle. |
SERVER_ERROR | 500 | Evet | Sunucu 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 riskieventId-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ğeattentionalanı eklemektir; sistem prompt'u SDK tarafındanAppTrackingTransparency(ATTrackingManager) ile atılır.
9.1 İki ayrı izin katmanı
| Katman | Ne izler | Kim 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:
status | Anlam | Onaya etkisi |
|---|---|---|
notDetermined | Henüz sorulmadı | ATT'ye tabi grup onaylanacaksa sistem prompt atılmalıdır; çözülmeden takip onayı kaydolunmaz (V6). |
authorized | Kullanıcı takibi izinledi | ATT'ye tabi gruplar onaylanabilir → takip çalışır. |
denied | Kullanıcı takibi reddetti | Kayıt engelLENMEZ; ATT'ye tabi gruplar GTM'de denied (§9.4) + danışma mesajı. |
restricted | Ebeveyn/MDM sistemi takibi engelledi | Kullanı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:
platform === "iOS"VEbehavior.promptATTdialog === trueVEattention.status === "notDetermined"VE- Kullanıcının onayı ≥1 ATT'ye tabi grubu
grantedyapı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.status | GTM'de etkili | Kullanıcıya gösterilen |
|---|---|---|---|
denied | herhangi | denied | (normal) |
granted | authorized | granted | (normal) |
granted | denied | denied | Danışma: "Ayarlar'da takibi kapattınız; tercih kaydınızda ama takip sistemi gereği devre dışı." + Settings kısayolu |
granted | restricted | denied | Bilgi: "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 olaraktargeting).tracking(analitik),functionalityveessentialATT'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; durumATTrackingManager.trackingAuthorizationStatus, promptATTrackingManager.requestTrackingAuthorization(completion:).NSTrackingUsageDescription(Info.plist) ZORUNLUDUR — yoksarequestTrackingAuthorization()uygulama crash'er. Kullanıcıya "neden soruyoruz" metnidir.- Apple once-only kuralı: sistem dialog'u yalnız bir kez (durum
notDeterminediken) 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. restrictedtüretimi:restrictedbir Apple enum'ı değildir; ebeveyn/MDM engeli ham.denied'i verir. SDK bu durumu yardımcı sinyalle ayırarakrestrictedolarak 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ı
- 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). stateyalnızgranted/denied. Ara durumlar desteklenmez.essentialkilitli.security_storageher zamangranted; kullanıcı kapatamaz. Sunucu gerekirsegranted'e zorlar (V1).- 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).
- Geri besleme döngüsü: Yanıt
localState, bir sonraki AUTH'ın girdisidir.installedContentVersion ≠ remote contentVersionise reprompt tetiklenir. Bu zincir "onay ver → içerik değişsin → yeniden sor" davranışının omurgasıdır. - Idempotency: Aynı onay eylemi (ağ tekrarında)
eventId/nonce ile tek kayıt olarak işlenir; mükerrer consent record üretilmez.consentRecordIdraporlama/audit akışına akar. groupId → consentKeysçevirimi SDK sorumluluğudur: HergroupId'yi yerel config'dekigroups[].consentKeyskümesine yayın. BirgroupIdyerel 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ılocalStatesayesinde kaybolmaz.- IOS'ta ATT'yi çöz, sonra post:
ATT_REQUIREDalırsanızrequestTrackingAuthorizationile ATT'yi çözün (notDetermined→authorized/denied) ve yeniden post edin.denied/restrictedkaydı 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.