使用 A/B Testing 来创建消息传递实验

如果您要向现有用户发布消息或者开始新的营销活动,您应确保自己的做法正确无误。A/B Testing 可以帮助您在所选的细分用户群中测试各种消息变体,以找出理想的措辞和呈现方式。无论您的目标是为产品或服务留住更多客户,还是要提高产品或服务的转化率,A/B Testing 都可以执行统计分析,确定消息变体在实现您所选目标方面的效果是否超过基准。

如需利用基准来对功能变体进行 A/B 测试,请执行以下操作:

  1. 创建实验。
  2. 在测试设备上验证您的实验。
  3. 管理实验。

创建实验

使用 Notifications Composer 的实验可用于评估一条通知消息的多个变体。

  1. 登录 Firebase 控制台,验证是否已在您的项目中启用 Google Analytics(分析),以便实验可以访问 Analytics 数据。

    如果您在创建项目时没有启用 Google Analytics(分析),可以在集成标签页中启用。在 Firebase 控制台中点击 > 项目设置即可访问此标签页。

  2. Firebase 控制台导航栏的吸引部分,点击 A/B Testing

  3. 点击创建实验,然后在系统提示您选择要试验的服务时选择 Notifications

  4. 输入实验的名称说明(可选),然后点击下一步

  5. 填写定位字段,首先选择要开展实验的应用。您还可以选择下列一个或多个选项来定位一部分用户,让这些用户参与您的实验:

    • 版本:应用的一个或多个版本
    • 用户受众群体:用于选择哪些用户可参与实验的 Analytics 受众群体
    • 用户属性:用于选择哪些用户可参与实验的一个或多个 Analytics 用户属性
    • 国家/地区:用于选择哪些用户可参与实验的一个或多个国家或地区
    • 设备语言:用于选择哪些用户可参与实验的一种或多种语言和语言区域
    • 首次打开:根据用户首次打开您的应用的时间来定位用户
    • 上次应用互动:根据用户上次与您的应用互动的时间来定位用户
  6. 设置目标用户百分比:选择应用的用户群百分比,以指定与您在目标用户下设置的条件匹配的用户中,您要将其中多少比例的用户平均分配到实验中的基准和一个或多个变体。此值可以为介于 0.01% 到 100% 之间的任何百分比。 系统会为每个实验(包括复制的实验)的用户随机重新分配百分比。

  7. 变体部分的输入消息文字字段中输入要发送给基准组的消息。如果不打算向基准组发送任何消息,请将此字段留空。

  8. (可选)如需在实验中添加多个变体,请点击添加变体。默认情况下,实验有一个基准和一个变体。

  9. (可选)为实验中每个变体输入名称,以替换变体 A变体 B 等名称。

  10. 为您的实验定义目标指标,以便在评估实验变体时与下拉列表中提供的其他所需指标一起使用。这些指标包括内置目标(互动、购买量、收入和留存率等),Analytics 转化事件和其他 Analytics 事件。

  11. 为您的消息选择选项:

    • 发送日期:选择立即发送在保存时立即启动实验,或者选择预定发送指定在将来某个时间启动实验。
    • 高级选项:如需为实验中包含的所有通知选择高级选项,请展开高级选项,然后更改列出的任何消息选项。
  12. 点击查看以保存实验。

每个项目最多可以有 300 个实验,最多包括 24 个正在运行的实验,其余为实验草稿或已完成的实验。

在测试设备上验证您的实验

对于每个 Firebase 安装,您都可以检索与其关联的 FCM 注册令牌。您可以使用此令牌在安装了您的应用的测试设备上测试特定实验变体。如需在测试设备上验证您的实验,请执行以下操作:

  1. 获取 FCM 注册令牌,如下所示:

    Swift

    Messaging.messaging().token { token, error in
      if let error = error {
        print("Error fetching FCM registration token: \(error)")
      } else if let token = token {
        print("FCM registration token: \(token)")
        self.fcmRegTokenMessage.text  = "Remote FCM registration token: \(token)"
      }
    }
    

    Objective-C

    [[FIRMessaging messaging] tokenWithCompletion:^(NSString *token, NSError *error) {
      if (error != nil) {
        NSLog(@"Error getting FCM registration token: %@", error);
      } else {
        NSLog(@"FCM registration token: %@", token);
        self.fcmRegTokenMessage.text = token;
      }
    }];
    

    Java

    FirebaseMessaging.getInstance().getToken()
        .addOnCompleteListener(new OnCompleteListener<String>() {
            @Override
            public void onComplete(@NonNull Task<String> task) {
              if (!task.isSuccessful()) {
                Log.w(TAG, "Fetching FCM registration token failed", task.getException());
                return;
              }
    
              // Get new FCM registration token
              String token = task.getResult();
    
              // Log and toast
              String msg = getString(R.string.msg_token_fmt, token);
              Log.d(TAG, msg);
              Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });

    Kotlin+KTX

    FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
        if (!task.isSuccessful) {
            Log.w(TAG, "Fetching FCM registration token failed", task.exception)
            return@OnCompleteListener
        }
    
        // Get new FCM registration token
        val token = task.result
    
        // Log and toast
        val msg = getString(R.string.msg_token_fmt, token)
        Log.d(TAG, msg)
        Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
    })

    C++

    firebase::InitResult init_result;
    auto* installations_object = firebase::installations::Installations::GetInstance(
        firebase::App::GetInstance(), &init_result);
    installations_object->GetToken().OnCompletion(
        [](const firebase::Future& future) {
          if (future.status() == kFutureStatusComplete &&
              future.error() == firebase::installations::kErrorNone) {
            printf("Installations Auth Token %s\n", future.result()->c_str());
          }
        });
        

    Unity

    Firebase.Messaging.FirebaseMessaging.DefaultInstance.GetTokenAsync().ContinueWith(
      task => {
        if (!(task.IsCanceled || task.IsFaulted) && task.IsCompleted) {
          UnityEngine.Debug.Log(System.String.Format("FCM registration token {0}", task.Result));
        }
      });
    
  2. Firebase 控制台导航栏上,点击 A/B Testing
  3. 点击草稿,将鼠标光标悬停在实验上,点击上下文菜单 (),然后点击管理测试设备
  4. 输入测试设备的 FCM 令牌,并选择要发送到该测试设备的实验变体。
  5. 运行应用,并确认测试设备正在接收所选变体。

管理实验

无论您是使用 Remote Config、Notifications Composer 还是 Firebase In-App Messaging 来创建实验,接下来您都可以验证并启动实验,在实验运行时监控实验,并增加参与正在运行的实验的用户数量。

实验完成后,您可以记录胜出变体的设置,然后向所有用户发布这些设置。或者,您可以运行另一个实验。

启动实验

  1. Firebase 控制台导航菜单的吸引部分中,点击 A/B Testing
  2. 依次点击草稿和实验标题。
  3. 如需验证您的应用是否有将会参与实验的用户,请展开草稿详情,然后检查定位和分布部分中是否存在大于 0% 的数字(例如,1% 的用户符合条件)。
  4. 如需更改实验,请点击修改
  5. 如需启动实验,请点击启动实验。一个项目最多可以同时运行 24 个实验。

监控实验

在实验运行了一段时间后,您可以查看实验进度,并了解到目前为止,在参与实验的用户中效果如何。

  1. Firebase 控制台导航菜单的吸引部分中,点击 A/B Testing
  2. 点击正在运行,然后点击或搜索实验标题。在此页面上,您可以查看有关正在运行的实验的各种实测和建模统计信息,包括以下内容:

    • 与基准的偏差百分比:根据给定变体与基准的比较结果来衡量某个指标的提高幅度。计算方法是将相应变体的值范围与基准组合的值范围进行比较。
    • 胜过基准组合的概率:对于所选指标,给定变体胜过基准组合的估算概率。
    • 每用户 observed_metric:根据实验结果,预测指标值将逐渐归入的范围。
    • observed_metric:观测到的基准或变体的累积值。该值用于衡量每个实验变体的表现,以及计算提高幅度值范围胜过基准组合的概率成为最佳变体的概率。根据要衡量的指标,此列可能会标记为“每位用户的使用时长”“每位用户的收入”“留存率”或“转化率”。
  3. 在实验运行一段时间(FCM 和 In-App Messaging 至少 7 天,Remote Config 则要求 14 天)后,此页面上的数据会指明哪个变体(如果有)是“领先变体”。一些衡量结果会使用条形图以可视化的形式来呈现。

向所有用户发布实验

在实验运行了较长的一段时间,足以让您依据目标指标找到“领先变体”(即胜出变体)后,您就可以向所有用户发布该实验了。这样,您就可以选择一个要面向所有用户发布的变体。即使实验尚未确定明确的胜出变体,您仍然可以选择向所有用户发布某个变体。

  1. Firebase 控制台导航菜单的吸引部分中,点击 A/B Testing
  2. 点击已完成正在运行,然后点击您要向所有用户发布的实验,再点击上下文菜单 () 发布变体
  3. 执行以下操作之一,向所有用户发布您的实验:

    • 对于使用 Notifications Composer 的实验,请使用发布消息对话框向未参与该实验的其余目标用户发送消息。
    • 对于 Remote Config 实验,请选择一个变体以确定要更新的 Remote Config 参数值。创建实验时指定的定位条件会作为新条件添加到您的模板中,以确保发布仅影响实验所定位的用户。点击在 Remote Config 中查看以查看更改后,点击发布更改以完成发布。
    • 对于 In-App Messaging 实验,请使用对话框确定哪个变体需要作为独立 In-App Messaging 宣传活动发布。选择变体后,系统会将您重定向到 FIAM 编写屏幕,您可以根据需要在其中对变体进行任何更改,然后再发布变体。

扩大实验规模

如果发现某个实验涵盖的用户不够多,无法让 A/B Testing 确定领先变体,您可以扩大实验规模以提高所覆盖的应用用户群比例。

  1. Firebase 控制台导航菜单的吸引部分中,点击 A/B Testing
  2. 选择要修改的正在运行的实验。
  3. 实验概览中,点击上下文菜单 (),然后点击修改正在运行的实验
  4. 定位对话框会显示一个选项,用于增加当前正在进行的实验的用户所占的百分比。选择一个大于当前百分比的数字,然后点击发布。系统就会将实验推送给您所指定的用户群中该百分比的用户。

复制或停止实验

  1. Firebase 控制台导航菜单的吸引部分中,点击 A/B Testing
  2. 点击已完成正在运行,将指针悬停在实验上,点击上下文菜单 (),然后点击复制实验停止实验

用户定位

您可以使用以下条件来定位用户,以将其纳入到实验中。

定位条件 运算符    备注
版本 包含、
不包含、
完全匹配、
包含正则表达式
输入要纳入到实验中的一个或多个应用版本的值。

使用包含不包含完全匹配运算符时,您可以提供一个以英文逗号分隔的值列表。

使用包含正则表达式运算符时,您可以创建 RE2 格式的正则表达式。您的正则表达式可以与目标版本字符串的全部或部分文本匹配。您还可以使用 ^$ 定位点来与目标字符串的开头部分、结尾部分或全部文本匹配。

用户受众群体 包含全部、
包含至少一个、
不包含全部、
不包含至少一个
选择一个或多个 Analytics 受众群体,以定位可以参与实验的用户。 一些针对 Google Analytics(分析)受众群体的实验可能需要几天时间来累积数据,因为它们会受到 Analytics 数据处理延迟的影响。对于在创建后 24-48 小时内加入符合条件的受众群体的新用户或最近创建的受众群体,最有可能遇到这种延迟。
用户属性 对于文本:
包含、
不包含、
完全匹配、
包含正则表达式

对于数字:
<、≤、=、≥、>
Analytics 用户属性用于选择可以参与实验的用户,并提供一系列用于选择用户属性值的选项。

在客户端上,您只能为用户属性设置字符串值。对于使用数值运算符的条件,Remote Config 服务会将相应用户属性的值转换为整数/浮点数。
使用包含正则表达式运算符时,您可以创建 RE2 格式的正则表达式。您的正则表达式可以与目标版本字符串的全部或部分文本匹配。您还可以使用 ^$ 定位点来与目标字符串的开头部分、结尾部分或全部文本匹配。
国家/地区 不适用 用于选择哪些用户可参与实验的一个或多个国家或地区。  
语言 不适用 用于选择哪些用户可参与实验的一种或多种语言和语言区域。  
首次打开 超过
小于
介于
根据用户首次打开您的应用的时间(以天数指定)来定位用户。
上次应用互动 超过
小于
介于
根据用户上次与您的应用互动的时间(以天数指定)来定位用户。

A/B Testing 指标

创建实验时,您需要选择主要或“目标”指标,用于确定胜出的变体。您还应跟踪其他指标,以便更好地了解每个实验变体的效果,并跟踪可能因变体而异的重要趋势,例如用户留存率、应用稳定性和应用内购买收入。在实验中,您最多可以跟踪五个非目标指标。

例如,假设您已向应用添加新的应用内购买,并希望比较两条不同的“智能推送”消息的效果。在这种情况下,您可能需要选择将购买收入设为目标指标,因为您希望胜出变体代表产生最高应用内购买收入的通知。由于您还想跟踪哪个变体促成了更多的未来转化并留存了用户,因此您可以在要跟踪的其他指标中添加以下指标:

  • 估算总收入,用于了解两个变体的应用内购买和广告收入总额有何不同
  • 留存人数(1 天)留存人数(2-3 天)留存人数(4-7 天),用于跟踪每日/每周的用户留存率

下方各表提供了有关如何计算目标指标和其他指标的详细信息。

目标指标

指标 说明
未遇到崩溃问题的用户数 在实验期间,未在您的应用中遇到 Firebase Crashlytics SDK 所检测到的错误的用户所占的百分比。
估算的广告收入 估算的广告盈利。
估算的总收入 购买活动收入和估算的广告收入的总价值。
购买活动带来的收入 所有 purchasein_app_purchase 事件的总价值。
留存人数(1 天) 每天都会访问您的应用的用户数。
留存人数(2-3 天) 间隔 2-3 天后访问您的应用的用户数。
留存人数(4-7 天) 间隔 4-7 天后访问您的应用的用户数。
留存人数(8-14 天) 间隔 8-14 天后访问您的应用的用户数。
留存人数(15 天以上) 在距离上次使用您的应用 15 天(或更长时间)后访问应用的用户数。
first_open 用户在安装或重新安装应用后首次打开该应用时触发的 Analytics 事件。用作转化漏斗的一部分。

其他指标

指标 说明
notification_dismiss 当 Notifications Composer 所发出的通知被忽略时触发的 Analytics 事件(仅适用于 Android)。
notification_receive 当收到 Notifications Composer 所发出的通知且应用正在后台运行时触发的 Analytics 事件(仅适用于 Android)。
os_update 一个用于跟踪设备操作系统何时更新为新版本的 Analytics 事件。如需了解详情,请参阅自动收集的事件
screen_view 用于跟踪您的应用中的屏幕浏览量的 Analytics 事件。如需了解详情,请参阅跟踪屏幕浏览量
session_start 用于统计应用中的用户会话数的 Analytics 事件。如需了解详情,请参阅自动收集的事件

BigQuery 数据导出服务

除了在 Firebase 控制台中查看 A/B Testing 实验数据之外,您还可以在 BigQuery 中检查和分析实验数据。虽然 A/B Testing 没有单独的 BigQuery 表,但实验和变体成员资格会存储在 Google Analytics(分析)事件表中的每个 Google Analytics(分析)事件上。

包含实验信息的用户属性的形式为 userProperty.key like "firebase_exp_%"userProperty.key = "firebase_exp_01",其中 01 是实验 ID,userProperty.value.string_value 包含实验变体的索引(从零开始)。

您可以使用这些实验用户属性来提取实验数据。这样,您便能够按多种不同的方式拆分实验结果,并独立验证 A/B Testing 的结果。

如需开始使用,请按照本指南中的说明完成以下操作:

  1. 在 Firebase 控制台中为 Google Analytics(分析)启用 BigQuery Export
  2. 使用 BigQuery 访问 A/B Testing 数据
  3. 探索示例查询

在 Firebase 控制台中为 Google Analytics(分析)启用 BigQuery Export

如果您使用的是 Spark 方案,则可以使用 BigQuery 沙盒免费访问 BigQuery,但需遵循沙盒限制。如需了解详情,请参阅价格和 BigQuery 沙盒

首先,请确保将 Analytics(分析)数据导出到 BigQuery:

  1. 打开集成标签页,您可以在 Firebase 控制台中使用 > 项目设置访问该标签页。
  2. 如果您已经将 BigQuery 与其他 Firebase 服务搭配使用,请点击管理。否则,请点击关联
  3. 查看如何将 Firebase 关联至 BigQuery,然后点击下一步
  4. 配置集成部分中,启用 Google Analytics(分析)切换开关。
  5. 选择区域,然后选择导出设置。

  6. 点击关联到 BigQuery

根据您选择导出数据的方式,这些表最多可能需要一天的时间才能供您使用。如需详细了解如何将项目数据导出到 BigQuery,请参阅将项目数据导出到 BigQuery

在 BigQuery 中访问 A/B Testing 数据

在查询特定实验的数据之前,您需要获取要在查询中使用的以下部分或全部信息:

  • 实验 ID:您可以从实验概览页面的网址获取此 ID。例如,如果您的网址类似于 https://console.firebase.google.com/project/my_firebase_project/config/experiment/results/25,则实验 ID 为 25
  • Google Analytics(分析)媒体资源 ID:这是 9 位数 Google Analytics(分析)媒体资源 ID。您可以在 Google Analytics(分析)中找到该 ID;当您展开项目名称以显示 Google Analytics(分析)事件表的名称 (project_name.analytics_000000000.events) 时,该 ID 也会显示在 BigQuery 中。
  • 实验日期:为了编写更快速、更高效的查询,最好是将查询限制为包含实验数据的 Google Analytics(分析)每日事件表分区,即由 YYYYMMDD 后缀标识的表。因此,如果您的实验运行时间为 2024 年 2 月 2 日至 2024 年 5 月 2 日,则应指定 _TABLE_SUFFIX between '20240202' AND '20240502'。如需查看示例,请参阅选择特定实验的值
  • 事件名称:通常,这些名称与您在实验中配置的目标指标相对应。例如,in_app_purchase 事件、ad_impressionuser_retention 事件。

收集生成查询所需的信息后,请执行以下操作:

  1. 在 Google Cloud 控制台中打开 BigQuery
  2. 选择您的项目,然后选择创建 SQL 查询
  3. 添加查询。如需查看要运行的示例查询,请参阅探索示例查询
  4. 点击运行

使用 Firebase 控制台自动生成的查询来查询实验数据

如果您使用的是 Blaze 方案,则实验概览页面会提供一个示例查询,该查询会返回您正在查看的实验的实验名称、变体、事件名称和事件数量。

如需获取并运行自动生成的查询,请执行以下操作:

  1. 在 Firebase 控制台中,打开 A/B Testing,然后选择您要查询的 A/B Testing 实验以打开实验概览
  2. 在“选项”菜单中的 BigQuery 集成下方,选择查询实验数据。系统会在 Google Cloud 控制台内的 BigQuery 中打开您的项目,并提供可用于查询实验数据的基本查询。

以下示例展示了为包含三个变体(包括基准)的实验(名为“Winter Welcome 实验”)生成的查询。该查询会返回运行中实验的名称、变体名称、唯一身份事件以及每个事件的事件计数。请注意,查询构建器不会在表名称中指定项目名称,因为它会直接在项目中打开。

  /*
    This query is auto-generated by Firebase A/B Testing for your
    experiment "Winter welcome experiment".
    It demonstrates how you can get event counts for all Analytics
    events logged by each variant of this experiment's population.
  */
  SELECT
    'Winter welcome experiment' AS experimentName,
    CASE userProperty.value.string_value
      WHEN '0' THEN 'Baseline'
      WHEN '1' THEN 'Welcome message (1)'
      WHEN '2' THEN 'Welcome message (2)'
      END AS experimentVariant,
    event_name AS eventName,
    COUNT(*) AS count
  FROM
    `analytics_000000000.events_*`,
    UNNEST(user_properties) AS userProperty
  WHERE
    (_TABLE_SUFFIX BETWEEN '20240202' AND '20240502')
    AND userProperty.key = 'firebase_exp_25'
  GROUP BY
    experimentVariant, eventName

如需查看其他查询示例,请继续探索示例查询

探索示例查询

以下各部分提供了一些查询示例,您可以使用这些查询示例从 Google Analytics(分析)事件表中提取 A/B Testing 实验数据。

从所有实验中提取购买和实验标准差值

您可以使用实验结果数据独立验证 Firebase A/B Testing 结果。以下 BigQuery SQL 语句会提取实验变体、每个变体中的唯一身份用户数,in_app_purchaseecommerce_purchase 事件带来的总收入,以及指定为 _TABLE_SUFFIX 开始日期和结束日期的时间范围内的所有实验的标准差。您可以将通过此查询获取的数据与统计显著性生成器结合使用进行单侧 t 测试,以验证 Firebase 提供的结果是否与您自己的分析结果一致。

如需详细了解 A/B Testing 如何计算推理,请参阅解读测试结果

  /*
    This query returns all experiment variants, number of unique users,
    the average USD spent per user, and the standard deviation for all
    experiments within the date range specified for _TABLE_SUFFIX.
  */
  SELECT
    experimentNumber,
    experimentVariant,
    COUNT(*) AS unique_users,
    AVG(usd_value) AS usd_value_per_user,
    STDDEV(usd_value) AS std_dev
  FROM
    (
      SELECT
        userProperty.key AS experimentNumber,
        userProperty.value.string_value AS experimentVariant,
        user_pseudo_id,
        SUM(
          CASE
            WHEN event_name IN ('in_app_purchase', 'ecommerce_purchase')
              THEN event_value_in_usd
            ELSE 0
            END) AS usd_value
      FROM `PROJECT_NAME.analytics_ANALYTICS_ID.events_*`
      CROSS JOIN UNNEST(user_properties) AS userProperty
      WHERE
        userProperty.key LIKE 'firebase_exp_%'
        AND event_name IN ('in_app_purchase', 'ecommerce_purchase')
        AND (_TABLE_SUFFIX BETWEEN 'YYYYMMDD' AND 'YYYMMDD')
      GROUP BY 1, 2, 3
    )
  GROUP BY 1, 2
  ORDER BY 1, 2;

选择特定实验的值

以下示例查询说明了如何在 BigQuery 中获取特定实验的数据。此示例查询会返回实验名称、变体名称(包括基准)、事件名称和事件计数。

  SELECT
    'EXPERIMENT_NAME' AS experimentName,
    CASE userProperty.value.string_value
      WHEN '0' THEN 'Baseline'
      WHEN '1' THEN 'VARIANT_1_NAME'
      WHEN '2' THEN 'VARIANT_2_NAME'
      END AS experimentVariant,
    event_name AS eventName,
    COUNT(*) AS count
  FROM
    `analytics_ANALYTICS_PROPERTY.events_*`,
    UNNEST(user_properties) AS userProperty
  WHERE
    (_TABLE_SUFFIX BETWEEN 'YYYMMDD' AND 'YYYMMDD')
    AND userProperty.key = 'firebase_exp_EXPERIMENT_NUMBER'
  GROUP BY
    experimentVariant, eventName