---
metadata:
  - name: generator
    content: Diplodoc Platform v5.63.4
alternate:
  - https://appmetrica.yandex.com/docs/en/data-collection/offers.md
  - https://appmetrica.yandex.com/docs/ru/data-collection/offers.md
  - https://appmetrica.yandex.com/docs/zh/data-collection/offers.md
  - href: https://appmetrica.yandex.com/docs/zh/data-collection/offers.md
    type: text/markdown
    title: Markdown version
  - href: https://appmetrica.yandex.com/docs/zh/llms.txt?revision=r21698989
    rel: describedby
---
> **Documentation Index:** Fetch the complete configuration index at https://appmetrica.yandex.com/docs/zh/llms.txt?revision=r21698989

# 在产品场景中提供事件

关于产品流程的文档，包含SDK集成示例：

- **安卓** — [产品场景和推广事件](https://appmetrica.yandex.com/docs/zh/sdk/android/analytics/android-product-flow.md);
- **iOS** — [产品场景和推广事件](https://appmetrica.yandex.com/docs/zh/sdk/ios/analytics/ios-product-flow.md).

## 关于该方法的更多信息 {#details}

**产品流程** 是一种处理应用中标准 AppMetrica 事件的新方案，适用于包含优惠、购买、申请以及多步骤产品和服务订购场景的应用。

这种方法有助于为以下实体和场景标准化分析：

- product offers;
- marketing offers;
- 购买商品和服务；
- user funnels;
- ordering steps;
- 应用程序和审批结果；
- 异步 S2S 结果。

我们建议为以下类型的应用使用产品流程（Product Flow）方法：

- banks;
- 保险服务；
- telecom apps;
- 预订和旅行服务；
- subscription services;
- 送货服务；
- marketplaces;
- 游戏应用；
- 任何具有产品场景、购买和漏斗分析的应用。

{% note tip "不消耗自定义事件和DSA限制" %}

新的标准事件不计入以下限制：

- `自定义事件`;
- `数据流 API`.

这让您可以：

- 逐步采用新的标记方案；
- 发送更多产品场景和步骤；
- 在不消耗自定义事件和 DSA 限额的情况下，构建详细的漏斗和分析。

{% endnote %}

## 这种方法解决什么问题 {#problem-statement}

目前，许多应用使用`自定义事件`来发送关于以下实体和场景的分析数据：

- offers;
- applications;
- product scenarios;
- onboarding scenarios;
- 订单下单场景;
- approval scenarios.

这种方法会导致以下问题：

- 相同的场景标记方式不同；
- 创建标准报告很困难；
- 分析数据在团队间传递较为困难；
- 自动漏斗构建是不可能的；
- 很难比较广告推送和场景的效果。

产品场景和奖励事件架构提供了一种统一的方法来标注关键阶段：

- offer display;
- 开始订购;
- 中间步骤；
- 最终结果。

## 主要事件 {#main-events}

交互方案基于四个主要事件：

#|
|| **事件** | **含义** ||
|| `offerShown` | 用户看到了一个倡议或提议 ||
|| `flowStart` | 用户开始订购产品 ||
|| `flowStep` | 一个中间排序步骤 ||
|| `flowResult` | 最终结果 ||
|#

## 标记场景 {#scenarios}

此部分展示了不同行业的完整用户场景。

{% note tip "场景示例" %}

本文档中的所有场景都是**示例**标记，展示了可能的集成选项。

事件名称、参数、场景步骤和负载结构可以根据您的应用和用户场景特点进行调整。

{% endnote %}

每个场景描述：

- 用户在应用中看到和做的事情；
- 哪些事件需要发送；
- when `offerShown` 可以省略；
- when `flowStart` 可以省略；
- 如何通过 `flowStep` 传递中间步骤;
- 如何通过`flowResult`传递最终结果；
- 如何使用 `payload`、`referrer` 和 `stepOption`；
- 如何后续通过 S2S 传递结果。

### 银行和金融科技 {#banks}

#### 通过个人优惠贷款：优惠 → 申请 → 待处理 → S2S 结果 {#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(
    产品ID = "personal_loan",
    产品报价ID = null,
    状态 = "已拒绝",
    负载 = 映射为(
        "申请编号" to "loan_app_67890",
        "拒绝原因" to "scoring_rejected",
        "决策来源" to "s2s"
    )
)
```

通过S2S方案发送推广事件将在未来的某个版本中通过POST API实现。 当前文档提供了一个示例脚本，演示了预期的集成方法。

{% endcut %}


### Telecom {#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 GB，14天，1500 RUB”。" %}

{% 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()
          )
          .withPrice(OfferPrice(1500.0, "RUB"))
          .withPayload(mapOf(
              "region" to "Europe",
              "traffic_limit_gb" to "10",
              "duration_days" to "14"
          ))
          .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"))
      .withPrice(OfferPrice(amount: 1500.0, unit: "RUB"))
      .withPayload([
          "region": "Europe",
          "traffic_limit_gb": "10",
          "duration_days": "14"
      ])
      .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-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()
          )
          .withPrice(OfferPrice(1990.0, "RUB"))
          .withPayload(mapOf(
              "current_tariff" to "smart_m",
              "target_tariff" to "premium_unlimited"
          ))
          .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"))
      .withPrice(OfferPrice(amount: 1990.0, unit: "RUB"))
      .withPayload([
          "current_tariff": "smart_m",
          "target_tariff": "premium_unlimited"
      ])
      .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 Mbps，每月990 RUB”。" %}

{% 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()
          )
          .withPrice(OfferPrice(990.0, "RUB"))
          .withPayload(mapOf(
              "speed_mbps" to "500",
              "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"))
      .withPrice(OfferPrice(amount: 990.0, unit: "RUB"))
      .withPayload([
          "speed_mbps": "500",
          "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 = "成功",
    payload = mapOf(
        "request_id" to "internet_request_555",
        "installation_status" to "已完成",
        "technician_visit" to "已完成",
        "tariff_id" to "home_500",
        "tariff_status" to "活跃",
        "decision_source" to "s2s"
    )
)
```

通过S2S方案发送推广事件将在未来的某个版本中通过POST API实现。 当前文档提供了一个示例脚本，演示了预期的集成方法。

{% endcut %}

### 旅行 / 预订 {#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()
          )
          .withPrice(OfferPrice(20000.0, "RUB"))
          .withPayload(mapOf(
              "campaign_id" to "may_hotels_sale",
              "hotel_id" to "hotel_987",
              "city" to "Belgrade",
              "discount_value" to "20",
              "original_price" to "25000",
              "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"))
      .withPrice(OfferPrice(amount: 20000.0, unit: "RUB"))
      .withPayload([
          "campaign_id": "may_hotels_sale",
          "hotel_id": "hotel_987",
          "city": "Belgrade",
          "discount_value": "20",
          "original_price": "25000",
          "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")
          .withPrice(OfferPrice(20000.0, "RUB"))
          .withPayload(mapOf(
              "hotel_id" to "hotel_987",
              "city" to "Belgrade",
              "nights" to "3",
              "guests" to "2",
              "original_price" to "25000",
              "discount_applied" to "true"
          ))
          .build()
  )
  ```

- Swift

  ```swift translate=no
  let event = ProductFlowEvents.flowResult(productId: "hotel_booking", status: .success)
      .withProductOfferId("hotel_discount_may")
      .withPrice(OfferPrice(amount: 20000.0, unit: "RUB"))
      .withPayload([
          "hotel_id": "hotel_987",
          "city": "Belgrade",
          "nights": "3",
          "guests": "2",
          "original_price": "25000",
          "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 "用户打开七嘟医疗App的主屏幕，看到一张卡片：“预约检查，享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}

#### SPA预订（预付款） {#spa-registry}

{% cut "用户打开SPA沙龙App，看到一个优惠刊登：“在线支付享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()
          )
          .withPrice(OfferPrice(9600.0, "RUB"))
          .withPayload(mapOf(
              "service_type" to "spa_program",
              "discount_value" to "20",
              "original_price" to "12000",
              "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"))
      .withPrice(OfferPrice(amount: 9600.0, unit: "RUB"))
      .withPayload([
          "service_type": "spa_program",
          "discount_value": "20",
          "original_price": "12000",
          "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")
          .withPrice(OfferPrice(9600.0, "RUB"))
          .withPayload(mapOf(
              "booking_id" to "spa_booking_555",
              "service_type" to "relax_spa_program",
              "prepayment_amount" to "3000",
              "remaining_amount" to "6600",
              "payment_status" to "partially_paid"
          ))
          .build()
  )
  ```

- Swift

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

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "之后，SPA沙龙通过S2S确认用户确实参加了治疗。" %}

```java
flowResult(
    productId = "spa_booking",
    productOfferId = "spa_weekend_offer",
    status = "成功",
    price = OfferPrice(6600.0, "RUB"),
    payload = mapOf(
        "booking_id" to "spa_booking_555",
        "visit_status" to "已完成",
        "service_type" to "放松水疗项目",
        "decision_source" to "s2s"
    )
)
```

通过S2S方案发送推荐事件将在未来的某个版本中通过POST API实现。 当前文档提供了一个示例脚本，演示了预期的集成方法。

{% endcut %}

#### 美甲预约 {#manicure}

{% cut "用户打开沙龙App，看到一个优惠券：“首次访问折扣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 = "已取消",
    payload = mapOf(
        "booking_id" to "beauty_booking_777",
        "cancellation_reason" to "客户取消",
        "decision_source" to "s2s"
    )
)
```

通过S2S方案发送推广事件将在未来的某个版本中通过POST API实现。 当前文档提供了一个示例脚本，演示了预期的集成方法。

{% endcut %}

### Subscription / Media {#media}

#### 试用订阅无需单独的流程启动 {#no-flowstart}

{% cut "用户收到推送通知：“免费试用 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 "用户点击推送，立即激活试用。 没有单独的排序过程，因此可以省略 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-activation}

{% cut "用户打开在线电影应用，看到全屏付费墙：“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 RUB”。" %}

{% 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()
          )
          .withPrice(OfferPrice(299.0, "RUB"))
          .withPayload(mapOf(
              "movie_id" to "movie_987",
              "movie_title" to "SciFi Adventure"
          ))
          .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"))
      .withPrice(OfferPrice(amount: 299.0, unit: "RUB"))
      .withPayload([
          "movie_id": "movie_987",
          "movie_title": "SciFi Adventure"
      ])
      .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 RUB”。" %}

{% 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()
          )
          .withPrice(OfferPrice(500.0, "RUB"))
          .withPayload(mapOf(
              "event_id" to "premiere_987",
              "event_type" to "online_premiere",
              "content_id" to "movie_987"
          ))
          .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"))
      .withPrice(OfferPrice(amount: 500.0, unit: "RUB"))
      .withPayload([
          "event_id": "premiere_987",
          "event_type": "online_premiere",
          "content_id": "movie_987"
      ])
      .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 %}

### 忠诚度 / 促销 {#promo}

#### 获取促销码而不需要复杂流程 {#get-promocode}

{% cut "用户在结算页面看到一个弹窗：“获取促销码 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 "用户点击“获取促销码”。 没有单独的流程，因此结果可以立即发送。" %}

{% 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 结果） {#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"
    )
)
```

通过S2S方案发送推广事件将在未来的某个版本中通过POST API实现。 当前文档提供了一个示例脚本，演示了预期的集成方法。

{% endcut %}

### Gaming {#gaming}

#### 购买游戏套餐 {#bundle}

{% cut "用户打开游戏商店，看到一个广告横幅：“初始包：硬币 + 宝石 + 额外物品”。" %}

{% 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()
          )
          .withPrice(OfferPrice(4.99, "USD"))
          .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"))
      .withPrice(OfferPrice(amount: 4.99, unit: "USD"))
      .withPayload([
          "bundle_id": "starter_bundle",
          "bonus_items": "coins",
          "price_tier": "low",
          "campaign_id": "starter_pack_campaign"
      ])
      .build()

  AppMetrica.report(event: event)
  ```

{% endlist %}

{% endcut %}

{% cut "用户打开套餐购买。" %}

{% 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")
          .withPrice(OfferPrice(4.99, "USD"))
          .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")
      .withPrice(OfferPrice(amount: 4.99, unit: "USD"))
      .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 "用户已完成购买，看到屏幕提示：“帮助我们改进推荐 — 回答几个问题”。 没有券，但有多步流程。" %}

{% 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` 

:   若用户实际看到了推广内容（如横幅广告、弹窗、推送通知、按钮、卡片或其他推广模块），则会发送。

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

#|
|| **状态** | **含义** ||
|| `成功` | 成功完成 ||
|| `拒绝` | 被第三方拒绝 ||
|| `等待` | 等待决定 ||
|| `已取消` | 已被用户取消 ||
|| `已过期` | 优惠或会话已过期 ||
|| `失败` | 技术错误 ||
|#

## 如何判断新事件标记是否适合您 {#how-to}

我们建议使用此标记方案，如果您的应用有：

- offers;
- proposal cards;
- onboarding scenarios;
- 订单下单场景;
- 金融产品应用场景；
- booking scenarios;
- subscription scenarios;
- 升级套餐或产品的场景；
- approval scenarios;
- funnel analytics.

该架构在当前实现中会尤其有用：

- 所有事件都作为`自定义事件`发送；
- 事件难以相互关联；
- 相同的步骤名称不同；
- 阶段间转换分析较困难；
- 对产品漏斗没有统一的方法。

## 从自定义事件迁移 {#custom-events}

如果您已经使用`自定义事件`，可以逐步迁移：新的事件可以与现有的自定义事件并行发送。

新的标准事件不会占用`自定义事件`的限制，并允许您在迁移前验证集成的正确性和数据的完整性。

验证后，可以禁用相应的`自定义事件`。

<!-- source: zh/_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: zh/_includes/feedback-button.md -->
