Как DSP обрабатывают постбеки SKAdNetwork? Платформы спроса (DSP) и рекламные сети обрабатывают постбеки SKAdNetwork путем настройки безопасных эндпоинтов приёма данных по протоколу HTTPS POST, формирования сериализованной строки сообщения в кодировке UTF-8 с использованием разделителя U+2063, проверки криптографической подписи Apple ECDSA P-256 по опубликованному открытому ключу Apple, а также регистрации проверенных идентификаторов транзакций для предотвращения дублирования обработки перед обновлением моделей назначения ставок.
Постбек валидации установки SKAdNetwork — это подписанное Apple уведомление HTTPS POST, которое операционная система отправляет соответствующей рекламной сети и, для успешных атрибуций, опционально на настроенный конечный эндпоинт разработчика рекламируемого приложения. Для обеспечения целостности данных бэкенд-системы приёма должны проверять подпись Apple ECDSA P-256, валидировать сериализацию параметров и обеспечивать дедупликацию на уровне транзакций.
| Термин | Определение |
|---|---|
| SKAdNetwork | Платформенный фреймворк Apple для конфиденциальной атрибуции рекламных кампаний. |
| Постбек валидации установки | Подписанный Apple JSON-пейлоуд, содержащий метаданные валидации установки и атрибуции после успешной рекламной конверсии. |
| ECDSA P-256 | Алгоритм криптографии на эллиптических кривых, используемый Apple для подписи постбеков валидации установки. |
| Идентификатор транзакции (Transaction ID) | Уникальный идентификатор валидации, который получатели используют в качестве ключа идемпотентности для обнаружения дубликатов. |
Архитектура приема постбеков SKAdNetwork для DSP и рекламных сетей
Двойной конвейер приема: прямая доставка рекламной сети против эндпоинтов постбеков разработчика
При совершении атрибутированной установки приложения iOS подсистема атрибуции Apple отправляет постбеки валидации установки через HTTPS POST:
- Прием рекламной сетью: Устройство доставляет основной выигрышный постбек (
did-win: true) напрямую на URL-адрес сервера, зарегистрированный под соответствующимad-network-idв реестре Apple. - Прием копии разработчиком: Если рекламируемое приложение указывает ключ
NSAdvertisingAttributionReportEndpointв своем файлеInfo.plist, устройство одновременно отправляет точную копию выигрышного постбека непосредственно на сервер разработчика. - Маршрутизация проигравших постбеков: Начиная с SKAdNetwork 3.0, если несколько рекламных сетей соответствовали критериям атрибуции, но не выиграли, устройство отправляет до пяти проигравших постбеков (
did-win: false) напрямую этим вторичным квалифицированным рекламным сетям. Проигравшие постбеки не доставляются на эндпоинт копии разработчика.
Эндпоинты приема на бэкенде должны отвечать кодом HTTP 200 OK. Если устройство не получает ответ 200, оно может повторить доставку до девяти раз в течение максимум девяти дней.

Роль NSAdvertisingAttributionReportEndpoint в аудите разработчика
Параметр NSAdvertisingAttributionReportEndpoint позволяет разработчикам приложений получать прямые копии выигрышных постбеков независимо от пересылки рекламной сетью:
- Независимый аудит: Разработчики получают точные копии всех выигрышных постбеков, созданных для их приложения, что обеспечивает внутреннюю валидацию отчетности рекламных сетей.
- Выделенный путь эндпоинта: Сервер разработчика должен размещать эндпоинт по адресу
https://<domain>/.well-known/skadnetwork/report-attribution/. - Различие с AdAttributionKit: Для AdAttributionKit Apple определяет отдельную конфигурацию маршрутизации на
https://<domain>/.well-known/appattribution/report-attribution/, которая использует архитектуру проверки JSON Web Signature (JWS).
Как MMP принимают, агрегируют и нормализуют потоки S2S-событий из нескольких сетей
В зависимости от коммерческих интеграций мобильные партнеры по измерению (MMP) могут принимать данные SKAdNetwork посредством пересылки на стороне разработчика, интеграций с рекламными сетями или пользовательских потоков серверов партнеров:
- Прием из нескольких источников: Прием проверенных данных постбеков, пересылаемых с эндпоинтов разработчика, наряду с прямыми потоками отчетности рекламных сетей.
- Дедупликация по потокам: Нормализация и дедупликация записей с использованием уникального
transaction-idпо общим копиям рекламной сети и разработчика. - Нормализация для нисходящей аналитики (BI): Сопоставление укрупненных и детализированных значений конверсии с определяемыми клиентом моделями доходов и событиями воронки.
Смотрите также: SKAdNetwork ──> Модель мобильной атрибуции
Криптографическая проверка: валидация подписи Apple ECDSA P-256
Понимание криптографического стека: кривая NIST P-256 (secp256r1) с SHA-256
Каждый постбек SKAdNetwork включает поле attribution-signature. Эта криптографическая подпись генерируется Apple с использованием алгоритма цифровой подписи на эллиптических кривых (ECDSA) с кривой NIST P-256 (secp256r1) и дайджестом SHA-256.
Подпись подтверждает два фундаментальных свойства безопасности:
- Подлинность: Постбек был сгенерирован непосредственно подсистемой платформы Apple на проверенном устройстве, а не подделан сторонним клиентом или прокси.
- Целостность: Параметры, охватываемые подписью, не были изменены при передаче.
Использование опубликованного открытого ключа SKAdNetwork от Apple
Для проверки подписи сервер приема должен загрузить официальный открытый ключ Apple. Начиная с SKAdNetwork 2.1, Apple публикует выделенный открытый ключ NIST P-256 в своей документации для разработчиков:
- Инициализация ключа: Открытый ключ загружается в память в качестве стандартного объекта открытого ключа X.509/DER во время инициализации сервера.
- Проверка асимметричной подписи: Механизм проверки реконструирует точную строку сериализованного сообщения в кодировке UTF-8, вычисляет хэш SHA-256 и проверяет раскодированную из Base64 подпись
attribution-signatureпо реконструированному сообщению.
[Device / Subsystem] ──► [Dispatches Signed JSON Postback]
│
▼
[DSP / Ad Network Ingestion Endpoint]
(HTTPS POST to registered postback URL)
│
▼
[Parse JSON & Reconstruct Message String]
(Concatenate UTF-8 fields with \u2063)
│
▼
[ECDSA P-256 Public Key Signature Verification]
│
┌──────────────┴──────────────┐
▼ ▼
[Signature Valid] [Signature Invalid]
│ │
▼ ▼
[Atomic Deduplication] [Log Error & Discard]
(Check transaction-id)
│
▼
[Process Attribution]

Почему одного хэша недостаточно: проверка асимметричной подписи
Поскольку Apple подписывает пейлоуд с помощью своего закрытого ключа и не распространяет общий секретный ключ, симметричная валидация (например, HMAC-SHA256) не может быть использована. Механизмы приема должны реализовывать стандартную проверку асимметричной подписи с открытым ключом с использованием стандартных криптографических библиотек (таких как OpenSSL, модуль crypto в Node.js или cryptography в Python).
Формирование строки сообщения для проверки подписи
Строгий протокол сериализации: роль невидимого разделителя (\u2063)
Apple задает точный формат сериализации байтов UTF-8 для формирования строки сообщения для валидации подписи. Параметры должны быть конкатенированы в точной последовательности и разделены невидимым символом Unicode \u2063 (невидимый разделитель U+2063, последовательность байтов UTF-8 0xE2 0x81 0xA3):
Замена пробелов, стандартных знаков препинания или альтернативных разделителей Unicode приведет к сбою криптографической проверки.
Порядок параметров для конкретных версий в SKAN 4.0
Согласно документации Apple для разработчиков по проверке постбека валидации установки, параметры для постбеков SKAdNetwork 4.0 должны быть сериализованы в следующем точном порядке:
version(например,"4.0")ad-network-id(например,"example123.skadnetwork")source-identifier(например,"4821")app-id(например,1234567890)transaction-id(например,"6a8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d")redownload(например,"true"или"false"в виде строки в нижнем регистре)source-app-id(для рекламы из приложения в приложение) ИЛИsource-domain(для веб-рекламы в Safari), включается только при наличии в постбекеfidelity-type(например,1для рекламы с рендерингом через StoreKit или веб-рекламы, атрибутированной SKAdNetwork;0для рекламы с просмотром (view-through))did-win(например,"true"или"false"в виде строки в нижнем регистре)postback-sequence-index(например,0,1или2)
Важная спецификация SKAN 4: значения конверсии исключены из подписи
В SKAdNetwork 4.0 подпись Apple не включает conversion-value или coarse-conversion-value, даже если одно из этих полей присутствует в JSON-пейлоуде. Сериализованная строка для SKAN 4 заканчивается на postback-sequence-index. Попытка добавить значения конверсии в строку сообщения приведет к сбою проверки.
JSON-пейлоуд ниже иллюстрирует полную схему постбека SKAdNetwork 4.0. Приведенная ниже подпись является иллюстративным заполнителем и не пройдет криптографическую проверку; для модульного тестирования используйте подписанные примеры Apple из официальной документации по проверке:
{
"version": "4.0",
"ad-network-id": "example123.skadnetwork",
"source-identifier": "4821",
"app-id": 1234567890,
"transaction-id": "6a8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d",
"redownload": false,
"source-app-id": 9876543210,
"fidelity-type": 1,
"did-win": true,
"postback-sequence-index": 0,
"conversion-value": 47,
"attribution-signature": "MEQCIFz8...SAMPLE_CRYPTOGRAPHIC_SIGNATURE...=="
}
Обработка многооконных пейлоудов SKAN 4.0 и эндпоинтов разработчиков
Парсинг postback-sequence-index по последовательным окнам конверсии
В SKAdNetwork 4.0 конверсии генерируют постбеки из окон конверсии продолжительностью до 35 дней после первого запуска приложения, причем фактическая доставка происходит после случайных задержек Apple после окончания окна. Бэкенд-системы приема анализируют поле postback-sequence-index для распределения данных конверсии в правильное окно жизненного цикла:
- Индекс
0(Окно 1: дни 0–2): Содержит либо детализированное значение конверсии (0–63), либо укрупненное значение конверсии (low,medium,high), либо поле отсутствует. - Индекс
1(Окно 2: дни 3–7): Для уровней данных постбека 1–3 может раскрыватьcoarse-conversion-value(low,medium,high) при наличии; уровень 0 не имеет права на получение второго или третьего постбеков. - Индекс
2(Окно 3: дни 8–35): Для уровней данных постбека 1–3 может раскрыватьcoarse-conversion-value(low,medium,high) при наличии; уровень 0 не имеет права на получение второго или третьего постбеков.
Управление детализированными и укрупненными значениями конверсии
Декодеры приема должны учитывать вариативность пейлоудов:
- Взаимная исключаемость: Apple указывает, что постбек валидации установки может содержать либо
conversion-value, либоcoarse-conversion-value, но никогда оба одновременно. - Отсутствующие значения конверсии: Если назначенному уровню данных постбека соответствует низкий уровень (уровень 0), поля значений конверсии опускаются в JSON-пейлоуде.
Защита от атак повторного воспроизведения и поддельных пейлоудов конверсий
Роль transaction-id в качестве ключа дедупликации
Каждый постбек SKAdNetwork содержит уникальный UUID transaction-id. Документация Apple рекомендует получателям использовать этот идентификатор в качестве ключа идемпотентности для обнаружения и отбрасывания дублирующихся постбеков конверсии.
Поскольку прослушиватели постбеков являются общедоступными эндпоинтами HTTPS, злоумышленники могут попытаться провести атаки повторного воспроизведения (replay attacks), перехватив действительный постбек и отправляя его повторно для искусственного завышения показателей конверсии.
Реализация распределенного кэширования в памяти и постоянных реестров
Apple не предписывает универсальный период хранения для дедупликации. Продакшн-получатели должны поддерживать надежную запись идемпотентности для проверенных идентификаторов транзакций в соответствии со своими требованиями к сверке и защите от повторного воспроизведения; время жизни (TTL) в Redis может использоваться в качестве оптимизации горячего кэша, а не в качестве единственного авторитетного реестра дубликатов:
- Сначала криптографическая проверка: Полностью проверьте подпись ECDSA по открытому ключу Apple перед сохранением идентификатора транзакции в хранилище.
- Атомарная дедупликация: Выполните операцию атомарной записи (например, команду Redis
SET key value NX EX <seconds>), поддерживаемую уникальным ограничением постоянной реляционной базы данных или базы данных документов. - Горизонт дедупликации: Установите операционное окно хранения на уровне кэша, которое охватывает ожидаемую доставку постбеков, повторные попытки сети (Apple повторяет неудачные доставки до 9 дней) и последующую сверку.

Приведенная ниже реализация на бэкенде демонстрирует проверку подписи, валидацию схемы и атомарную дедупликацию на Python:
import base64
import json
import redis
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_der_public_key
from cryptography.exceptions import InvalidSignature
# Initialize Redis client for hot-cache transaction deduplication
redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)
# Official Apple SKAdNetwork 2.1+ Public Key (Base64 DER encoded, published by Apple)
APPLE_SKAN_PUBLIC_KEY_B64 = (
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWdp8GPcGqmhgzEFj9Z2nSpQVdday"
"aPe4FMzqM9wib1+aHaaIzoHoLN9zW4K8y4SPykE3YVK3sVqW6Af0lfx3gg=="
)
# Exact Apple-specified invisible separator: U+2063 INVISIBLE SEPARATOR (UTF-8: 0xE2 0x81 0xA3)
SEPARATOR = "\u2063"
def construct_skan4_message_bytes(payload: dict) -> bytes:
"""
Constructs the serialized UTF-8 message string for SKAN 4.0 signature verification.
Apple specification explicitly EXCLUDES conversion-value and coarse-conversion-value from the signature.
"""
parts = [
str(payload["version"]),
str(payload["ad-network-id"]),
str(payload["source-identifier"]),
str(payload["app-id"]),
str(payload["transaction-id"]),
"true" if payload["redownload"] is True else "false"
]
# Include source-app-id (app ad) OR source-domain (web ad) if present
if payload.get("source-app-id") is not None:
parts.append(str(payload["source-app-id"]))
elif payload.get("source-domain") is not None:
parts.append(str(payload["source-domain"]))
parts.append(str(payload["fidelity-type"]))
parts.append("true" if payload["did-win"] is True else "false")
parts.append(str(payload["postback-sequence-index"]))
# Join with U+2063 separator and encode to UTF-8
message_string = SEPARATOR.join(parts)
return message_string.encode('utf-8')
def verify_and_ingest_skan4_postback(postback_json_str: str) -> dict:
"""
Validates payload schema, verifies the ECDSA P-256 signature against Apple's public key,
and performs atomic transaction-id deduplication.
"""
try:
payload = json.loads(postback_json_str)
except Exception:
return {"status": "REJECTED", "reason": "INVALID_JSON_FORMAT"}
# Version Gate: Enforce SKAN 4.0 payload handling
if payload.get("version") != "4.0":
return {"status": "REJECTED", "reason": "UNSUPPORTED_SKAN_VERSION"}
# Schema Validation: Required fields for SKAN 4.0
required_fields = [
"version", "ad-network-id", "source-identifier", "app-id",
"transaction-id", "redownload", "fidelity-type", "did-win",
"postback-sequence-index", "attribution-signature"
]
for field in required_fields:
if field not in payload:
return {"status": "REJECTED", "reason": f"MISSING_REQUIRED_FIELD_{field.upper()}"}
# Strict Type Validation
if not isinstance(payload["redownload"], bool):
return {"status": "REJECTED", "reason": "INVALID_TYPE_REDOWNLOAD"}
if not isinstance(payload["did-win"], bool):
return {"status": "REJECTED", "reason": "INVALID_TYPE_DID_WIN"}
if payload["postback-sequence-index"] not in (0, 1, 2):
return {"status": "REJECTED", "reason": "INVALID_SEQUENCE_INDEX"}
if payload["fidelity-type"] not in (0, 1):
return {"status": "REJECTED", "reason": "INVALID_FIDELITY_TYPE"}
# Enforce mutual exclusivity between source-app-id and source-domain
has_source_app = payload.get("source-app-id") is not None
has_source_domain = payload.get("source-domain") is not None
if has_source_app and has_source_domain:
return {"status": "REJECTED", "reason": "CONFLICTING_SOURCE_FIELDS"}
signature_b64 = payload["attribution-signature"]
transaction_id = payload["transaction-id"]
try:
# Step 1: Reconstruct the exact UTF-8 serialized message
message_bytes = construct_skan4_message_bytes(payload)
signature_der = base64.b64decode(signature_b64, validate=True)
# Step 2: Verify ECDSA P-256 / SHA-256 signature using Apple's published public key
apple_public_key = load_der_public_key(base64.b64decode(APPLE_SKAN_PUBLIC_KEY_B64))
apple_public_key.verify(
signature_der,
message_bytes,
ec.ECDSA(hashes.SHA256())
)
except InvalidSignature:
return {"status": "REJECTED", "reason": "INVALID_CRYPTOGRAPHIC_SIGNATURE"}
except Exception as e:
return {"status": "ERROR", "reason": f"VERIFICATION_FAILED: {str(e)}"}
# Step 3: Atomic Deduplication via Redis (Hot cache layer)
# Note: In production, pair this hot cache with a persistent unique database constraint.
# 14-day TTL (1,209,600 seconds) serves as an illustrative receiver cache policy covering retries.
is_new = redis_client.set(f"skan_tx:{transaction_id}", "1", nx=True, ex=1209600)
if not is_new:
return {"status": "DUPLICATE", "reason": "TRANSACTION_ALREADY_PROCESSED"}
return {
"status": "VERIFIED",
"transaction_id": transaction_id,
"sequence_index": payload["postback-sequence-index"],
"did_win": payload["did-win"]
}
Прием постбеков в модели реального времени для назначения ставок и оптимизаторы CPA
Отвязка краевого приема (edge ingestion) от асинхронной обработки
Высокопроизводительные DSP обрабатывают большие объемы постбеков в периоды пиковых кампаний. Синхронная нисходящая обработка может приводить к задержкам.
Корпоративные архитектуры реализуют асинхронный конвейер:
- Краевой приемник (Edge Receiver): Принимает входящий запрос HTTP POST, проверяет подлинность подписи, выполняет атомарную дедупликацию по
transaction-idи немедленно возвращает HTTP200 OK. - Очередь сообщений: Публикует проверенный пейлоуд в распределенный брокер событий (например, Apache Kafka или AWS SQS).
- Воркеры назначения ставок и аналитики: Обрабатывают поток событий, сопоставляют значения конверсии с метриками доходов и обновляют целевые модели CPA для торгов в реальном времени (RTB).
Использование иерархического идентификатора источника (Source Identifier)
Первый выигрышный постбек может раскрывать две, три или четыре цифры иерархического source-identifier в зависимости от уровня данных постбека. Семантическое значение этих цифр определяется собственной таксономией идентификаторов источников рекламной сети. Системы назначения ставок должны сопоставлять полученный идентификатор источника с метаданными кампании самой сети, а не предполагать универсальное сопоставление между длиной цифр и конкретным размещением или деталями креатива.
Сравнительная матрица: прямая доставка Apple против S2S-приема через MMP
| Функциональное измерение | Прямая доставка Apple (Рекламная сеть) | Эндпоинт разработчика (NSAdvertising...) |
Конвейер приема S2S от MMP |
|---|---|---|---|
| Получатель | Зарегистрированная рекламная сеть | Разработчик рекламируемого приложения | Мобильный партнер по измерению (MMP) |
| Область атрибуции | Выигрышные постбеки для данной сети | Копия выигрышных постбеков для приложения | Сводное представление по нескольким сетям |
| Проверка подписи | Выполняется бэкендом рекламной сети | Выполняется бэкендом разработчика | Зависит от реализации (потоки партнеров) |
| Проигравшие постбеки | Получаются при соответствии критериям (did-win: false) |
Не доставляются на эндпоинт разработчика | Могут быть доступны через потоки партнеров |
| Основной вариант использования | Прямой биддер и оптимизация целевого CPA | Внутренний аудит хранилища и проверка | Панель мониторинга кросс-канальной эффективности |
Часто задаваемые вопросы (FAQ)
Какой открытый ключ используется для проверки подписи постбека Apple?
Почему действительный постбек SKAdNetwork не проходит проверку подписи?
Может ли эндпоинт разработчика рекламируемого приложения получать проигравшие постбеки SKAdNetwork?
Резюме и платформа принятия решений
Обработка постбеков SKAdNetwork в больших масштабах требует сочетания краевого приема с низкими задержками, строгой криптографической валидации и дедупликации на уровне транзакций. Поскольку постбеки Apple напрямую влияют на распределение бюджетов и алгоритмы назначения ставок, проверка подписей ECDSA и обеспечение идемпотентности transaction-id защищают конвейеры приема от поддельных или измененных постбеков, а также от обработки повторно воспроизведенных дубликатов.
Чтобы дополнить опосредованную платформой отчетность SKAdNetwork адаптацией пользователей на микроуровне и мгновенной маршрутизацией глубоких ссылок (deep links), инженерные команды развертывают архитектуры маршрутизации собственными силами параллельно с API платформ.
Чтобы узнать больше о настройке серверных постбеков атрибуции и конвейеров диплинков, ознакомьтесь с документацией OpoInstall.
Связанные материалы
-
Концепции: S2S-постбеки, Криптографическая проверка, ECDSA P-256, Защита от атак повторного воспроизведения, Дедупликация транзакций
-
Технологии: Apple SKAdNetwork, Apple AdAttributionKit, Кэш Redis в памяти, Мобильный SDK OpoInstall
-
Стандарты: IETF RFC 8259 (обмен данными JSON), RFC 5480 (криптография на эллиптических кривых)
-
API: StoreKit SKAdNetwork API, спецификация доставки S2S-постбеков Apple, S2S API OpoInstall
Официальная документация
Share this article



