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

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

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

1. Вы [создали онбординг](create-onboarding).
2. Вы добавили онбординг в [плейсмент](placements).

## Настройка обработчиков событий \{#set-up-event-handlers\}

Для обработки событий онбординга используйте метод `view.setEventHandlers`:

```typescript showLineNumbers

try {
  const view = await createOnboardingView(onboarding);
  
  view.setEventHandlers({
    onAnalytics(event, meta) {
      console.log('Analytics event:', event);
    },
    onClose(actionId, meta) {
      console.log('Onboarding closed:', actionId);
      return true; // Allow the onboarding to close
    },
    onCustom(actionId, meta) {
      console.log('Custom action:', actionId);
      return false; // Don't close the onboarding
    },
    onPaywall(actionId, meta) {
      console.log('Paywall action:', actionId);
      view.dismiss().then(() => {
        openPaywall(actionId);
      });
    },
    onStateUpdated(action, meta) {
      console.log('State updated:', action);
    },
    onFinishedLoading(meta) {
      console.log('Onboarding finished loading');
    },
    onError(error) {
      console.error('Onboarding error:', error);
    },
  });
  
  await view.present();
} catch (error) {
  console.error('Failed to present onboarding:', error);
}
```

## Типы событий \{#event-types\}

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

### Обработка пользовательских действий \{#handle-custom-actions\}

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

  <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 */
  }}
/>

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

```typescript showLineNumbers
view.setEventHandlers({
  onCustom(actionId, meta) {
    switch (actionId) {
      case 'login':
        console.log('Login action triggered');
        break;
      case 'allow_notifications':
        console.log('Allow notifications action triggered');
        break;
    }
    return false; // Don't close the onboarding
  },
});
```

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

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

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

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

```typescript showLineNumbers
view.setEventHandlers({
  onFinishedLoading(meta) {
    console.log('Onboarding loaded:', meta.onboardingId);
  },
});
```

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

```json
{
    "meta": {
        "onboarding_id": "onboarding_123",
        "screen_cid": "welcome_screen",
        "screen_index": 0,
        "total_screens": 4
    }
}
```
</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
Обратите внимание: вам нужно самостоятельно управлять тем, что происходит при закрытии онбординга пользователем. Например, необходимо прекратить его отображение.
:::

```typescript showLineNumbers
view.setEventHandlers({
  onClose(actionId, meta) {
    console.log('Onboarding closed:', actionId);
    return true; // Allow the onboarding to close
  },
});
```

<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
Обрабатывайте это событие, если хотите открывать пейвол внутри онбординга. Если вы хотите открыть пейвол после его закрытия, есть более простой способ: обработайте действие закрытия и откройте пейвол, не опираясь на данные события.
:::

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

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

```typescript showLineNumbers
view.setEventHandlers({
  onPaywall(actionId, meta) {
    // Dismiss onboarding before presenting paywall
    view.dismiss().then(() => {
      openPaywall(actionId);
    });
  },
});

async function openPaywall(placementId: string) {
  // Implement your paywall opening logic here
}
```

<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>

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

Аналитическое событие приходит при различных событиях навигации в процессе онбординга:

```typescript showLineNumbers
view.setEventHandlers({
  onAnalytics(event, meta) {
    console.log('Analytics event:', event.type, meta.onboardingId);
  },
});
```

Объект `event` может быть одним из следующих типов:

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

Каждое событие содержит информацию `meta` со следующими полями:

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

<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>