---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://appmetrica.yandex.com.tr/docs/en/data-collection/offers.md
  - https://appmetrica.yandex.com.tr/docs/ru/data-collection/offers.md
---
> **Documentation Index:** Fetch the complete configuration index at https://appmetrica.yandex.com.tr/docs/ru/llms.txt

# Офферные события в продуктовых сценариях

Документация по Product Flow с примерами интеграции в SDK:

- **Android** — [Продуктовые сценарии и офферные события](https://appmetrica.yandex.com.tr/docs/ru/sdk/android/analytics/android-product-flow.md);
- **iOS** — [Продуктовые сценарии и офферные события](https://appmetrica.yandex.com.tr/docs/ru/sdk/ios/analytics/ios-product-flow.md).

## Подробнее о подходе {#details}

**Product Flow** — это новая схема работы типовых событий AppMetrica для приложений с офферами, покупками, оформлением заявок и многошаговыми сценариями оформления продуктов и услуг.

Данный подход помогает стандартизировать аналитику следующих сущностей и сценариев:

- продуктовые предложения;
- маркетинговые офферы;
- покупки товаров и услуг;
- пользовательские воронки;
- шаги оформления;
- заявки и результаты одобрения;
- асинхронные S2S-результаты.

Рекомендуем использовать подход Product Flow для следующих типов приложений:

- банки;
- страховые сервисы;
- телеком-приложения;
- сервисы бронирования и путешествий;
- подписочные сервисы;
- сервисы доставки;
- маркетплейсы;
- игровые приложения;
- любые приложения с продуктовыми сценариями, покупками и аналитикой воронок.

{% note tip "Не расходуют лимиты custom events и DSA" %}

Новые типовые события не учитываются в следующих лимитах:

- `custom events`;
- `Data Stream API`.

Это позволяет:

- постепенно внедрять новую схему разметки;
- отправлять больше продуктовых сценариев и шагов;
- строить подробные воронки и аналитику без расходования лимитов кастомных событий и DSA.

{% endnote %}

## Какую проблему решает данный подход {#problem-statement}

В настоящее время многие приложения используют `custom events` для передачи аналитических данных о следующих сущностях и сценариях:

- офферы;
- заявки;
- продуктовые сценарии;
- onboarding-сценарии;
- сценарии оформления заказа;
- сценарии одобрения.

Такой подход приводит к следующим проблемам:

- одинаковые сценарии размечаются по-разному;
- затруднено построение типовых отчетов;
- аналитика слабо переносится между командами;
- невозможно автоматическое построение воронок;
- сложно сравнивать эффективность офферов и сценариев.

Схема продуктовых сценариев и офферных событий предлагает унифицированный подход к разметке ключевых этапов:

- показ оффера;
- начало оформления;
- промежуточные шаги;
- финальный результат.

## Основные события {#main-events}

Схема взаимодействия строится на основе четырех основных событий:

#|
|| **Событие** | **Что означает** ||
|| `offerShown` | Пользователь увидел оффер или предложение ||
|| `flowStart` | Пользователь начал оформление продукта ||
|| `flowStep` | Промежуточный шаг оформления ||
|| `flowResult` | Итоговый результат ||
|#

## Сценарии разметки {#scenarios}

В этом разделе показаны полные пользовательские сценарии для разных индустрий.

{% note tip "Примеры сценариев" %}

Все сценарии в данном документе являются **примерами** разметки и демонстрируют возможные варианты интеграции.

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

{% endnote %}

Каждый сценарий описывает:

- что видит и делает пользователь в приложении;
- какие события нужно отправить;
- когда `offerShown` можно не отправлять;
- когда `flowStart` можно не отправлять;
- как передавать промежуточные шаги через `flowStep`;
- как передавать финальный результат через `flowResult`;
- как использовать `payload`, `referrer` и `stepOption`;
- как передавать результат позже через S2S.

### Банки и финтех {#banks}

#### Кредит по персональному офферу: offer → оформление → pending → S2S result {#personal-offer}

{% cut "Пользователь видит баннер: «Вам предварительно одобрен кредит до 500 000 ₽ по ставке от 12.5%»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("credit_q1", "financial_product")
          .withProductId("personal_loan")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("main_screen_credit_banner")
                      .withScreen("main")
                      .build()
          )
          .withPayload(mapOf(
              "campaign_id" to "credit_spring_2026",
              "segment" to "preapproved_users",
              "approved_limit" to "500000",
              "currency" to "RUB",
              "interest_rate" to "12.5"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "credit_q1", offerType: "financial_product")
      .withProductId("personal_loan")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "banner", identifier: "main_screen_credit_banner", screen: "main"))
      .withPayload([
          "campaign_id": "credit_spring_2026",
          "segment": "preapproved_users",
          "approved_limit": "500000",
          "currency": "RUB",
          "interest_rate": "12.5"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь нажимает на баннер и начинает оформление заявки." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("personal_loan")
          .withProductOfferId("credit_q1")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "personal_loan")
      .withProductOfferId("credit_q1")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь загружает документы." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("personal_loan", "documents")
          .withProductOfferId("credit_q1")
          .withStepOption("passport_upload")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "personal_loan", stepType: "documents")
      .withProductOfferId("credit_q1")
      .withStepOption("passport_upload")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь отправляет заявку на скоринг." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("personal_loan", "scoring")
          .withProductOfferId("credit_q1")
          .withStepOption("automatic_scoring")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "personal_loan", stepType: "scoring")
      .withProductOfferId("credit_q1")
      .withStepOption("automatic_scoring")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь завершил действия на своей стороне, заявка ушла на рассмотрение." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.PENDING, "personal_loan")
          .withProductOfferId("credit_q1")
          .withPayload(mapOf(
              "application_id" to "loan_app_12345",
              "requested_amount" to "450000",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "personal_loan", status: .pending)
      .withProductOfferId("credit_q1")
      .withPayload([
          "application_id": "loan_app_12345",
          "requested_amount": "450000",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже банк присылает финальный результат через S2S." %}

```java
flowResult(
    productId = "travel_insurance",
    productOfferId = "travel_insurance_offer",
    status = "success",
    payload = mapOf(
        "application_id" to "insurance_app_987",
        "policy_id" to "policy_555",
        "decision_source" to "s2s"
    )
)
```

Отправка офферных событий по схеме S2S будет реализована через POST API в одном из ближайших релизов. В текущей документации приведен пример сценария, который демонстрирует ожидаемый способ интеграции.

{% endcut %}

#### Органическое оформление кредита без оффера {#no-offer}

{% cut "Пользователь сам открыл раздел «Кредиты» из меню приложения. Оффера не было." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("personal_loan")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "personal_loan")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь загружает документы." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("personal_loan", "documents")
          .withStepOption("passport_upload")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "personal_loan", stepType: "documents")
      .withStepOption("passport_upload")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Заявка отправлена на рассмотрение." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.PENDING, "personal_loan")
          .withPayload(mapOf(
              "application_id" to "loan_app_67890",
              "requested_amount" to "300000",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "personal_loan", status: .pending)
      .withPayload([
          "application_id": "loan_app_67890",
          "requested_amount": "300000",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже банк присылает отказ через S2S." %}

```java
flowResult(
    productId = "personal_loan",
    productOfferId = null,
    status = "declined",
    payload = mapOf(
        "application_id" to "loan_app_67890",
        "decline_reason" to "scoring_rejected",
        "decision_source" to "s2s"
    )
)
```

Отправка офферных событий по схеме S2S будет реализована через POST API в одном из ближайших релизов. В текущей документации приведен пример сценария, который демонстрирует ожидаемый способ интеграции.

{% endcut %}


### Телеком {#telecom}

#### Подключение eSIM по офферу {#esim}

{% cut "Пользователь открывает экран тарифов и видит баннер: «eSIM со скидкой 20% на первый месяц»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("esim_offer_q2", "service")
          .withProductId("esim")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("tariffs_screen_esim_banner")
                      .withScreen("tariffs")
                      .build()
          )
          .withPayload(mapOf(
              "campaign_id" to "esim_discount_q2",
              "discount_value" to "20",
              "discount_period" to "first_month",
              "region" to "RS"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "esim_offer_q2", offerType: "service")
      .withProductId("esim")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "banner", identifier: "tariffs_screen_esim_banner", screen: "tariffs"))
      .withPayload([
          "campaign_id": "esim_discount_q2",
          "discount_value": "20",
          "discount_period": "first_month",
          "region": "RS"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь нажимает на баннер и начинает подключение." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("esim")
          .withProductOfferId("esim_offer_q2")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "esim")
      .withProductOfferId("esim_offer_q2")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает тариф." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("esim", "tariff_selection")
          .withProductOfferId("esim_offer_q2")
          .withStepOption("unlimited_30d")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "esim", stepType: "tariff_selection")
      .withProductOfferId("esim_offer_q2")
      .withStepOption("unlimited_30d")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь проходит идентификацию." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("esim", "identity_verification")
          .withProductOfferId("esim_offer_q2")
          .withStepOption("document_scan")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "esim", stepType: "identity_verification")
      .withProductOfferId("esim_offer_q2")
      .withStepOption("document_scan")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "eSIM успешно подключена." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "esim")
          .withProductOfferId("esim_offer_q2")
          .withPayload(mapOf(
              "tariff_id" to "unlimited_30d",
              "activation_type" to "esim",
              "discount_applied" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "esim", status: .success)
      .withProductOfferId("esim_offer_q2")
      .withPayload([
          "tariff_id": "unlimited_30d",
          "activation_type": "esim",
          "discount_applied": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Подключение роуминг-пакета перед поездкой {#roaming}

{% cut "Пользователь открывает раздел роуминга и видит предложение: «10 ГБ в Европе на 14 дней за 1500 рублей»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("eu_roaming_10gb", "service")
          .withProductId("roaming_package")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("roaming_europe_banner")
                      .withScreen("roaming")
                      .build()
          )
          .withPayload(mapOf(
              "region" to "Europe",
              "traffic_limit_gb" to "10",
              "duration_days" to "14",
              "price" to "1500",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "eu_roaming_10gb", offerType: "service")
      .withProductId("roaming_package")
      .withReferrer(OfferReferrer(type: "banner", identifier: "roaming_europe_banner", screen: "roaming"))
      .withPayload([
          "region": "Europe",
          "traffic_limit_gb": "10",
          "duration_days": "14",
          "price": "1500",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает подключение роуминг-пакета." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("roaming_package")
          .withProductOfferId("eu_roaming_10gb")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "roaming_package")
      .withProductOfferId("eu_roaming_10gb")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь подтверждает условия подключения." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("roaming_package", "terms_confirmation")
          .withProductOfferId("eu_roaming_10gb")
          .withStepOption("accepted")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "roaming_package", stepType: "terms_confirmation")
      .withProductOfferId("eu_roaming_10gb")
      .withStepOption("accepted")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Роуминг-пакет успешно подключён." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "roaming_package")
          .withProductOfferId("eu_roaming_10gb")
          .withPayload(mapOf(
              "region" to "Europe",
              "traffic_limit_gb" to "10",
              "duration_days" to "14",
              "activation_status" to "enabled"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "roaming_package", status: .success)
      .withProductOfferId("eu_roaming_10gb")
      .withPayload([
          "region": "Europe",
          "traffic_limit_gb": "10",
          "duration_days": "14",
          "activation_status": "enabled"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Upgrade тарифа {#upgrade-tariff}

{% cut "Пользователь видит предложение: «Перейдите на Premium-тариф с безлимитным интернетом»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("premium_tariff_upgrade", "service")
          .withProductId("tariff_upgrade")
          .withBenefitType("bundle_extra")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("popup")
                      .withIdentifier("premium_upgrade_popup")
                      .withScreen("tariff_details")
                      .build()
          )
          .withPayload(mapOf(
              "current_tariff" to "smart_m",
              "target_tariff" to "premium_unlimited",
              "monthly_price" to "1990",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "premium_tariff_upgrade", offerType: "service")
      .withProductId("tariff_upgrade")
      .withBenefitType("bundle_extra")
      .withReferrer(OfferReferrer(type: "popup", identifier: "premium_upgrade_popup", screen: "tariff_details"))
      .withPayload([
          "current_tariff": "smart_m",
          "target_tariff": "premium_unlimited",
          "monthly_price": "1990",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает смену тарифа." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("tariff_upgrade")
          .withProductOfferId("premium_tariff_upgrade")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "tariff_upgrade")
      .withProductOfferId("premium_tariff_upgrade")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь подтверждает новый тариф." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("tariff_upgrade", "tariff_confirmation")
          .withProductOfferId("premium_tariff_upgrade")
          .withStepOption("premium_unlimited")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "tariff_upgrade", stepType: "tariff_confirmation")
      .withProductOfferId("premium_tariff_upgrade")
      .withStepOption("premium_unlimited")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Тариф успешно изменён." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "tariff_upgrade")
          .withProductOfferId("premium_tariff_upgrade")
          .withPayload(mapOf(
              "previous_tariff" to "smart_m",
              "new_tariff" to "premium_unlimited",
              "upgrade_status" to "completed"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "tariff_upgrade", status: .success)
      .withProductOfferId("premium_tariff_upgrade")
      .withPayload([
          "previous_tariff": "smart_m",
          "new_tariff": "premium_unlimited",
          "upgrade_status": "completed"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Подключение домашнего интернета {#home-internet}

{% cut "Пользователь открывает раздел домашнего интернета и видит предложение: «Домашний интернет 500 Мбит/с за 990 рублей в месяц»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("home_internet_500", "service")
          .withProductId("home_internet")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("home_internet_offer")
                      .withScreen("home_services")
                      .build()
          )
          .withPayload(mapOf(
              "speed_mbps" to "500",
              "monthly_price" to "990",
              "currency" to "RUB",
              "connection_fee" to "0"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "home_internet_500", offerType: "service")
      .withProductId("home_internet")
      .withReferrer(OfferReferrer(type: "banner", identifier: "home_internet_offer", screen: "home_services"))
      .withPayload([
          "speed_mbps": "500",
          "monthly_price": "990",
          "currency": "RUB",
          "connection_fee": "0"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает оформление заявки на подключение домашнего интернета." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("home_internet")
          .withProductOfferId("home_internet_500")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "home_internet")
      .withProductOfferId("home_internet_500")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь вводит адрес подключения." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("home_internet", "address_input")
          .withProductOfferId("home_internet_500")
          .withStepOption("manual_input")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "home_internet", stepType: "address_input")
      .withProductOfferId("home_internet_500")
      .withStepOption("manual_input")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату визита мастера." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("home_internet", "installation_timeslot")
          .withProductOfferId("home_internet_500")
          .withStepOption("2026-06-20_10:00")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "home_internet", stepType: "installation_timeslot")
      .withProductOfferId("home_internet_500")
      .withStepOption("2026-06-20_10:00")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Заявка на подключение отправлена, пользователь ждёт визита мастера." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.PENDING, "home_internet")
          .withProductOfferId("home_internet_500")
          .withPayload(mapOf(
              "request_id" to "internet_request_555",
              "connection_status" to "awaiting_installation",
              "selected_timeslot" to "2026-06-20_10:00"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "home_internet", status: .pending)
      .withProductOfferId("home_internet_500")
      .withPayload([
          "request_id": "internet_request_555",
          "connection_status": "awaiting_installation",
          "selected_timeslot": "2026-06-20_10:00"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже оператор через S2S сообщает, что мастер выполнил подключение, интернет проведён и тариф активирован." %}

```java
flowResult(
    productId = "home_internet",
    productOfferId = "home_internet_500",
    status = "success",
    payload = mapOf(
        "request_id" to "internet_request_555",
        "installation_status" to "completed",
        "technician_visit" to "completed",
        "tariff_id" to "home_500",
        "tariff_status" to "active",
        "decision_source" to "s2s"
    )
)
```

Отправка офферных событий по схеме S2S будет реализована через POST API в одном из ближайших релизов. В текущей документации приведен пример сценария, который демонстрирует ожидаемый способ интеграции.

{% endcut %}

### Travel / Booking {#travel}

#### Бронирование отеля по скидочному офферу {#booking-offer-discount}

{% cut "Пользователь ищет отель в Белграде и видит карточку: «Скидка 20% на этот отель»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("hotel_discount_may", "booking")
          .withProductId("hotel_booking")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("search_results_hotel_discount")
                      .withScreen("hotel_search_results")
                      .build()
          )
          .withPayload(mapOf(
              "campaign_id" to "may_hotels_sale",
              "hotel_id" to "hotel_987",
              "city" to "Belgrade",
              "discount_value" to "20",
              "original_price" to "25000",
              "final_price" to "20000",
              "currency" to "RUB",
              "room_type" to "deluxe",
              "refundable" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "hotel_discount_may", offerType: "booking")
      .withProductId("hotel_booking")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "banner", identifier: "search_results_hotel_discount", screen: "hotel_search_results"))
      .withPayload([
          "campaign_id": "may_hotels_sale",
          "hotel_id": "hotel_987",
          "city": "Belgrade",
          "discount_value": "20",
          "original_price": "25000",
          "final_price": "20000",
          "currency": "RUB",
          "room_type": "deluxe",
          "refundable": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает бронирование." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("hotel_booking")
          .withProductOfferId("hotel_discount_may")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "hotel_booking")
      .withProductOfferId("hotel_discount_may")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает даты." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("hotel_booking", "dates")
          .withProductOfferId("hotel_discount_may")
          .withStepOption("3_nights")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "hotel_booking", stepType: "dates")
      .withProductOfferId("hotel_discount_may")
      .withStepOption("3_nights")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает гостей." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("hotel_booking", "guests")
          .withProductOfferId("hotel_discount_may")
          .withStepOption("2_adults")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "hotel_booking", stepType: "guests")
      .withProductOfferId("hotel_discount_may")
      .withStepOption("2_adults")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает способ оплаты." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("hotel_booking", "payment")
          .withProductOfferId("hotel_discount_may")
          .withStepOption("bank_card")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "hotel_booking", stepType: "payment")
      .withProductOfferId("hotel_discount_may")
      .withStepOption("bank_card")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Бронирование успешно завершено." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "hotel_booking")
          .withProductOfferId("hotel_discount_may")
          .withPayload(mapOf(
              "hotel_id" to "hotel_987",
              "city" to "Belgrade",
              "nights" to "3",
              "guests" to "2",
              "original_price" to "25000",
              "final_price" to "20000",
              "currency" to "RUB",
              "discount_applied" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "hotel_booking", status: .success)
      .withProductOfferId("hotel_discount_may")
      .withPayload([
          "hotel_id": "hotel_987",
          "city": "Belgrade",
          "nights": "3",
          "guests": "2",
          "original_price": "25000",
          "final_price": "20000",
          "currency": "RUB",
          "discount_applied": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Медицинские сервисы {#med-services}

#### Органическая запись к врачу без оффера {#doctors-appointment}

{% cut "Пользователь сам открывает раздел записи к врачу из меню приложения. Оффера или рекламного предложения не было." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("doctor_appointment")
          .withPayload(mapOf("entry_point" to "menu", "clinic_id" to "clinic_123"))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "doctor_appointment")
      .withPayload(["entry_point": "menu", "clinic_id": "clinic_123"])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает специализацию врача." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("doctor_appointment", "specialization_selection")
          .withStepOption("therapy")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "doctor_appointment", stepType: "specialization_selection")
      .withStepOption("therapy")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает врача." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("doctor_appointment", "doctor_selection")
          .withStepOption("doctor_456")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "doctor_appointment", stepType: "doctor_selection")
      .withStepOption("doctor_456")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату и время приёма." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("doctor_appointment", "timeslot_selection")
          .withStepOption("2026-06-10_14:30")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "doctor_appointment", stepType: "timeslot_selection")
      .withStepOption("2026-06-10_14:30")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Запись к врачу успешно создана." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "doctor_appointment")
          .withPayload(mapOf(
              "appointment_id" to "appointment_777",
              "clinic_id" to "clinic_123",
              "doctor_specialization" to "therapy"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "doctor_appointment", status: .success)
      .withPayload([
          "appointment_id": "appointment_777",
          "clinic_id": "clinic_123",
          "doctor_specialization": "therapy"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Запись к врачу по предложению {#appointment-suggestion}

{% cut "Пользователь открывает главный экран приложения клиники и видит карточку: «Запишитесь на чек-ап со скидкой 20%»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("checkup_discount_q2", "service")
          .withProductId("doctor_appointment")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("main_checkup_banner")
                      .withScreen("main")
                      .build()
          )
          .withPayload(mapOf(
              "clinic_id" to "clinic_123",
              "specialization" to "therapy",
              "discount_value" to "20",
              "campaign_id" to "health_checkup_q2"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "checkup_discount_q2", offerType: "service")
      .withProductId("doctor_appointment")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "banner", identifier: "main_checkup_banner", screen: "main"))
      .withPayload([
          "clinic_id": "clinic_123",
          "specialization": "therapy",
          "discount_value": "20",
          "campaign_id": "health_checkup_q2"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает запись к врачу." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("doctor_appointment")
          .withProductOfferId("checkup_discount_q2")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "doctor_appointment")
      .withProductOfferId("checkup_discount_q2")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает врача." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("doctor_appointment", "doctor_selection")
          .withProductOfferId("checkup_discount_q2")
          .withStepOption("therapist")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "doctor_appointment", stepType: "doctor_selection")
      .withProductOfferId("checkup_discount_q2")
      .withStepOption("therapist")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату и время приёма." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("doctor_appointment", "timeslot_selection")
          .withProductOfferId("checkup_discount_q2")
          .withStepOption("2026-06-10_14:30")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "doctor_appointment", stepType: "timeslot_selection")
      .withProductOfferId("checkup_discount_q2")
      .withStepOption("2026-06-10_14:30")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Запись успешно создана." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "doctor_appointment")
          .withProductOfferId("checkup_discount_q2")
          .withPayload(mapOf(
              "appointment_id" to "appointment_555",
              "doctor_specialization" to "therapy",
              "clinic_id" to "clinic_123",
              "discount_applied" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "doctor_appointment", status: .success)
      .withProductOfferId("checkup_discount_q2")
      .withPayload([
          "appointment_id": "appointment_555",
          "doctor_specialization": "therapy",
          "clinic_id": "clinic_123",
          "discount_applied": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Beauty / Wellness {#beauty}

#### Запись в SPA с предоплатой {#spa-registry}

{% cut "Пользователь открывает приложение SPA-салона и видит предложение: «Скидка 20% на SPA-программу при онлайн-оплате»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("spa_weekend_offer", "service")
          .withProductId("spa_booking")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("spa_weekend_banner")
                      .withScreen("main")
                      .build()
          )
          .withPayload(mapOf(
              "service_type" to "spa_program",
              "discount_value" to "20",
              "original_price" to "12000",
              "final_price" to "9600",
              "currency" to "RUB",
              "campaign_id" to "spa_weekend_q2"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "spa_weekend_offer", offerType: "service")
      .withProductId("spa_booking")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "banner", identifier: "spa_weekend_banner", screen: "main"))
      .withPayload([
          "service_type": "spa_program",
          "discount_value": "20",
          "original_price": "12000",
          "final_price": "9600",
          "currency": "RUB",
          "campaign_id": "spa_weekend_q2"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает запись в SPA." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("spa_booking")
          .withProductOfferId("spa_weekend_offer")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "spa_booking")
      .withProductOfferId("spa_weekend_offer")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает SPA-программу." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("spa_booking", "service_selection")
          .withProductOfferId("spa_weekend_offer")
          .withStepOption("relax_spa_program")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "spa_booking", stepType: "service_selection")
      .withProductOfferId("spa_weekend_offer")
      .withStepOption("relax_spa_program")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату и время посещения." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("spa_booking", "timeslot_selection")
          .withProductOfferId("spa_weekend_offer")
          .withStepOption("2026-06-15_18:00")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "spa_booking", stepType: "timeslot_selection")
      .withProductOfferId("spa_weekend_offer")
      .withStepOption("2026-06-15_18:00")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь переходит к оплате предоплаты." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("spa_booking", "prepayment")
          .withProductOfferId("spa_weekend_offer")
          .withStepOption("bank_card")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "spa_booking", stepType: "prepayment")
      .withProductOfferId("spa_weekend_offer")
      .withStepOption("bank_card")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Предоплата успешно внесена, запись подтверждена." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "spa_booking")
          .withProductOfferId("spa_weekend_offer")
          .withPayload(mapOf(
              "booking_id" to "spa_booking_555",
              "service_type" to "relax_spa_program",
              "prepayment_amount" to "3000",
              "remaining_amount" to "6600",
              "currency" to "RUB",
              "payment_status" to "partially_paid"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "spa_booking", status: .success)
      .withProductOfferId("spa_weekend_offer")
      .withPayload([
          "booking_id": "spa_booking_555",
          "service_type": "relax_spa_program",
          "prepayment_amount": "3000",
          "remaining_amount": "6600",
          "currency": "RUB",
          "payment_status": "partially_paid"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже SPA-салон через S2S подтверждает, что пользователь действительно посетил процедуру." %}

```java
flowResult(
    productId = "spa_booking",
    productOfferId = "spa_weekend_offer",
    status = "success",
    payload = mapOf(
        "booking_id" to "spa_booking_555",
        "visit_status" to "completed",
        "service_type" to "relax_spa_program",
        "final_payment_amount" to "6600",
        "currency" to "RUB",
        "decision_source" to "s2s"
    )
)
```

Отправка офферных событий по схеме S2S будет реализована через POST API в одном из ближайших релизов. В текущей документации приведен пример сценария, который демонстрирует ожидаемый способ интеграции.

{% endcut %}

#### Запись на маникюр {#manicure}

{% cut "Пользователь открывает приложение салона и видит предложение: «Скидка 15% на первое посещение»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("first_visit_nails", "service")
          .withProductId("beauty_appointment")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("popup")
                      .withIdentifier("new_user_discount_popup")
                      .withScreen("main")
                      .build()
          )
          .withPayload(mapOf(
              "service_type" to "manicure",
              "discount_value" to "15",
              "campaign_id" to "new_clients_q2"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "first_visit_nails", offerType: "service")
      .withProductId("beauty_appointment")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "popup", identifier: "new_user_discount_popup", screen: "main"))
      .withPayload([
          "service_type": "manicure",
          "discount_value": "15",
          "campaign_id": "new_clients_q2"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает запись в салон." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("beauty_appointment")
          .withProductOfferId("first_visit_nails")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "beauty_appointment")
      .withProductOfferId("first_visit_nails")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает услугу." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "service_selection")
          .withProductOfferId("first_visit_nails")
          .withStepOption("manicure_gel")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "service_selection")
      .withProductOfferId("first_visit_nails")
      .withStepOption("manicure_gel")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает мастера." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "master_selection")
          .withProductOfferId("first_visit_nails")
          .withStepOption("top_master")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "master_selection")
      .withProductOfferId("first_visit_nails")
      .withStepOption("top_master")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату и время." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "timeslot_selection")
          .withProductOfferId("first_visit_nails")
          .withStepOption("2026-06-12_18:00")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "timeslot_selection")
      .withProductOfferId("first_visit_nails")
      .withStepOption("2026-06-12_18:00")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Запись успешно создана." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "beauty_appointment")
          .withProductOfferId("first_visit_nails")
          .withPayload(mapOf(
              "appointment_id" to "beauty_booking_987",
              "service_type" to "manicure_gel",
              "master_level" to "top_master",
              "discount_applied" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "beauty_appointment", status: .success)
      .withProductOfferId("first_visit_nails")
      .withPayload([
          "appointment_id": "beauty_booking_987",
          "service_type": "manicure_gel",
          "master_level": "top_master",
          "discount_applied": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Запись на стрижку и окрашивание с последующей отменой {#haircut-cancel}

{% cut "Пользователь открывает приложение салона и самостоятельно начинает запись на стрижку и окрашивание. Оффера или рекламного предложения не было." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("beauty_appointment")
          .withPayload(mapOf("entry_point" to "catalog", "service_category" to "hair"))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "beauty_appointment")
      .withPayload(["entry_point": "catalog", "service_category": "hair"])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает услугу: стрижка и окрашивание." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "service_selection")
          .withStepOption("haircut_coloring")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "service_selection")
      .withStepOption("haircut_coloring")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает мастера." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "master_selection")
          .withStepOption("top_master")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "master_selection")
      .withStepOption("top_master")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает дату и время записи." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("beauty_appointment", "timeslot_selection")
          .withStepOption("2026-06-20_15:00")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "beauty_appointment", stepType: "timeslot_selection")
      .withStepOption("2026-06-20_15:00")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Запись успешно создана." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "beauty_appointment")
          .withPayload(mapOf(
              "booking_id" to "beauty_booking_777",
              "service_type" to "haircut_coloring",
              "master_level" to "top_master",
              "booking_status" to "confirmed"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "beauty_appointment", status: .success)
      .withPayload([
          "booking_id": "beauty_booking_777",
          "service_type": "haircut_coloring",
          "master_level": "top_master",
          "booking_status": "confirmed"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже пользователь отменяет запись через приложение." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.CANCELLED, "beauty_appointment")
          .withPayload(mapOf(
              "booking_id" to "beauty_booking_777",
              "cancellation_reason" to "client_cancelled",
              "cancellation_source" to "app"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "beauty_appointment", status: .cancelled)
      .withPayload([
          "booking_id": "beauty_booking_777",
          "cancellation_reason": "client_cancelled",
          "cancellation_source": "app"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Или салон через S2S сообщает, что запись была отменена." %}

```java
flowResult(
    productId = "beauty_appointment",
    productOfferId = null,
    status = "cancelled",
    payload = mapOf(
        "booking_id" to "beauty_booking_777",
        "cancellation_reason" to "client_cancelled",
        "decision_source" to "s2s"
    )
)
```

Отправка офферных событий по схеме S2S будет реализована через POST API в одном из ближайших релизов. В текущей документации приведен пример сценария, который демонстрирует ожидаемый способ интеграции.

{% endcut %}

### Subscription / Media {#media}

#### Trial-подписка без отдельного flowStart {#no-flowstart}

{% cut "Пользователь получает push-уведомление: «Попробуйте Premium бесплатно 30 дней»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("premium_trial_30d", "subscription")
          .withProductId("premium_subscription")
          .withBenefitType("trial")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("notification")
                      .withIdentifier("premium_trial_push")
                      .build()
          )
          .withPayload(mapOf(
              "trial_days" to "30",
              "subscription_plan" to "premium_monthly",
              "campaign_id" to "trial_reactivation_2026"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "premium_trial_30d", offerType: "subscription")
      .withProductId("premium_subscription")
      .withBenefitType("trial")
      .withReferrer(OfferReferrer(type: "notification", identifier: "premium_trial_push"))
      .withPayload([
          "trial_days": "30",
          "subscription_plan": "premium_monthly",
          "campaign_id": "trial_reactivation_2026"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь нажимает на push и сразу активирует trial. Отдельного процесса оформления нет, поэтому flowStart можно не отправлять." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "premium_subscription")
          .withProductOfferId("premium_trial_30d")
          .withPayload(mapOf(
              "trial_days" to "30",
              "subscription_plan" to "premium_monthly",
              "activation_source" to "push"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "premium_subscription", status: .success)
      .withProductOfferId("premium_trial_30d")
      .withPayload([
          "trial_days": "30",
          "subscription_plan": "premium_monthly",
          "activation_source": "push"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Видео-платформы и онлайн-кинотеатры {#video}

#### Активация trial-подписки {#trial-activation}

{% cut "Пользователь открывает приложение онлайн-кинотеатра и видит fullscreen paywall: «30 дней Premium бесплатно»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("premium_trial_30d", "subscription")
          .withProductId("premium_subscription")
          .withBenefitType("trial")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("screen")
                      .withIdentifier("premium_paywall")
                      .withScreen("home")
                      .build()
          )
          .withPayload(mapOf(
              "trial_days" to "30",
              "subscription_plan" to "premium_monthly",
              "campaign_id" to "summer_trial_2026"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "premium_trial_30d", offerType: "subscription")
      .withProductId("premium_subscription")
      .withBenefitType("trial")
      .withReferrer(OfferReferrer(type: "screen", identifier: "premium_paywall", screen: "home"))
      .withPayload([
          "trial_days": "30",
          "subscription_plan": "premium_monthly",
          "campaign_id": "summer_trial_2026"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь нажимает «Попробовать бесплатно»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("premium_subscription")
          .withProductOfferId("premium_trial_30d")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "premium_subscription")
      .withProductOfferId("premium_trial_30d")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает тариф." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("premium_subscription", "plan_selection")
          .withProductOfferId("premium_trial_30d")
          .withStepOption("premium_monthly")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "premium_subscription", stepType: "plan_selection")
      .withProductOfferId("premium_trial_30d")
      .withStepOption("premium_monthly")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь добавляет способ оплаты." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("premium_subscription", "payment_method")
          .withProductOfferId("premium_trial_30d")
          .withStepOption("bank_card")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "premium_subscription", stepType: "payment_method")
      .withProductOfferId("premium_trial_30d")
      .withStepOption("bank_card")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пробная подписка успешно активирована." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "premium_subscription")
          .withProductOfferId("premium_trial_30d")
          .withPayload(mapOf(
              "subscription_plan" to "premium_monthly",
              "trial_days" to "30",
              "autorenew_enabled" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "premium_subscription", status: .success)
      .withProductOfferId("premium_trial_30d")
      .withPayload([
          "subscription_plan": "premium_monthly",
          "trial_days": "30",
          "autorenew_enabled": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Аренда фильма {#movie-rental}

{% cut "Пользователь открывает карточку фильма и видит предложение: «Аренда фильма за 299 руб.»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("movie_rental_offer", "digital_good")
          .withProductId("movie_rental")
          .withBenefitType("discount_absolute")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("button")
                      .withIdentifier("rent_movie_button")
                      .withScreen("movie_details")
                      .build()
          )
          .withPayload(mapOf(
              "movie_id" to "movie_987",
              "movie_title" to "SciFi Adventure",
              "rental_price" to "299",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "movie_rental_offer", offerType: "digital_good")
      .withProductId("movie_rental")
      .withBenefitType("discount_absolute")
      .withReferrer(OfferReferrer(type: "button", identifier: "rent_movie_button", screen: "movie_details"))
      .withPayload([
          "movie_id": "movie_987",
          "movie_title": "SciFi Adventure",
          "rental_price": "299",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает оформление аренды." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("movie_rental")
          .withProductOfferId("movie_rental_offer")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "movie_rental")
      .withProductOfferId("movie_rental_offer")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь подтверждает оплату." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("movie_rental", "payment_confirmation")
          .withProductOfferId("movie_rental_offer")
          .withStepOption("bank_card")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "movie_rental", stepType: "payment_confirmation")
      .withProductOfferId("movie_rental_offer")
      .withStepOption("bank_card")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Аренда фильма успешно оформлена." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "movie_rental")
          .withProductOfferId("movie_rental_offer")
          .withPayload(mapOf(
              "movie_id" to "movie_987",
              "rental_duration_hours" to "48",
              "payment_status" to "paid"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "movie_rental", status: .success)
      .withProductOfferId("movie_rental_offer")
      .withPayload([
          "movie_id": "movie_987",
          "rental_duration_hours": "48",
          "payment_status": "paid"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Покупка билета на онлайн-показ фильма {#offline-ticket}

{% cut "Пользователь открывает карточку фильма и видит предложение: «Купить билет на онлайн-показ за 500 рублей»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("online_premiere_ticket_offer", "digital_good")
          .withProductId("online_event_ticket")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("button")
                      .withIdentifier("buy_ticket_button")
                      .withScreen("premiere_details")
                      .build()
          )
          .withPayload(mapOf(
              "event_id" to "premiere_987",
              "event_type" to "online_premiere",
              "content_id" to "movie_987",
              "ticket_price" to "500",
              "currency" to "RUB"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "online_premiere_ticket_offer", offerType: "digital_good")
      .withProductId("online_event_ticket")
      .withReferrer(OfferReferrer(type: "button", identifier: "buy_ticket_button", screen: "premiere_details"))
      .withPayload([
          "event_id": "premiere_987",
          "event_type": "online_premiere",
          "content_id": "movie_987",
          "ticket_price": "500",
          "currency": "RUB"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает покупку билета." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("online_event_ticket")
          .withProductOfferId("online_premiere_ticket_offer")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "online_event_ticket")
      .withProductOfferId("online_premiere_ticket_offer")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает тип билета." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("online_event_ticket", "ticket_type_selection")
          .withProductOfferId("online_premiere_ticket_offer")
          .withStepOption("standard")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "online_event_ticket", stepType: "ticket_type_selection")
      .withProductOfferId("online_premiere_ticket_offer")
      .withStepOption("standard")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь подтверждает оплату." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("online_event_ticket", "payment_confirmation")
          .withProductOfferId("online_premiere_ticket_offer")
          .withStepOption("bank_card")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "online_event_ticket", stepType: "payment_confirmation")
      .withProductOfferId("online_premiere_ticket_offer")
      .withStepOption("bank_card")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Билет успешно куплен." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "online_event_ticket")
          .withProductOfferId("online_premiere_ticket_offer")
          .withPayload(mapOf(
              "event_id" to "premiere_987",
              "content_id" to "movie_987",
              "ticket_type" to "standard",
              "payment_status" to "paid"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "online_event_ticket", status: .success)
      .withProductOfferId("online_premiere_ticket_offer")
      .withPayload([
          "event_id": "premiere_987",
          "content_id": "movie_987",
          "ticket_type": "standard",
          "payment_status": "paid"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Loyalty / Promo {#promo}

#### Получение промокода без сложного оформления {#get-promocode}

{% cut "Пользователь видит popup на экране checkout: «Получите промокод SUMMER20»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("promo_summer_20", "digital_good")
          .withProductId("promo_code")
          .withBenefitType("discount_absolute")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("popup")
                      .withIdentifier("summer_promo_popup")
                      .withScreen("checkout")
                      .build()
          )
          .withPayload(mapOf(
              "promo_code" to "SUMMER20",
              "discount_value" to "20",
              "currency" to "EUR",
              "min_order_value" to "100"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "promo_summer_20", offerType: "digital_good")
      .withProductId("promo_code")
      .withBenefitType("discount_absolute")
      .withReferrer(OfferReferrer(type: "popup", identifier: "summer_promo_popup", screen: "checkout"))
      .withPayload([
          "promo_code": "SUMMER20",
          "discount_value": "20",
          "currency": "EUR",
          "min_order_value": "100"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь нажимает «Получить промокод». Отдельного flow нет, поэтому можно сразу отправить результат." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "promo_code")
          .withProductOfferId("promo_summer_20")
          .withPayload(mapOf("promo_code" to "SUMMER20", "copied_to_clipboard" to "true"))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "promo_code", status: .success)
      .withProductOfferId("promo_summer_20")
      .withPayload(["promo_code": "SUMMER20", "copied_to_clipboard": "true"])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Страхование {#insurance}

#### Оформление страховки с серверным решением (S2S result) {#s2s}

{% cut "Пользователь открывает экран поездки и видит кнопку: «Добавить страховку со скидкой 15%»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("travel_insurance_offer", "insurance")
          .withProductId("travel_insurance")
          .withBenefitType("discount_percentage")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("button")
                      .withIdentifier("trip_details_insurance_button")
                      .withScreen("trip_details")
                      .build()
          )
          .withPayload(mapOf(
              "campaign_id" to "travel_insurance_q2",
              "discount_value" to "15",
              "destination_country" to "Serbia",
              "trip_duration_days" to "7"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "travel_insurance_offer", offerType: "insurance")
      .withProductId("travel_insurance")
      .withBenefitType("discount_percentage")
      .withReferrer(OfferReferrer(type: "button", identifier: "trip_details_insurance_button", screen: "trip_details"))
      .withPayload([
          "campaign_id": "travel_insurance_q2",
          "discount_value": "15",
          "destination_country": "Serbia",
          "trip_duration_days": "7"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь начинает оформление страховки." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("travel_insurance")
          .withProductOfferId("travel_insurance_offer")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "travel_insurance")
      .withProductOfferId("travel_insurance_offer")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь выбирает покрытие." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("travel_insurance", "coverage_selection")
          .withProductOfferId("travel_insurance_offer")
          .withStepOption("standard")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "travel_insurance", stepType: "coverage_selection")
      .withProductOfferId("travel_insurance_offer")
      .withStepOption("standard")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь вводит данные." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("travel_insurance", "traveler_details")
          .withProductOfferId("travel_insurance_offer")
          .withStepOption("manual_input")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "travel_insurance", stepType: "traveler_details")
      .withProductOfferId("travel_insurance_offer")
      .withStepOption("manual_input")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Заявка отправлена на проверку." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.PENDING, "travel_insurance")
          .withProductOfferId("travel_insurance_offer")
          .withPayload(mapOf(
              "application_id" to "insurance_app_987",
              "coverage_type" to "standard",
              "destination_country" to "Serbia"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "travel_insurance", status: .pending)
      .withProductOfferId("travel_insurance_offer")
      .withPayload([
          "application_id": "insurance_app_987",
          "coverage_type": "standard",
          "destination_country": "Serbia"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Позже страховая присылает финальный результат через S2S." %}

```java
flowResult(
    productId = "travel_insurance",
    productOfferId = "travel_insurance_offer",
    status = "success",
    payload = mapOf(
        "application_id" to "insurance_app_987",
        "policy_id" to "policy_555",
        "decision_source" to "s2s"
    )
)
```

{% endcut %}

### Gaming {#gaming}

#### Покупка игрового bundle {#bundle}

{% cut "Пользователь открывает игровой магазин и видит баннер: «Starter bundle: монеты + гемы + бонусный предмет»." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.offerShown("starter_bundle_offer", "bundle")
          .withProductId("starter_bundle")
          .withBenefitType("bundle_extra")
          .withReferrer(
                  OfferReferrer.newBuilder()
                      .withType("banner")
                      .withIdentifier("store_starter_bundle_banner")
                      .withScreen("game_store")
                      .build()
          )
          .withPayload(mapOf(
              "bundle_id" to "starter_bundle",
              "bonus_items" to "coins,gems,sword_skin",
              "price_tier" to "low",
              "campaign_id" to "starter_pack_campaign"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.offerShown(productOfferId: "starter_bundle_offer", offerType: "bundle")
      .withProductId("starter_bundle")
      .withBenefitType("bundle_extra")
      .withReferrer(OfferReferrer(type: "banner", identifier: "store_starter_bundle_banner", screen: "game_store"))
      .withPayload([
          "bundle_id": "starter_bundle",
          "bonus_items": "coins",
          "price_tier": "low",
          "campaign_id": "starter_pack_campaign"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь открывает покупку bundle." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("starter_bundle")
          .withProductOfferId("starter_bundle_offer")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "starter_bundle")
      .withProductOfferId("starter_bundle_offer")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь подтверждает покупку." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("starter_bundle", "purchase_confirmation")
          .withProductOfferId("starter_bundle_offer")
          .withStepOption("confirmed")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "starter_bundle", stepType: "purchase_confirmation")
      .withProductOfferId("starter_bundle_offer")
      .withStepOption("confirmed")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Покупка успешно завершена." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "starter_bundle")
          .withProductOfferId("starter_bundle_offer")
          .withPayload(mapOf(
              "bundle_id" to "starter_bundle",
              "payment_status" to "paid",
              "bonus_items_granted" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "starter_bundle", status: .success)
      .withProductOfferId("starter_bundle_offer")
      .withPayload([
          "bundle_id": "starter_bundle",
          "payment_status": "paid",
          "bonus_items_granted": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

### Опросы и оценка товара {#surveys}

#### Одностраничный опрос после покупки {#one-page-survey}

{% cut "Пользователь завершил покупку и видит экран: «Оцените товар». Оффера нет, flowStart можно не отправлять." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "product_review")
          .withPayload(mapOf(
              "survey_id" to "post_purchase_review",
              "product_id" to "sku_12345",
              "rating" to "5",
              "has_comment" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "product_review", status: .success)
      .withPayload([
          "survey_id": "post_purchase_review",
          "product_id": "sku_12345",
          "rating": "5",
          "has_comment": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

#### Многошаговый опрос после покупки {#many-step-survey}

{% cut "Пользователь завершил покупку и видит экран: «Помогите нам улучшить рекомендации — ответьте на несколько вопросов». Оффера нет, но есть многошаговый flow." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStart("product_review_survey")
          .withPayload(mapOf(
              "survey_id" to "post_purchase_review",
              "product_id" to "sku_12345",
              "entry_point" to "order_success_screen"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStart(productId: "product_review_survey")
      .withPayload([
          "survey_id": "post_purchase_review",
          "product_id": "sku_12345",
          "entry_point": "order_success_screen"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь ставит оценку товару." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("product_review_survey", "rating")
          .withStepOption("5")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "product_review_survey", stepType: "rating")
      .withStepOption("5")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь отвечает, что понравилось." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("product_review_survey", "positive_feedback")
          .withStepOption("quality")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowStep(productId: "product_review_survey", stepType: "positive_feedback")
      .withStepOption("quality")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь переходит к шагу комментария, но закрывает экран. Последний flowStep перед flowResult(cancelled) поможет понять, где произошёл отказ." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowStepForProduct("product_review_survey", "comment")
          .withStepOption("optional_text")
          .build()
  )
  ```

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.CANCELLED, "product_review_survey")
          .withPayload(mapOf(
              "survey_id" to "post_purchase_review",
              "product_id" to "sku_12345",
              "last_completed_step" to "comment"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let commentStep = ProductFlowEvents.flowStep(productId: "product_review_survey", stepType: "comment")
      .withStepOption("optional_text")
      .build()

  AppMetrica.report(event: commentStep)
  ```

  ```swift translate=no
  let result = ProductFlowEvents.flowResult(productId: "product_review_survey", status: .cancelled)
      .withPayload([
          "survey_id": "post_purchase_review",
          "product_id": "sku_12345",
          "last_completed_step": "comment"
      ])
      .build()

  AppMetrica.report(event: result)
  ```

{% endlist %}

{% endcut %}

{% cut "Пользователь прошёл опрос до конца." %}

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "product_review_survey")
          .withPayload(mapOf(
              "survey_id" to "post_purchase_review",
              "product_id" to "sku_12345",
              "rating" to "5",
              "positive_feedback" to "quality",
              "has_comment" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "product_review_survey", status: .success)
      .withPayload([
          "survey_id": "post_purchase_review",
          "product_id": "sku_12345",
          "rating": "5",
          "positive_feedback": "quality",
          "has_comment": "true"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

## Как читать сценарии разметки {#how-to-read}

`offerShown` 

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

`flowStart` 

:   Отправляется, если у пользователя есть отдельный старт оформления, активации или многошагового сценария.

`flowStep` 

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

`flowResult` 

:   Отправляется всегда, когда известен итог сценария.

Если результат известен не сразу, сначала отправляется промежуточный результат:

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.PENDING, "...")
          .withProductOfferId("...")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "...", status: .pending)
      .withProductOfferId("...")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

А позже через S2S отправляется финальный результат:

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.SUCCESS, "...")
          .withProductOfferId("...")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "...", status: .success)
      .withProductOfferId("...")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

или

{% list tabs %}

- Kotlin

  ```kotlin translate=no
  AppMetrica.reportEvent(
      ProductFlowEvent.flowResultForProduct(ProductFlowStatus.DECLINED, "...")
          .withProductOfferId("...")
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "...", status: .declined)
      .withProductOfferId("...")
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

## Рекомендуемые статусы {#recommended-statuses}

#|
|| **Статус** | **Значение** ||
|| `success` | Успешное завершение ||
|| `declined` | Отклонено третьей стороной ||
|| `pending` | Ожидает решения ||
|| `cancelled` | Пользователь отменил ||
|| `expired` | Оффер или сессия истекли ||
|| `fail` | Техническая ошибка ||
|#

## Как понять, подходит ли вам новая разметка событий {#how-to}

Рекомендуем данную схему разметки, если в вашем приложении есть:

- офферы;
- карточки предложений;
- onboarding-сценарии;
- сценарии оформления заказа;
- сценарии оформления финансовых продуктов;
- сценарии бронирования;
- сценарии оформления подписки;
- сценарии апгрейда тарифа или продукта;
- сценарии одобрения;
- аналитика воронок.

Схема будет особенно полезна, если в текущей реализации:

- все события отправляются как `custom events`;
- события трудно сопоставлять друг с другом;
- одинаковые шаги называются по-разному;
- сложно анализировать конверсию между этапами;
- нет единого подхода к продуктовой воронке.

## Переход с custom events {#custom-events}

Если вы уже используете `custom events`, переход может быть постепенным: новые события можно отправлять параллельно с существующими кастомными событиями.

Новые типовые события не расходуют лимит `custom events` и позволяют проверить корректность интеграции и полноту данных перед миграцией.

После проверки отправку соответствующих `custom events` можно отключить.

<!-- source: ru/_includes/feedback-button.md -->
Если вы не нашли ответ на свой вопрос, то вы можете задать его через форму обратной связи. Пожалуйста, опишите возникшую проблему как можно подробнее. Если возможно, приложите скриншот.

<a href="../troubleshooting/feedback-new">
  <span class="button">Написать в службу поддержки</span>
</a>

<a href="../troubleshooting/feedback-docs">
  <span class="button">Предложить улучшение для документации</span>
</a>
<!-- endsource: ru/_includes/feedback-button.md -->
