---
title: "Обработка событий онбординга в iOS SDK"
description: "Обработка событий, связанных с онбордингом, в iOS с помощью Adapty."
---

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

1. Вы установили [Adapty iOS SDK](sdk-installation-ios) версии 3.8.0 или выше.
2. Вы [создали онбординг](create-onboarding).
3. Вы добавили онбординг в [плейсмент](placements).

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

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

## Пользовательские действия \{#custom-actions\}

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

  <img src="/assets/shared/img/ios-events-1.webp"
  style={{
    border: '1px solid #727272', /* border width and color */
    width: '700px', /* image width */
    display: 'block', /* for alignment */
    margin: '0 auto' /* center alignment */
  }}
/>

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

```swift showLineNumbers    
func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) {
    if action.actionId == "allowNotifications" {
        // Request notification permissions
    }
}
    
func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) {
    // Handle errors
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>

```json
{
  "actionId": "allowNotifications",
  "meta": {
    "onboardingId": "onboarding_123",
    "screenClientId": "profile_screen",
    "screenIndex": 0,
    "screensTotal": 3
  }
}
```
</Details>

## Закрытие онбординга \{#closing-onboarding\}

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

  <img src="/assets/shared/img/ios-events-2.webp"
  style={{
    border: '1px solid #727272', /* border width and color */
    width: '700px', /* image width */
    display: 'block', /* for alignment */
    margin: '0 auto' /* center alignment */
  }}
/>

:::important
Обратите внимание: вам нужно самостоятельно управлять тем, что происходит при закрытии онбординга пользователем. Например, необходимо прекратить отображение самого онбординга.
:::
Пример:

```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) {
    controller.dismiss(animated: true)
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>

```json
{
  "action_id": "close_button",
  "meta": {
    "onboarding_id": "onboarding_123",
    "screen_cid": "final_screen",
    "screen_index": 3,
    "total_screens": 4
  }
}
```

</Details>

## Открытие пейвола \{#opening-a-paywall\}

:::tip
Обрабатывайте это событие, если хотите открыть пейвол внутри онбординга. Если же пейвол нужно открыть после закрытия онбординга, есть более простой способ — обработайте [`AdaptyOnboardingsCloseAction`](#closing-onboarding) и откройте пейвол без привязки к данным события.
:::

Если пользователь нажимает кнопку, открывающую пейвол, вы получите ID действия кнопки, который вы [задали вручную](get-paid-in-onboardings). Наиболее удобный подход — сделать ID действия равным ID плейсмента пейвола. Тогда после получения `AdaptyOnboardingsOpenPaywallAction` можно сразу использовать ID плейсмента для получения и отображения пейвола.

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

```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onPaywallAction action: AdaptyOnboardingsOpenPaywallAction) {
    // Dismiss onboarding before presenting paywall
    controller.dismiss(animated: true) {
        Task {
            do {
                // Get the paywall using the placement ID from the action
                let paywall = try await Adapty.getPaywall(placementId: action.actionId)
                
                // Get the paywall configuration
                let paywallConfig = try await AdaptyUI.getPaywallConfiguration(
                    forPaywall: paywall
                )
                
                // Create and present the paywall controller
                let paywallController = try AdaptyUI.paywallController(
                    with: paywallConfig,
                    delegate: self
                )
                
                // Present the paywall from the root view controller
                if let rootVC = UIApplication.shared.windows.first?.rootViewController {
                    rootVC.present(paywallController, animated: true)
                }
            } catch {
                // Handle any errors that occur during paywall loading
                print("Failed to present paywall: \(error)")
            }
        }
    }
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>

```json
{
    "action_id": "premium_offer_1",
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "pricing_screen",
        "screen_index": 2,
        "total_screens": 4
    }
}
```

</Details>

## Завершение загрузки онбординга \{#finishing-loading-onboarding\}

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

```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, didFinishLoading action: OnboardingsDidFinishLoadingAction) {
    // Handle loading completion
}
```

<Details>
<summary>Пример события (нажмите, чтобы развернуть)</summary>

```json
{
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "welcome_screen",
        "screen_index": 0,
        "total_screens": 4
    }
}
```

</Details>

## Отслеживание навигации \{#tracking-navigation\}

Метод `onAnalyticsEvent` вызывается при возникновении различных аналитических событий в процессе прохождения онбординга.

Объект `event` может быть одного из следующих типов:
| Тип | Описание |
|------------|-------------|
| `onboardingStarted` | Онбординг загружен |
| `screenPresented` | Показан любой экран |
| `screenCompleted` | Экран завершён. Включает необязательный `elementId` (идентификатор завершённого элемента) и необязательный `reply` (ответ пользователя). Срабатывает, когда пользователь выполняет любое действие для выхода с экрана. |
| `secondScreenPresented` | Показан второй экран |
| `userEmailCollected` | Срабатывает, когда адрес электронной почты пользователя получен через поле ввода |
| `onboardingCompleted` | Срабатывает, когда пользователь достигает экрана с ID `final`. Если вам нужно это событие, [назначьте ID `final` последнему экрану](design-onboarding). |
| `unknown` | Для любого нераспознанного типа события. Включает `name` (название неизвестного события) и `meta` (дополнительные метаданные) |

Каждое событие содержит информацию `meta` со следующими полями:
| Поле | Описание |
|------------|-------------|
| `onboardingId` | Уникальный идентификатор онбординга |
| `screenClientId` | Идентификатор текущего экрана |
| `screenIndex` | Позиция текущего экрана в потоке |
| `screensTotal` | Общее количество экранов в потоке |

Пример использования аналитических событий для отслеживания:

```swift
func onboardingController(_ controller: AdaptyOnboardingController, onAnalyticsEvent event: AdaptyOnboardingsAnalyticsEvent) {
    switch event {
    case .onboardingStarted(let meta):
        // Track onboarding start
        trackEvent("onboarding_started", meta: meta)
    case .screenPresented(let meta):
        // Track screen presentation
        trackEvent("screen_presented", meta: meta)
    case .screenCompleted(let meta, let elementId, let reply):
        // Track screen completion with user response
        trackEvent("screen_completed", meta: meta, elementId: elementId, reply: reply)
    case .onboardingCompleted(let meta):
        // Track successful onboarding completion
        trackEvent("onboarding_completed", meta: meta)
    case .unknown(let meta, let name):
        // Handle unknown events
        trackEvent(name, meta: meta)
    // Handle other cases as needed
    }
}
```

<Details>
<summary>Примеры событий (нажмите, чтобы развернуть)</summary>

```javascript
// 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
    }
}

```

</Details>