---
title: "Xử lý sự kiện onboarding trong Kotlin Multiplatform SDK"
description: "Xử lý các sự kiện liên quan đến onboarding trong Kotlin Multiplatform bằng Adapty."
---

Trước khi bắt đầu, hãy đảm bảo rằng:

1. Bạn đã cài đặt [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) phiên bản 3.15.0 trở lên.
2. Bạn đã [tạo một onboarding](create-onboarding).
3. Bạn đã thêm onboarding vào một [placement](placements).

Các onboarding được cấu hình bằng builder sẽ tạo ra các sự kiện mà ứng dụng của bạn có thể phản hồi. Xem cách xử lý các sự kiện này bên dưới.

## Thiết lập observer sự kiện onboarding \{#set-up-the-onboarding-event-observer\}

Để xử lý các sự kiện onboarding, bạn cần triển khai interface `AdaptyUIOnboardingsEventsObserver` và thiết lập nó với `AdaptyUI.setOnboardingsEventsObserver()`. Việc này nên được thực hiện sớm trong vòng đời ứng dụng, thường là trong activity chính hoặc khi khởi tạo ứng dụng.

```kotlin

// In your app initialization
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

## Hành động tùy chỉnh \{#custom-actions\}

Trong builder, bạn có thể thêm hành động **custom** vào một nút và gán cho nó một ID. Sau đó, bạn có thể sử dụng ID này trong code và xử lý nó như một hành động tùy chỉnh.

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

Ví dụ: nếu người dùng nhấn vào một nút tùy chỉnh như **Login** hoặc **Allow notifications**, phương thức delegate `onCustomAction` sẽ được kích hoạt với action ID từ builder. Bạn có thể tạo ID tùy ý, chẳng hạn như "allowNotifications".

```kotlin

class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
    override fun onboardingViewOnCustomAction(
        view: AdaptyUIOnboardingView,
        meta: AdaptyUIOnboardingMeta,
        actionId: String
    ) {
        when (actionId) {
            "openPaywall" -> {
                // Display paywall from onboarding
                // You would typically fetch and present a new paywall here
                mainUiScope.launch {
                    // Example: Get paywall by placement ID
                    // val paywallResult = Adapty.getPaywall("your_placement_id")
                    // paywallResult.onSuccess { paywall ->
                    //     val paywallViewResult = AdaptyUI.createPaywallView(paywall)
                    //     paywallViewResult.onSuccess { paywallView ->
                    //         paywallView.present()
                    //     }
                    // }
                }
            }
            "allowNotifications" -> {
                // Handle notification permissions
            }
            else -> {
                // Handle other custom actions
            }
        }
    }
}

// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

<Details>
    <summary>Ví dụ sự kiện (Nhấn để mở rộng)</summary>

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

## Đóng onboarding \{#closing-onboarding\}

Onboarding được coi là đã đóng khi người dùng nhấn vào một nút được gán hành động **Close**. Bạn cần quản lý những gì xảy ra khi người dùng đóng onboarding. Ví dụ:

:::important
Bạn cần quản lý những gì xảy ra khi người dùng đóng onboarding. Chẳng hạn, bạn cần dừng hiển thị onboarding đó.
:::

Nếu bạn đang dùng [`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform), `view.isStandaloneView` là `false` — cách triển khai mặc định không gọi `view.dismiss()`. Hãy xóa view khỏi layout và gọi `dispose()` trên nó trong callback này.

```kotlin

class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
    override fun onboardingViewOnCloseAction(
        view: AdaptyUIOnboardingView,
        meta: AdaptyUIOnboardingMeta,
        actionId: String
    ) {
        // Dismiss the onboarding screen
        mainUiScope.launch {
            view.dismiss()
        }

        // Additional cleanup or navigation logic can be added here
        // For example, navigate back or show main app content
    }
}

// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

<Details>
    <summary>Ví dụ sự kiện (Nhấn để mở rộng)</summary>

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

</Details>

## Mở paywall \{#opening-a-paywall\}

:::tip
Xử lý sự kiện này để mở paywall nếu bạn muốn mở nó bên trong onboarding. Nếu bạn muốn mở paywall sau khi onboarding đóng lại, có một cách đơn giản hơn — xử lý [`onboardingViewOnCloseAction`](#closing-onboarding) và mở paywall mà không cần dựa vào dữ liệu sự kiện.
:::

Cách làm liền mạch nhất khi làm việc với paywall trong onboarding là đặt action ID bằng với placement ID của paywall. Bằng cách này, bạn có thể dùng placement ID để lấy và mở paywall ngay lập tức:

```kotlin

class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
    override fun onboardingViewOnPaywallAction(
        view: AdaptyUIOnboardingView,
        meta: AdaptyUIOnboardingMeta,
        actionId: String
    ) {
        // Get the paywall using the placement ID from the action
        mainUiScope.launch {
            val paywallResult = Adapty.getPaywall(placementId = actionId)
            paywallResult.onSuccess { paywall ->
                val paywallViewResult = AdaptyUI.createPaywallView(paywall)
                paywallViewResult.onSuccess { paywallView ->
                    paywallView.present()
                }.onError { error ->
                    // handle the error
                }
            }.onError { error ->
                // handle the error
            }
        }
    }
}

// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

<Details>
    <summary>Ví dụ sự kiện (Nhấn để mở rộng)</summary>

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

</Details>

## Hoàn tất tải onboarding \{#finishing-loading-onboarding\}

Khi onboarding hoàn tất quá trình tải, phương thức này sẽ được gọi:

```kotlin

class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
    override fun onboardingViewDidFinishLoading(
        view: AdaptyUIOnboardingView,
        meta: AdaptyUIOnboardingMeta
    ) {
        // Handle loading completion
        // You can add any initialization logic here
    }
}

// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

<Details>
    <summary>Ví dụ sự kiện (Nhấn để mở rộng)</summary>

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

</Details>

## Sự kiện điều hướng \{#navigation-events\}

Phương thức `onboardingViewOnAnalyticsEvent` được gọi khi các sự kiện analytics khác nhau xảy ra trong quá trình onboarding flow.

Đối tượng `event` có thể là một trong các kiểu sau:
|Kiểu | Mô tả |
|------------|-------------|
| `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | Khi onboarding đã được tải xong |
| `AdaptyOnboardingsAnalyticsEventScreenPresented` | Khi có màn hình nào đó được hiển thị |
| `AdaptyOnboardingsAnalyticsEventScreenCompleted` | Khi một màn hình hoàn tất. Bao gồm `elementId` tùy chọn (định danh của phần tử đã hoàn tất) và `reply` tùy chọn (phản hồi từ người dùng). Được kích hoạt khi người dùng thực hiện bất kỳ hành động nào để thoát khỏi màn hình. |
| `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | Khi màn hình thứ hai được hiển thị |
| `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | Được kích hoạt khi email của người dùng được thu thập qua trường nhập liệu |
| `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | Được kích hoạt khi người dùng đến màn hình có ID `final`. Nếu bạn cần sự kiện này, hãy gán ID `final` cho màn hình cuối cùng. |
| `AdaptyOnboardingsAnalyticsEventUnknown` | Dành cho các kiểu sự kiện không xác định. Bao gồm `name` (tên của sự kiện không xác định) và `meta` (metadata bổ sung) |

Mỗi sự kiện bao gồm thông tin `meta` chứa:
| Trường | Mô tả |
|------------|-------------|
| `onboardingId` | Định danh duy nhất của onboarding flow |
| `screenClientId` | Định danh của màn hình hiện tại |
| `screenIndex` | Vị trí của màn hình hiện tại trong flow |
| `screensTotal` | Tổng số màn hình trong flow |

Dưới đây là ví dụ về cách bạn có thể sử dụng các sự kiện analytics để theo dõi:

```kotlin

class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
    override fun onboardingViewOnAnalyticsEvent(
        view: AdaptyUIOnboardingView,
        meta: AdaptyUIOnboardingMeta,
        event: AdaptyOnboardingsAnalyticsEvent
    ) {
        when (event) {
            is AdaptyOnboardingsAnalyticsEventOnboardingStarted -> {
                // Track onboarding start
                trackEvent("onboarding_started", event.meta)
            }
            is AdaptyOnboardingsAnalyticsEventScreenPresented -> {
                // Track screen presentation
                trackEvent("screen_presented", event.meta)
            }
            is AdaptyOnboardingsAnalyticsEventScreenCompleted -> {
                // Track screen completion with user response
                trackEvent("screen_completed", event.meta, event.elementId, event.reply)
            }
            is AdaptyOnboardingsAnalyticsEventOnboardingCompleted -> {
                // Track successful onboarding completion
                trackEvent("onboarding_completed", event.meta)
            }
            is AdaptyOnboardingsAnalyticsEventUnknown -> {
                // Handle unknown events
                trackEvent(event.name, event.meta)
            }
            // Handle other cases as needed
        }
    }

    private fun trackEvent(eventName: String, meta: AdaptyUIOnboardingMeta, elementId: String? = null, reply: String? = null) {
        // Implement your analytics tracking here
        // For example, send to your analytics service
    }
}

// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```

<Details>
    <summary>Ví dụ các sự kiện (Nhấn để mở rộng)</summary>

    ```javascript
    // OnboardingStarted
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "welcome_screen",
        "screenIndex": 0,
        "screensTotal": 4
    }
    }

    // ScreenPresented
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "interests_screen",
        "screenIndex": 2,
        "screensTotal": 4
    }
    }

    // ScreenCompleted
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "profile_screen",
        "screenIndex": 1,
        "screensTotal": 4
    },
        "elementId": "profile_form",
        "reply": "success"
    }

    // SecondScreenPresented
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "profile_screen",
        "screenIndex": 1,
        "screensTotal": 4
    }
    }

    // UserEmailCollected
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "profile_screen",
        "screenIndex": 1,
        "screensTotal": 4
    }
    }

    // OnboardingCompleted
    {
        "meta": {
        "onboardingId": "onboarding_123",
        "screenClientId": "final_screen",
        "screenIndex": 3,
        "screensTotal": 4
    }
    }

    ```

</Details>