Как добавить обязательный запрос на IDFA через App Tracking Transparency

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

С весны этого года каждый iOS-разработчик должен запрашивать разрешение пользователя на использование рекламного идентификатора IDFA. В предыдущей статье мы сделали подробный обзор изменений в App Store и их влияния на мир iOS-разработки.

А сегодня — практический материал. Расскажем, как с помощью нового фреймворка App Tracking Transparency добавить в своё приложение обязательный запрос на использование персональных данных, как потом эти данные передавать рекламным сетям и что делать, если пользователь решил не делиться своей активностью. 

Требования Apple

Подготавливать приложение мы начали с изучения гайдлайнов Apple. Там вводится понятие трекинга, которое подразумевает:

  • Связывание данных пользователей или устройств, собираемых вашим приложением, с данными пользователей или устройств, собираемых другими приложениями или веб-сайтами, для таргетирования рекламы.

  • Обмен данными пользователей или устройств с брокерами данных (компаниями, которые собирают и продают персональные данные).

В нашем приложении iFunny персональные данные пользователя используются двумя брокерами данных, которые попадают под определение трекинга:

  1. Рекламными сетями. Для этого нужен доступ к IDFA, который используется для таргетирования. Кроме того, мы можем передавать в рекламные SDK пол и возраст пользователя.

  2. Facebook. Пользователь может авторизоваться через Facebook. А так как по правилам соцсети пользователь должен быть старше 18 лет, то мы передаем его возраст.

Эти два пункта обязывают использовать фреймворк App Tracking Transparency, иначе можно даже не пройти ревью в App Store. Чтобы этого не произошло, нужно покопаться внутри приложения и добавить соответствующую поддержку.

Запрос IDFA

Теперь если приложение попытается получить доступ к IDFA без явного запроса на разрешение у пользователя, то будут такие проблемы:

  1. ASIdentifierManager.shared().advertisingIdentifier.uuidString вернет пустой IDFA, состоящий из нулей: 00000000-0000-0000-0000-000000000000.

  2. Вы не пройдете ревью в App Store. Ревьюеры Apple теперь отклоняют все приложения, в которых нет IDFA.

IDFA крайне важен для таргетирования рекламы, поэтому каждому разработчику выгодно, чтобы больше пользователей нажимали кнопку «Разрешить». Для повышения конверсии можно экспериментировать и проводить A/B-тесты с разными показами запроса на IDFA.

Например, в iFunny были и стандартный вопрос, и котик, и сопроводительный текст, объясняющий, почему это полезно для пользователя:

Тексты, расположение view, картинку можно менять с помощью параметров A/B-теста. Был ещё информационный экран, после которого показывался запрос IDFA. Это не запрещено правилами — главное, чтобы всплывающий алерт в принципе был. 

Эксперименты проводили несколько раз. В нашем случае самое большое количество согласий дал стандартный первый вариант без каких-то вспомогательных диалогов. Возможно, пользователи просто привыкли нажимать «Разрешить» в аналогичных запросах на уведомления и использование геопозиции.

Добавить запрос IDFA в приложение довольно просто, но нужно учитывать пару важных условий:

  • Нельзя ограничивать функциональность приложения, если пользователь не согласился делиться своим IDFA.

  • Нужно уважать выбор пользователей — нельзя заставлять их дать разрешение формулировкой, в которой вы будете угрожать или манипулировать (например, написав, что приложение будет хуже работать).

Сам алерт на IDFA вызывается таким куском кода, добавленным в plist:

 @available(iOS 14, *)
    private func requestTrackingAuthorization(completion: ((Bool) -> Void)?) {
        ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
            DispatchQueue.main.async {
                // Проверяем status
            }
        })
    }

Текст запроса можно изменить там же строками:

<key>NSUserTrackingUsageDescription</key>
<string>This will only be used to serve only relevant ads</string>

Передача данных рекламным сетям, если пользователь предоставил IDFA 

Как уже разобрались выше, трекинг — это передача пользовательских данных сторонним рекламным SDK. В iFunny мы передаём пол, возраст и локацию пользователя (разумеется, если он дал на это разрешение) всем рекламным сетям, которые поддерживают передачу таких данных.

У каждого SDK свой API для передачи персональных данных, но общая логика примерно одинаковая у всех: показываем пользователю запрос > проверяем согласие > отправляем данные рекламным сетям.

Например, чтобы передавать информацию рекламной сети Prebid, нужно добавить код:

import PrebidMobile
import AppTrackingTransparency

private func setAgeAndGender(yearOfBirth: Int,
                             gender: Gender) {

    // Проверяем, что пользователь дал согласие
    let canSendData = ATTrackingManager.trackingAuthorizationStatus == .authorized
    guard canSendData else {
    // Если не дал согласие, то очищаем закешированные данные
        Targeting.shared.gender = .unknown
        Targeting.shared.clearYearOfBirth()
        return
    }
    
    // Устанавливаем пол и возраст
    Targeting.shared.gender = gender
    try? Targeting.shared.setYearOfBirth(yob: yearOfBirth)
}

Для рекламной сети Appodeal:

import BidMachine
import AppTrackingTransparency

private func setAgeAndGender(yearOfBirth: Int,
                            gender: String,
                            targeting: BDMTargeting) {
   // Проверяем, что пользователь дал согласие
   let canSendData = ATTrackingManager.trackingAuthorizationStatus == .authorized
   guard canSendData else {
       return
   }
  
   // Устанавливаем пол и возраст
   targeting.yearOfBirth = NSNumber(integerLiteral: yearOfBirth)
   targeting.gender = gender
}

А для рекламной сети MyTarget:

import MyTargetSDK
import AppTrackingTransparency

private func setAgeAndGender(age: Int,
                            gender: MTRGGender,
                            parameters: MTRGCustomParams) {
   // Проверяем, что пользователь дал согласие
   let canSendData = ATTrackingManager.trackingAuthorizationStatus == .authorized
   guard canSendData else {
       return
   }
  
   // Устанавливаем пол и возраст
   parameters.age = NSNumber(integerLiteral: age)
   parameters.gender = gender;
}

Передача данных рекламным сетям, если пользователь не предоставил IDFA

Для этого есть альтернативный фреймворк, работающий с рекламными сетями — SKAdNetwork. Он позволяет получить атрибуцию рекламных кампаний на iOS, даже если пользователь не предоставил доступ к IDFA. 

Для его использования рекламные сети должны регистрироваться в Apple, а разработчики добавлять специальные идентификаторы в свои приложения, чтобы рекламные сети могли использовать этот способ.

Нужно в plist добавить ключ SKAdNetworkItems, значениями которого будет массив с SKAdNetwork-идентификаторами:

<key>SKAdNetworkItems</key>
<array>
   <dict>
       <key>SKAdNetworkIdentifier</key>
       <string>csnmt7uwn9.skadnetwork</string>
   </dict>
   <dict>
       <key>SKAdNetworkIdentifier</key>
       <string>uw7m6nh5d.skadnetwork</string>
   </dict>
   ...
<array>

Facebook Limited Login

Чтобы соответствовать новой политике приватности, Facebook сделал специальную реализация своего логина. По сути, теперь у соцсети есть две кнопки: 

  1. Классический логин (Classic Login Mode) остался без изменений. Там по-прежнему передаются все данные без ограничений.

  2. Ограниченный логин (Limited Login) работает на базе стандарта OpenID Connect и позволяет пользователям создавать новые аккаунты или использовать существующие, при этом делясь ограниченным набором данных: имя, фото профиля и (опционально) email

Разработчики могут разделить пользователей на две группы и для каждой группы использовать определенную реализацию логина. Например, для тех пользователей, которые дали согласие на использование их данных для персонализации рекламы, можно использовать Classic Login Mode, а для тех, кто отказался от этого – Limited Login Mode. 

Мы поддерживаем оба, и пользователь в любой момент может переключиться на нужный.

private func loginWithFacebook() {
        // Проверяем, что пользователь дал согласие
        let useLimitedLogin = ATTrackingManager.trackingAuthorizationStatus != .authorized
        // Выбираем подходящий способ
        let loginTracking: LoginTracking = useLimitedLogin ? .limited : .enabled
        // Устанавливаем разрешения
        var permissions: Set<Permission>
        if useLimitedLogin {
            permissions = [.email, .publicProfile]
        } else {
            var permissions = Set<Permission>([.email, .publicProfile])
            permissions.insert(.custom("user_gender"))
            permissions.insert(.custom("user_age_range"))
        }
        
        guard let loginConfiguration = LoginConfiguration(
            permissions: permissions,
            tracking: loginTracking,
            nonce: UUID().uuidString
        ) else {
            return
        }
        
        let loginManager = LoginManager()
        // Авторизовываемся
        loginManager.logIn(configuration: loginConfiguration, ...)
    }

Заключение

С обновлением iOS 14.5 пришлось повозиться под капотом приложения. Экспериментировали, боролись с ревьюерами Apple, добавляли изменения в рекламные SDK и, в целом, получили большой опыт по подготовке приложения.

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

Источник: https://habr.com/ru/company/funcorp/blog/588008/


Интересные статьи

Интересные статьи

Цель данной статьи - рассказать о GraphQL и Hasura человеку, который вообще ничего не слышал об этих инструментах. И, например, его карьерный путь сложился так, что ему необходимо иметь общее представ...
Этот пост предназначен в первую очередь для сотрудников телекома, админов и новичков в разработке, впервые столкнувшихся с необходимостью отправить snmp-запросы к какому-нибудь коммутатору и разобрат...
Всем привет. Если вы когда-либо работали с универсальными списками в Битрикс24, то, наверное, в курсе, что страница детального просмотра элемента полностью идентична странице редак...
Если во время удаленной работы вам все равно нужно звонить и принимать звонки, без виртуального номера не обойтись. Но что делать, если нет возможности идти в офис оператора, или желания отправля...
Обобщенные асинхронные типы возвращаемых значений — это новая возможность появившаяся в C# 7, которая позволяет использовать не только Task в качестве возвращаемого типа асинхронных (async/awai...