在 React Native SDK 中向流程传递数据

自定义标签是一个从应用中获取值的自定义变量。在变量设置中选择 Value comes from outside the app 后,应用即可通过 Adapty SDK 设置其值。例如,某个文本元素包含”Coins:“和一个自定义标签,若应用为该标签传入”120”,用户看到的内容便是”Coins: 120”。

开始之前

您需要使用 Adapty SDK v4 或更高版本。v4 之前的版本不支持显示流程。

向流程添加自定义标签

要在流程中显示应用的数据,请在编辑工具中设置自定义标签:

  1. 为应用传递的每个值创建一个自定义标签。

    Create variable form with a name, a description, the String value type, and an initial value
  2. 将每个标签插入文本元素。

  3. 记录每个标签的完整名称,包括其所属分组。应用代码在传递对应值时需使用该名称。例如,若 user 分组中包含 streak 标签,则该标签的完整名称为 user.streak。

    Custom tab of the Add variable dropdown with the streak tag in the user group

传递自定义标签值

在视图参数的 customTags 字段中传入你的应用数据,格式为对象。使用 AdaptyFlowView 组件时,通过其 params prop 传入;使用 createFlowView 时,通过其第二个参数传入。

  • 每个键是自定义标签的完整名称,例如 user.streak。
  • 每个值是用户在标签位置看到的字符串。
  • 每个值必须是人类可读的格式,例如 “1,250” 而非 “1250.0”。Adapty 不会对其进行格式化或翻译。

createFlowView 在创建视图时只读取一次参数值,因此这些值在流程打开期间不会发生变化。如果已挂载的 AdaptyFlowView 的 params 发生变化,组件会重新创建流程视图,流程将从第一屏重新开始。请在流程打开期间保持 params 不变。

要测试自定义标签,请在添加设置其值的代码后,在应用中打开流程。编辑工具画布和在设备上预览只显示初始值:Adapty 移动应用不会设置自定义标签的值。

如果你的应用已经为旧版付费墙编辑工具的付费墙设置了自定义标签值,请了解流程中的自定义标签与旧版有何不同。

用户在没有值时看到的内容

在以下情况下,用户会看到自定义标签的初始值作为备用内容:

  • 您的应用未为该标签传递任何值。
  • 用户尚未将应用更新到能传递该值的版本。
  • 应用代码中的名称与标签的完整名称不匹配,包括字母大小写。
  • 同一文本元素中的另一个自定义标签没有值。此时该文本元素中的每个自定义标签都会显示其初始值。

如需在标签位置不显示任何内容,请传入空字符串。Adapty 将空字符串视为有效值,因此不会显示备用内容。

示例:根据用户引导答案显示 BMI

流程可以收集用户的答案,自定义标签可以显示来自你应用的值。将两者结合,即可向用户展示由你的应用根据其答案计算得出的结果,例如得分、推荐套餐或健康指标:

  1. 流程收集答案并将其发送给你的应用。
  2. 你的应用计算结果。
  3. 你的应用将结果作为自定义标签值传递给下一个流程。

在此示例中,一个用户引导流程收集用户的体重和身高。当用户在最后一屏关闭用户引导流程后,你的应用会计算其身体质量指数(BMI)。然后它会打开一个付费墙流程,显示该 BMI 值。

设置流程

  1. 创建两个流程:一个用于收集用户体重和身高的用户引导流程,以及一个展示 BMI 的付费墙流程。

  2. 在用户引导流程中添加两个 Number 输入框:

    • 一个用于输入体重(千克),Element ID 设为 weight。
    • 一个用于输入身高(厘米),Element ID 设为 height。

    两个输入框的 Format 均设为 Integer。输入框会将用户输入的内容原样以文本形式发送,示例代码对 “70.5” 和 “70,5” 的解析结果并不相同。整数没有小数分隔符,因此在任何语言环境下代码的解析结果都一致。

  3. 为确保您的应用能收到两个值,请在用户引导流程的最后添加一个不含输入框的屏幕。在该屏幕上添加一个带有 Close flow 操作的按钮。输入框会在失去焦点或用户切换到其他屏幕时发送其值,而 Close flow 操作不会触发发送。示例代码只有在用户到达最后一屏时才会打开付费墙。

  4. 在付费墙流程中,创建一个名为 bmi 的自定义标签。在 Initial value 字段中输入一个破折号(—)。如果您的应用未传入 BMI 值,用户将看到该破折号。

  5. 在付费墙流程中添加一个文本元素,内容为”Your BMI:“。在这些文字后面插入 bmi 自定义标签。

  6. 将用户引导流程添加到某个版位,例如 onboarding。将付费墙流程添加到 ID 为 bmi_paywall 的版位。将 BMI 传递给付费墙中的代码通过此 ID 获取付费墙。

将 BMI 传递给付费墙

从用户引导流程的 flow_user_input 事件中收集体重和身高,具体方式参见处理流程数据。要判断用户是否到达了最后一个屏幕,可监听 flow_screen_showed 事件中 is_last_screen 为 true 的情况,具体方式参见追踪流程屏幕浏览。当用户在该屏幕后关闭用户引导流程时,计算 BMI,然后创建付费墙的视图,并将 BMI 作为 bmi 自定义标签传入。

在 onboardingView(即 createFlowView 为用户引导流程返回的视图)上注册以下处理程序。AdaptyFlowView 组件没有 onDisappeared 处理程序,因此此示例不适用于该组件。


const bodyAnswers = {};
let reachedLastScreen = false;

const unsubscribe = onboardingView.setEventHandlers({
  onAnalytics(name, params) {
    if (name === 'flow_screen_showed' && params.is_last_screen) {
      reachedLastScreen = true;
    }
    if (name === 'flow_user_input' && typeof params.value === 'string') {
      bodyAnswers[params.element_id] = params.value;
    }
    return false; // keep the flow open
  },
  onDisappeared() {
    // Number inputs send their values as strings.
    const weight = Number(bodyAnswers.weight);
    const height = Number(bodyAnswers.height);
    const finished = reachedLastScreen;
    delete bodyAnswers.weight;
    delete bodyAnswers.height;
    reachedLastScreen = false;

    if (finished && weight > 0 && height > 0) {
      const heightInMeters = height / 100;
      const bmi = weight / (heightInMeters * heightInMeters);
      showBmiPaywall(bmi.toLocaleString(undefined, { maximumFractionDigits: 1 }));
    }
    return false;
  },
});

async function showBmiPaywall(bmi) {
  try {
    const flow = await adapty.getFlow('bmi_paywall');
    const view = await createFlowView(flow, { customTags: { 'bmi': bmi } });
    await view.present();
  } catch (error) {
    // handle the error
  }
}

toLocaleString 会使用用户所在地区的小数分隔符:英语为 “22.7”,德语为 “22,7”。

将 BMI 保存到用户画像

要根据用户的 BMI 显示不同的流程,请将其作为自定义属性保存到用户画像中。在 Adapty 看板中,创建一个 Number 类型的自定义属性,键名设为 bmi。然后为每个流程设置基于该属性构建的目标受众。

在计算 bmi 的那行代码之后,在 onDisappeared 中调用 updateProfile 方法。传入数字本身,而不是格式化后的字符串,这样市场细分才能将 BMI 与阈值进行比较。由于 onDisappeared 不能是 async,请使用 .catch 而非 await 来处理结果:

adapty
  .updateProfile({ codableCustomAttributes: { bmi } })
  .catch((error) => {
    // handle the error
  });