AppsFlyer

Adapty обменивается данными с AppsFlyer в обоих направлениях. AppsFlyer сообщает Adapty, из какой кампании пришёл пользователь. Adapty сообщает AppsFlyer, сколько этот пользователь заплатил — покупки, продления, пробные периоды и возвраты с данными о выручке и продуктах.

  • Просматривайте полный жизненный цикл подписки, а не только первую покупку. Продления и конвертации триалов — это события стора, для которых нет сессии приложения, чтобы клиентский SDK AppsFlyer мог их зафиксировать. Adapty получает события подписок на стороне сервера и пересылает их в AppsFlyer, поэтому данные по кампаниям обновляются ещё долго после первоначальной установки. Возвраты средств передаются тем же путём, и AppsFlyer вычитает их из доходов кампании.
  • Оптимизируйте рекламные кампании с помощью данных о событиях подписок. AppsFlyer передаёт события встроенных покупок из Adapty в ваши рекламные сети в виде постбэков. Сервисы, управляющие вашим рекламным бюджетом, могут оптимизироваться на основе реальных платежей пользователей.
  • Фильтруйте аналитику Adapty по кампании. Adapty сохраняет атрибуцию AppsFlyer в каждом профиле — вплоть до группы объявлений и креатива — и графики подписок можно фильтровать по этим данным.
  • Показывайте разные пейволы для разных кампаний. Сегменты Adapty фильтруются по тем же полям атрибуции — кампании, группе объявлений и креативу. Используйте сегмент как аудиторию, чтобы подобрать пейвол под рекламу, которая привела пользователя.
Tip

В вашем аккаунте Adapty уже есть два инструмента для платных кампаний. Adapty Ads Manager управляет кампаниями Apple Ads; Adapty Attribution охватывает Meta Ads и TikTok. Оба показывают ROAS и LTV прямо из данных о покупках Adapty, и оба бесплатны для старта — подробнее в разделе цен.

Данные атрибуции AppsFlyer в профиле пользователя Adapty

Как работает интеграция

Adapty получает данные атрибуции от AppsFlyer и отправляет обратно события подписок. Оба процесса зависят от одного значения: AppsFlyer ID — строки, которую AppsFlyer генерирует при первом запуске вашего приложения.

  1. Когда пользователь устанавливает ваше приложение, SDK AppsFlyer присваивает ему уникальный ID.
  2. Ваше приложение передаёт этот ID в Adapty, которая сохраняет его в профиле пользователя как appsflyer_id.
  3. Ваше приложение также передаёт данные атрибуции AppsFlyer в Adapty, которая сохраняет их в том же профиле.
  4. Позже, когда пользователь совершает событие подписки — например, начинает пробный период или покупает продукт, — серверы Adapty отправляют это событие в S2S API AppsFlyer с тем же appsflyer_id.
  5. AppsFlyer сопоставляет ID с установкой, которую уже атрибутировал, и покупка наследует кампанию и источник медиа этой установки.

Инструкции по настройке

Перед началом работы:

  • Убедитесь, что ваш тариф AppsFlyer поддерживает S2S in-app события. Пакет начального уровня Zero этого не поддерживает: его API отклоняет каждое событие, которое отправляет Adapty, с ошибкой 403 Forbidden.
  • Добавьте AppsFlyer SDK в приложение. Идентификатор AppsFlyer, от которого зависит интеграция, появляется только после инициализации этого SDK. Одна лишь серверная интеграция не создаст этот идентификатор.
  • Отключите все остальные интеграции атрибуции. Adapty принимает только один источник атрибуции на профиль и не может перезаписать уже существующее значение. На iOS ненативная атрибуция Apple Ads всегда имеет приоритет — см. Выбор единственного источника атрибуции.

Создание S2S-токена в AppsFlyer

Adapty проходит аутентификацию в S2S API AppsFlyer с помощью токена, который вы создаёте. Открыть страницу Tokens могут только администраторы AppsFlyer, поэтому попросите администратора создать токен, если у вашей учётной записи нет прав администратора. Если токен уже есть, перейдите к разделу Настройка Adapty.

  1. Войдите в AppsFlyer.

  2. Нажмите на имя вашей учётной записи в правом верхнем углу и откройте Security center.

    The Security center entry under the account menu in AppsFlyer
  3. На странице Manage your account security найдите карточку AppsFlyer API and S2S tokens и нажмите Manage your AppsFlyer tokens. Откроется страница Tokens.

  4. Нажмите New token.

    The New token dialog in AppsFlyer with the Name field and the Choose type list set to S2S
  5. Введите Name для токена. Это название только для вашего удобства, его можно изменить позже.

  6. Выберите тип токена S2S. Любой другой тип нарушит интеграцию.

  7. Нажмите Create new token.

Note

AppsFlyer допускает не более двух токенов каждого типа. Если у вас уже есть два S2S-токена, используйте один из них повторно.

  1. Найдите новый токен в списке. AppsFlyer скрывает значение, поэтому нажмите иконку копирования в столбце Token, чтобы получить его.

    The Tokens page in AppsFlyer showing an S2S token with its copy icon, type, and status

Настройка Adapty

  1. Откройте Integrations > AppsFlyer в дашборде Adapty.
  2. Включите переключатель AppsFlyer.
  3. Если вы уже подключили приложение к App Store, поле iOS App ID автоматически заполнится числовым Apple ID вашего приложения. Если оно пустое, сначала подключите аккаунт App Store. Для Android аналогичное поле не требуется.
  4. Вставьте S2S-токен в поле Production раздела S2S key for iOS, S2S key for Android или в оба.
  5. Заполните поля Sandbox, чтобы тестовые покупки не попадали в производственную статистику — см. Разделение данных песочницы и продакшена.
The AppsFlyer integration page in Adapty with the iOS app ID and the Production and Sandbox S2S key fields
  1. В разделе How the revenue data should be send выберите, какое значение выручки Adapty будет отправлять как af_revenue. Три варианта соответствуют представлениям выручки в Adapty Analytics, поэтому ваш выбор также определяет, с каким именно представлением должны совпадать данные AppsFlyer.
ВариантЧто отправляет Adapty
Gross revenueПолная сумма, которую заплатил покупатель, до вычета комиссии и налогов. По умолчанию.
Proceeds after store commissionСумма за вычетом комиссии стора, но с учётом налогов.
Proceeds after store commission and taxesСумма за вычетом и того, и другого.
  1. Настройте оставшиеся параметры:
ПереключательКогда включёнПо умолчанию
Report user’s currencyAdapty сообщает о каждой продаже в валюте покупателя, а не в USD.Выкл
Send trial priceТриалы не несут дохода в противном случае. Включите, чтобы назначить каждому пробному периоду условную цену; появится поле Trial price percentage — укажите, какую долю от цены подписки должен сообщать триал. При 60% подписка за $10 отправит $6.Выкл
Exclude historical eventsAdapty пропускает события, произошедшие до того, как пользователь установил сборку с SDK Adapty.Вкл
Delay events with a future datetimeApple сообщает о продлениях и конвертациях триалов заранее, поэтому эти события имеют будущую дату. AppsFlyer обычно заменяет её датой поступления события. Включите, чтобы удерживать каждое событие до наступления его даты — см. Продления попадают не в тот день.Выкл
  1. Переименуйте или отключите отдельные события в разделе Events names — см. Названия событий.

    The Events names section of the Adapty AppsFlyer integration page
  2. Нажмите Save.

Отправка данных из песочницы отдельно от производственных

Чтобы тестовые покупки не попадали в реальную статистику, отправляйте их в отдельное приложение AppsFlyer. Зарегистрируйте второе приложение для dev-сборок и вставьте его токен в поле Sandbox соответствующего раздела платформы.

Adapty распределяет транзакции по окружению: реальные покупки — в приложение с токеном из Production, тестовые — в приложение из Sandbox. Если вы хотите видеть всё в одном приложении, просто вставьте одинаковый токен в оба поля.

Покупки в ходе ревью App Store и через TestFlight являются sandbox-транзакциями, даже если они выполняются в production-сборке. Adapty отправляет такие покупки с ключом Sandbox.

Note

Транзакции из песочницы не отображаются в аналитических графиках. Они по-прежнему видны на страницах отдельных профилей и в ленте событий.

Настройте код вашего приложения

  1. Зарегистрируйте callback конверсии в AppsFlyer SDK. На iOS реализуйте протокол AppsFlyerLibDelegate; на Android — интерфейс AppsFlyerConversionListener; на Unity — интерфейс IAppsFlyerConversionData. На React Native и Flutter вместо этого передайте обработчик в метод onInstallConversionData.
  2. Дождитесь, пока AppsFlyer вызовет этот callback. AppsFlyer атрибутирует каждую установку на своих серверах, поэтому результат поступает в приложение асинхронно, а не в момент запуска. SDK снова вызывает callback при каждой последующей сессии.
  3. Внутри callback прочитайте AppsFlyer ID пользователя с помощью getAppsFlyerUID и передайте его в Adapty через setIntegrationIdentifier(). События Adapty попадают к нужному пользователю AppsFlyer только при наличии этого значения.
  4. Внутри того же callback передайте данные атрибуции AppsFlyer в Adapty через updateAttribution(). Это сообщает Adapty, какая кампания привела к установке. В iOS и Android SDK 4.1 и выше метод называется updateExternalAttribution().
  5. Используйте await Adapty.identify() вместо того, чтобы запускать его параллельно с шагами 3 и 4. Adapty создаёт анонимный профиль при активации, а затем переключается на идентифицированный профиль после завершения identify(). Значение appsflyer_id, установленное в момент этого переключения, не всегда сохраняется.

Полную последовательность вызовов см. в разделах для iOS, Android, React Native, Flutter, Unity, Capacitor и Kotlin Multiplatform.

Note

Сторонние SDK генерируют пользовательские ID асинхронно. ID может быть ещё не готов в момент вызова Adapty.activate(). Если ваш Customer User ID приходит из одного из таких SDK, вызывайте Adapty.activate() без него. Как только ID будет получен, вызовите setIntegrationIdentifier(), а затем identify() с CUID.

Проверьте интеграцию

  1. Совершите покупку в песочнице и откройте Event Feed вашего приложения. Там отображается каждая попытка доставки. Чтобы увидеть ответ AppsFlyer на неудачную попытку, наведите курсор на нужную строку.
  2. В AppsFlyer откройте Settings > SDK Integration Tests > Live Events и выберите ваше тестовое устройство. В Live Events S2S-события появляются сразу по мере поступления — задолго до того, как они попадут на дашборд Activity в AppsFlyer.
  3. Откройте дашборд Activity вашего приложения и проверьте событие, его выручку и источник трафика. Подождите около часа — S2S-события попадают на этот дашборд не сразу.
Note

События Adapty никогда не отображаются в отладочном логе AppsFlyer SDK вашего приложения. Adapty отправляет их со своих серверов, поэтому они не проходят через ваше приложение. Пустой локальный лог ничего не говорит о состоянии интеграции.

Структура событий AppsFlyer

Adapty отправляет один POST-запрос на каждое событие по адресу https://api3.appsflyer.com/inappevent/{app_id}, передавая S2S-токен в заголовке authentication. API 2 использует https://api2.appsflyer.com/inappevent/{app_id}.

{
  "appsflyer_id": "1699887556000-6192770",
  "eventName": "af_subscribe",
  "eventTime": "2026-03-01 12:00:00",
  "eventValue": "{\"af_content_id\":\"yearly.premium.6999\",\"af_order_id\":\"GPA.3383-4699-1373-07113\",\"store_country\":\"US\",\"profile_country\":\"US\",\"af_content_type\":\"in_app\",\"af_revenue\":\"9.9900\",\"af_currency\":\"USD\",\"af_quantity\":\"1\"}",
  "os": "17.0.1",
  "bundleIdentifier": "com.example.app",
  "customer_user_id": "user_12345",
  "eventCurrency": "USD",
  "ip": "192.168.100.1",
  "advertising_id": "00000000-0000-0000-0000-000000000000",
  "idfa": "00000000-0000-0000-0000-000000000000",
  "idfv": "00000000-0000-0000-0000-000000000000",
  "att": "3"
}
ПараметрТипОписание
appsflyer_idStringAppsFlyer ID, который ваше приложение передало в setIntegrationIdentifier. AppsFlyer сопоставляет событие с установкой по этому значению.
eventNameStringНазвание из раздела Events names — см. Названия событий.
eventTimeStringВремя возникновения события (UTC, YYYY-MM-DD HH:MM:SS). Adapty заменяет его текущим временем для событий старше 26 часов — см. Старые события приходят с сегодняшней датой.
eventValueStringJSON-строка с полями из таблицы ниже.
osStringВерсия ОС устройства пользователя.
bundleIdentifierStringBundle ID приложения на iOS или имя пакета на Android.
customer_user_idStringCustomer User ID пользователя.
eventCurrencyStringКод валюты по ISO 4217, например USD.
ipStringIP-адрес пользователя.
advertising_idStringТолько Android. Google Advertising ID.
idfaStringТолько iOS. ID для рекламодателей (ID for Advertisers).
idfvStringТолько iOS. ID для вендоров (ID for Vendors).
attStringТолько iOS. Статус App Tracking Transparency, от 0 до 3. Adapty отправляет 0, если значение отсутствует.

eventValue содержит саму покупку. Последние четыре параметра появляются только в событиях, несущих доход:

ПараметрТипОписание
af_content_idStringID продукта в сторе.
af_order_idStringОригинальный ID транзакции.
store_countryStringСтрана аккаунта пользователя в сторе.
profile_countryStringСтрана, определённая Adapty по IP-адресу пользователя.
af_content_typeStringВсегда in_app.
af_revenueStringСумма дохода с точностью до 4 знаков после запятой. Отрицательное значение при возвратах.
af_currencyStringВалюта af_revenue.
af_quantityStringВсегда 1.

Названия событий

По умолчанию Adapty сопоставляет события с доходами со стандартными названиями событий AppsFlyer, а не отправляет собственные названия как кастомные события. Это важно при пересылке событий в рекламные сети: сеть реагирует на стандартные названия, которые уже распознаёт, — и вам не нужно вручную настраивать маппинг для каждого из них.

Adapty eventDefault AppsFlyer name
Subscription startedaf_subscribe
Subscription renewedaf_subscribe
Trial convertedaf_subscribe
Trial startedaf_start_trial
Non-subscription purchaseaf_purchase

Все остальные события Adapty сохраняют свои имена, например subscription_refunded. В разделе Events names на странице интеграции AppsFlyer вы можете переименовать любое событие или отключить те, которые вам не нужны. Полный список событий, которые Adapty может отправлять, см. в разделе События.

Ограничения

  • Профиль без appsflyer_id не генерирует события. AppsFlyer сопоставляет событие с установкой, которая создала ID, и считывает кампанию из этой установки. Без него Adapty ничего не отправляет, а Event Feed помечает такие профили — см. События не доходят до AppsFlyer.
  • Нет ретроспективного заполнения. Adapty начинает передавать события с момента включения интеграции. Прошлые покупки в AppsFlyer не попадают.
  • Данные об устройстве в raw data AppsFlyer остаются пустыми. S2S-событие содержит только то, что передано в запросе. Для Device Model, Device Category, Language, Operator, WIFI, App Version и App Name нет S2S-параметров, поэтому они не могут быть заполнены через этот канал.

Устранение неполадок

События не доходят до AppsFlyer

Сначала откройте Event Feed. Неудачная доставка показывает ошибку, которую вернул AppsFlyer. Большинство случаев объясняется следующими причинами:

  • В профиле нет appsflyer_id. Убедитесь, что ваше приложение вызывает getAppsFlyerUID и передаёт результат в setIntegrationIdentifier на каждой платформе — см. Настройка кода приложения.
  • Отсутствует App ID для этой платформы. AppsFlyer идентифицирует каждое приложение по ID, поэтому без него Adapty не отправит ни одного события. Для iOS-событий нужен iOS App ID на странице интеграции; для Android-событий — имя пакета из App settings > Android SDK — см. Настройка Adapty.
  • Покупка является транзакцией в песочнице, а Sandbox-ключ не заполнен. См. Исключение данных песочницы из продакшна.
  • Событие отключено в разделе Events names.

Успешная доставка не гарантирует, что AppsFlyer сохранит событие. AppsFlyer возвращает 200 OK на любой корректно сформированный запрос, после чего отбрасывает события, чей appsflyer_id не совпадает ни с одной реальной установкой.

Покупки отображаются как органические

Каждый appsflyer_id идентифицирует одну установку, и каждое событие с этим ID наследует атрибуцию установки — кампанию, которая её привела, или ничего, если установка была органической. AppsFlyer требуется 20–30 секунд или больше, чтобы атрибутировать новую установку. Событие, пришедшее раньше этого момента, не имеет атрибуции для наследования, поэтому AppsFlyer помечает его как неатрибутированную органику.

Ожидайте, что покупки при первом запуске будут отображаться как органические — триалы, начатые в течение нескольких секунд после запуска приложения. Чтобы избежать этого, достаточно отложить показ пейвола, пока AppsFlyer не завершит обработку установки.

Если все события выглядят органическими, а не только отдельные покупки при первом запуске, причина в атрибуции, а не в тайминге: другой источник уже зафиксировал профиль первым. См. Выбор единственного источника атрибуции.

Старые события приходят с сегодняшней датой

События могут поступать в Adapty с задержкой по двум причинам:

  • Когда App Store Server Notifications отображаются как Delayed в App Store Connect, Apple ставит уведомления в очередь. В результате событие обновления подписки поступает в Adapty значительно позже фактического момента — см. App Store Server Notifications show “Delayed”.
  • События с прошедшими датами проходят всегда, когда опция Exclude historical events отключена.

AppsFlyer не принимает слишком старые временны́е метки. Чтобы события обрабатывались корректно, Adapty заменяет eventTime на текущее время для любого события старше 26 часов. Отключить эту перезапись нельзя.

Продления попадают не на тот день

Apple уведомляет Adapty о продлениях и конвертациях триалов заранее, и Adapty немедленно передаёт их с исходным будущим eventTime. AppsFlyer сохраняет будущую временну́ю метку только если она приходится на день получения события — продление, датированное завтрашним числом, получит временну́ю метку сегодняшнего дня прихода.

Включите Delay events with a future datetime в настройках интеграции. Adapty будет удерживать каждое событие до наступления его времени, и AppsFlyer зафиксирует дату, объявленную Apple. См. Временны́е метки событий с датой в будущем.

Доходы в AppsFlyer не совпадают с Adapty Analytics

Adapty и AppsFlyer по-разному считают одни и те же покупки. Именно эти различия объясняют почти все расхождения.

  • Обзорный дашборд AppsFlyer группирует доход по дате установки, а графики Adapty — по дате события. В AppsFlyer июльское продление подписки, установленной в январе, засчитывается в январь. Сравнивайте этот дашборд с когортным анализом Adapty, который также группирует доход по месяцу установки. Сырые отчёты AppsFlyer группируются по дате события — их стоит сравнивать с графиками Adapty.
  • Покупки из профилей без appsflyer_id никогда не попадают в AppsFlyer. Они остаются в Adapty Analytics. См. События не доходят до AppsFlyer.
  • AppsFlyer показывает только те данные о доходе, которые вы выбрали в Adapty. Настройка How the revenue data should be send определяет, что именно Adapty отправляет: валовой доход, выручку или чистый доход. Если сравнивать это с другим представлением Adapty Analytics, разница будет равна комиссии, налогу или обоим сразу.
  • Adapty использует часовой пояс отчётности вашего приложения, AppsFlyer получает UTC. Интеграции всегда получают временны́е метки в UTC, независимо от настроек в App Settings. Покупка в 23:30 UTC 1 июля отобразится как 2 июля в Adapty, если ваш часовой пояс отчётности — +02:00.
  • В AppsFlyer отсутствуют исторические события. Причин может быть две. Если включён параметр Exclude historical events, история AppsFlyer пользователя начинается с его первого запуска сборки с Adapty. Кроме того, Adapty никогда не восполняет события, обработанные до включения интеграции.
  • Покупки в песочнице попадают в приложение AppsFlyer, указанное в ключе Sandbox. Если это продакшн-приложение, тестовые покупки завышают его доход. См. Как не допустить попадания данных песочницы в продакшн.
  • События, отключённые в интеграции, никогда не попадают в AppsFlyer. Adapty Analytics по-прежнему их учитывает. Проверьте раздел Events names — отключение subscription_renewed убирает большую часть дохода для любого работающего приложения.

Failed to authenticate в ленте событий

AppsFlyer отклоняет учётные данные, если они не соответствуют версии API. API 2 ожидает Dev key, API 3 — токен S2S. Если сменить версию, не заменив ключ, эта ошибка будет появляться на каждом событии.

Создайте новый токен в AppsFlyer Security Center и вставьте его в поля S2S key, либо следуйте инструкции Switch from AppsFlyer S2S API 2 to 3.

access_level_updated отображается как ошибка в ленте событий

access_level_updated — это событие только для вебхуков. Adapty не отправляет его в эту интеграцию. Однако Adapty фиксирует результат для каждой активной интеграции, и неподдерживаемое событие отображается как ошибка.