Обработка событий онбординга в iOS SDK

Начиная с SDK v4 (бета), вы можете создавать флоу как более мощную альтернативу онбордингам. В отличие от онбордингов, которые работают внутри WebView, флоу рендерятся нативно на устройстве — это обеспечивает более плавные анимации, единый iOS look and feel, быструю загрузку и отсутствие зависимости от WebView. Смотрите Получение флоу и пейволов и Отображение флоу и пейволов, чтобы начать.

Прежде чем начать, убедитесь, что:

  1. Вы установили Adapty iOS SDK версии 3.8.0 или новее.
  2. Вы создали онбординг.
  3. Вы добавили онбординг в плейсмент.

Онбординги, настроенные с помощью конструктора, генерируют события, на которые ваше приложение может реагировать. Ниже описано, как это делать.

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

Пользовательские действия

В конструкторе можно добавить пользовательское действие к кнопке и назначить ему идентификатор.

ios-events-1.webp

Затем вы можете использовать этот ID в своём коде и обрабатывать его как пользовательское действие. Например, если пользователь нажимает на кастомную кнопку — скажем, Login или Allow notifications — метод делегата onboardingController будет вызван с кейсом .custom(id:), где параметр actionId соответствует Action ID из билдера. Вы можете задавать собственные ID, например “allowNotifications”.

func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) {
    if action.actionId == "allowNotifications" {
        // Request notification permissions
    }
}
    
func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) {
    // Handle errors
}
Пример события (нажмите, чтобы развернуть)
{
  "actionId": "allowNotifications",
  "meta": {
    "onboardingId": "onboarding_123",
    "screenClientId": "profile_screen",
    "screenIndex": 0,
    "screensTotal": 3
  }
}

Закрытие онбординга

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

ios-events-2.webp

Обратите внимание: вам нужно самостоятельно обработать закрытие онбординга пользователем — например, скрыть экран онбординга.

Например:

func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) {
    controller.dismiss(animated: true)
}
Пример события (нажмите, чтобы развернуть)
{
  "action_id": "close_button",
  "meta": {
    "onboarding_id": "onboarding_123",
    "screen_cid": "final_screen",
    "screen_index": 3,
    "total_screens": 4
  }
}

Открытие пейвола

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

Самый удобный подход при работе с пейволами в онбордингах — сделать action ID равным placement ID пейвола. Тогда после получения AdaptyOnboardingsOpenPaywallAction можно сразу использовать placement ID, чтобы получить и открыть нужный пейвол. Обратите внимание, что одновременно на экране может отображаться только одно представление (пейвол или онбординг). Если вы показываете пейвол поверх онбординга, программно управлять онбордингом в фоне не получится. Попытка закрыть онбординг закроет пейвол, оставив онбординг видимым. Чтобы избежать этого, всегда закрывайте представление онбординга перед показом пейвола.

func onboardingController(_ controller: AdaptyOnboardingController, onPaywallAction action: AdaptyOnboardingsOpenPaywallAction) {
    // Закрываем онбординг перед показом флоу
    controller.dismiss(animated: true) {
        Task {
            do {
                // Получаем флоу по идентификатору плейсмента из action
                let flow = try await Adapty.getFlow(placementId: action.actionId)

                // Получаем конфигурацию флоу
                let flowConfiguration = try await AdaptyUI.getFlowConfiguration(
                    forFlow: flow
                )

                // Создаём и показываем контроллер флоу
                let flowController = try AdaptyUI.flowController(
                    with: flowConfiguration,
                    delegate: self
                )

                // Показываем флоу из корневого view controller
                if let rootVC = UIApplication.shared.windows.first?.rootViewController {
                    rootVC.present(flowController, animated: true)
                }
            } catch {
                // Обрабатываем ошибки, возникшие при загрузке флоу
                print("Failed to present flow: \(error)")
            }
        }
    }
}
Пример события (нажмите, чтобы развернуть)
{
    "action_id": "premium_offer_1",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "pricing_screen",
        "screen_index": 2,
        "total_screens": 4
    }
}

Завершение загрузки онбординга

Когда онбординг завершает загрузку, вызывается следующий метод:

func onboardingController(_ controller: AdaptyOnboardingController, didFinishLoading action: OnboardingsDidFinishLoadingAction) {
    // Handle loading completion
}
Пример события (нажмите, чтобы развернуть)
{
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "welcome_screen",
        "screen_index": 0,
        "total_screens": 4
    }
}

Отслеживание навигации

Метод onAnalyticsEvent вызывается при возникновении различных аналитических событий в ходе онбординга. Объект event может быть одного из следующих типов:

ТипОписание
onboardingStartedКогда онбординг загружен
screenPresentedКогда отображается любой экран
screenCompletedКогда экран завершён. Включает необязательный elementId (идентификатор завершённого элемента) и необязательный reply (ответ пользователя). Срабатывает, когда пользователь выполняет любое действие для выхода с экрана.
secondScreenPresentedКогда отображается второй экран
userEmailCollectedСрабатывает, когда email пользователя собирается через поле ввода
onboardingCompletedСрабатывает, когда пользователь достигает экрана с ID final. Если вам нужно это событие, назначьте ID final последнему экрану.
unknownДля любого нераспознанного типа события. Включает name (название неизвестного события) и meta (дополнительные метаданные)
Каждое событие содержит мета-информацию в поле meta:
ПолеОписание
onboardingIdУникальный идентификатор флоу онбординга
screenClientIdИдентификатор текущего экрана
screenIndexПозиция текущего экрана во флоу
screensTotalОбщее количество экранов во флоу

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

func onboardingController(_ controller: AdaptyOnboardingController, onAnalyticsEvent event: AdaptyOnboardingsAnalyticsEvent) {
    switch event {
    case .onboardingStarted(let meta):
        // Отслеживаем начало онбординга
        trackEvent("onboarding_started", meta: meta)
    case .screenPresented(let meta):
        // Отслеживаем отображение экрана
        trackEvent("screen_presented", meta: meta)
    case .screenCompleted(let meta, let elementId, let reply):
        // Отслеживаем завершение экрана с ответом пользователя
        trackEvent("screen_completed", meta: meta, elementId: elementId, reply: reply)
    case .onboardingCompleted(let meta):
        // Отслеживаем успешное завершение онбординга
        trackEvent("onboarding_completed", meta: meta)
    case .unknown(let meta, let name):
        // Обрабатываем неизвестные события
        trackEvent(name, meta: meta)
    // При необходимости обработайте остальные случаи
    }
}
Примеры событий (нажмите, чтобы развернуть)
// onboardingStarted
{
  "name": "onboarding_started",
  "meta": {
    "onboarding_id": "onboarding_123",
    "screen_cid": "welcome_screen",
    "screen_index": 0,
    "total_screens": 4
  }
}

// screenPresented

{
    "name": "screen_presented",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "interests_screen",
        "screen_index": 2,
        "total_screens": 4
    }
}

// screenCompleted

{
    "name": "screen_completed",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "profile_screen",
        "screen_index": 1,
        "total_screens": 4
    },
    "params": {
        "element_id": "profile_form",
        "reply": "success"
    }
}

// secondScreenPresented

{
    "name": "second_screen_presented",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "profile_screen",
        "screen_index": 1,
        "total_screens": 4
    }
}

// userEmailCollected

{
    "name": "user_email_collected",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "profile_screen",
        "screen_index": 1,
        "total_screens": 4
    }
}

// onboardingCompleted

{
    "name": "onboarding_completed",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "final_screen",
        "screen_index": 3,
        "total_screens": 4
    }
}