Engage SDK Cluster 发布指南

本指南包含一系列与集群发布相关的准则,开发者在与 Engage SDK 集成时不妨加以利用。

推荐集群

集群名称

建议为每个集群提供一个相关且不重复的名称,以便用户更清楚地了解集群的内容。

下面列举了一些根据内容所取的集群名称,您可以参考这些示例:

  • 购物相关集群
    • 秒杀特惠
    • 每周必购
    • 与您购买的 Pixel Buds 相关
    • 女款雨靴
  • 健康类图书集群
    • 身心健康
    • 为您推荐的健康类图书
    • 健身畅销书

集群内容

发布推荐集群时,开发者必须考虑用户是否已登录开发者的应用。

如果用户已登录

如果用户已登录开发者应用,建议开发者发布“个性化内容”集群或“用户生成的内容”集群。这两类内容与用户更相关,因此用户会更愿意通过相应 Google surface 访问开发者应用。

  • 可以发布个性化推荐。
    • 下面是个性化推荐的一些示例:
      • 根据用户的观看记录推荐的热门精选。
      • 与用户的阅读记录中的图书类似的图书。
      • 用户喜爱的音乐人的歌曲。
  • 可以发布用户生成的内容库。
    • 下面是用户生成的内容库的一些示例:
      • 开发者应用中的用户观看列表。
      • 开发者应用中自行报告的“用户喜爱的音乐人”列表。
推荐类型 内容新鲜度策略 内容新鲜度准则
个性化推荐

宽松

建议每天更新一次推荐,以便用户每天都能看到新推荐。

由于用户对推荐内容没有确切预期,因此可以采用宽松的内容新鲜度策略。
用户生成的内容库

严格

建议在用户退出开发者应用时更新内容库。

请务必使此内容与各种 Google surface 中显示的数据保持同步。原因在于,与个性化推荐不同,用户对这一系列内容有确切预期。发布出现任何严重延迟,都会让用户感到困惑。因此,必须采用严格的内容新鲜度策略。

如果用户未登录

如果用户没有登录开发者应用,我们仍建议开发者发布集群,以便鼓励用户通过相应 Google surface 访问开发者应用。

  • 应该发布非个性化推荐集群。
    • 下面是非个性化推荐的一些示例:
      • 本年度最热门的 10 本图书。
      • 新上映的电影。
      • 热门播客。
  • 发布登录卡片。
    • 为了鼓励用户登录开发者应用,开发者可以选择同时发布登录卡片和非个性化推荐集群。如需详细了解如何发布登录卡片,请查看以下部分。
推荐类型 内容新鲜度策略 内容新鲜度准则
非个性化推荐

宽松

建议每天更新一次推荐。

由于用户对推荐内容没有确切预期,因此可以采用宽松的内容新鲜度策略。
推荐中的登录卡片

严格

我们建议在用户退出开发者应用时更新登录卡片状态。

用户登录后,开发者必须通过调用 deleteUserManagementCluster() API 来删除卡片。

请务必使登录状态与 Google 途径同步。如果用户已经登录,却在相应 Google surface 中看到登录卡片,便会感到困惑。因此,必须采用严格的内容新鲜度策略。

接续集群

发布接续 (continuation) 集群时,开发者必须考虑用户是否已登录开发者的应用。

如果用户已登录

  • 应该发布用户生成的接续集群。
    • 下面是用户生成的接续集群的一些示例:
      • 从用户离开的位置继续观看。
      • 从用户离开的位置继续阅读。
接续类型 内容新鲜度策略 内容新鲜度准则
用户生成的接续集群

严格

建议在用户退出开发者应用时更新内容库。

请务必使此内容与各种 Google surface 中显示的数据保持同步。原因在于,与个性化推荐不同,用户对这一系列内容有确切预期。发布出现任何严重延迟,都会让用户感到困惑。因此,必须采用严格的内容新鲜度策略。

如果用户未登录

接续历程主要面向已登录的用户;但是,如果您的应用支持访客会话,您还可面向未登录的用户发布接续集群。

用户管理集群

用户管理集群的主要目标是促使用户对提供商应用执行某些操作。登录操作会将用户定向到应用的登录页面,以便应用能够发布内容(或提供更个性化的内容)。

登录卡片

属性 要求 说明
操作 URI 必需 指向操作的深层链接(比如进入应用登录页面)
图片 可选;如果不提供图片,则必须提供标题

卡片上显示的图片

宽高比为 16x9 且分辨率为 1264x712 的图片

标题 可选;如果不提供标题,则必须提供图片 卡片上的标题
操作文本 可选 CTA 上显示的文字(比如“登录”)
副标题 可选 卡片上的可选副标题

Kotlin


var SIGN_IN_CARD_ENTITY =
      SignInCardEntity.Builder()
          .addPosterImage(
              Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build()

appEngagePublishClient.publishUserAccountManagementRequest(
            PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

Java


SignInCardEntity SIGN_IN_CARD_ENTITY =
      new SignInCardEntity.Builder()
          .addPosterImage(
              new Image.Builder()
                  .setImageUri(Uri.parse("http://www.x.com/image.png"))
                  .setImageHeightInPixel(500)
                  .setImageWidthInPixel(500)
                  .build())
          .setActionText("Sign In")
          .setActionUri(Uri.parse("http://xx.com/signin"))
          .build();

appEngagePublishClient.publishUserAccountManagementRequest(
            new PublishUserAccountManagementRequest.Builder()
                .setSignInCardEntity(SIGN_IN_CARD_ENTITY)
                .build());

用户登录后,开发者必须通过调用 deleteUserManagementCluster() API 来删除卡片。

更新发布状态

如果由于任何内部业务原因,所有集群均未发布,我们强烈建议使用 updatePublishStatus API 来更新发布状态。这样做非常重要,因为:

  • 在所有情况下都提供状态,即使内容已发布 (STATUS == PUBLISHED) 也不例外,这一点至关重要,因为只有这样才能填充信息中心,以便信息中心使用此明确状态传达集成的运行状况和其他指标。
  • 如果未发布任何内容,但集成状态未被破坏 (STATUS == NOT_PUBLISHED),Google 可避免在应用运行状况信息中心内触发提醒。它会确认内容是因提供商意料之中的情况而未发布。
  • 它可帮助开发者深入了解数据发布/未发布的详细情况。
  • Google 可能会借助状态代码促使用户在应用中执行某些操作,以便他们看到或处理应用内容。

下面列出了符合条件的发布状态代码:

// Content is published
AppEngagePublishStatusCode.PUBLISHED,

// Content is not published as user is not signed in
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,

// Content is not published as user is not subscribed
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,

// Content is not published as user location is ineligible
AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,

// Content is not published as there is no eligible content
AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,

// Content is not published as the feature is disabled by the client
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,

// Content is not published as the feature due to a client error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,

// Content is not published as the feature due to a service error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,

// Content is not published due to some other reason
// Reach out to engage-developers@ before using this enum.
AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER

如果内容因用户未登录而未发布,建议发布登录卡片。如果提供商因任何原因无法发布登录卡片,建议调用 updatePublishStatus API 并将状态代码设为 NOT_PUBLISHED_REQUIRES_SIGN_IN

Kotlin


client.updatePublishStatus(
   PublishStatusRequest.Builder()
     .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
     .build())

Java


client.updatePublishStatus(
    new PublishStatusRequest.Builder()
        .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN)
        .build());

使用 WorkManager 发布集群

建议使用 WorkManager 来发布集群,因为对于执行策略必须兼具机会性和保证性的后台工作而言,它是推荐的解决方案。

  • WorkManager 会尽快执行您的后台工作。
  • WorkManager 会通过相应逻辑,保障在各种情况下启动您的工作,即使用户离开您的应用也无妨。

当用户离开应用时,建议启动后台作业,以便同时发布接续集群和推荐集群。不妨通过 Activity.onStop() 来处理此逻辑,因为系统会在用户离开应用时调用该方法。

建议您使用 PeriodicWorkRequest 来安排每 24 小时发布一次集群的周期性作业。通过使用 CANCEL_AND_REENQUEUE 政策来触发相应工作,开发者可以确保每当用户离开应用时,WorkManager 都会发送经过更新的数据。这有助于防止用户看到过时的数据。

以下示例对此进行了演示:

// Define the PublishClusters Worker requiring input
public class PublishClusters extends Worker {

   public PublishClusters(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       // publish clusters
   }
   ...
}

public static void schedulePublishClusters(Context appContext) {
// Create a PeriodicWorkRequest to schedule a recurring job to update
// clusters at a regular interval
PeriodicWorkRequest publishClustersEntertainmentSpace =
// Define the time for the periodic job
       new PeriodicWorkRequest.Builder(PublishClusters.class, 24, TimeUnit.HOURS)
// Set up a tag for the worker.
// Tags are Unique identifier, which can be used to identify that work
// later in order to cancel the work or observe its progress.
          .addTag("Publish Clusters to Entertainment Space")
          .build();

// Trigger Periodic Job, this will ensure that the periodic job is triggered
// only once since we have defined a uniqueWorkName
WorkManager.getInstance(appContext).enqueueUniquePeriodicWork(
// uniqueWorkName
     "publishClustersEntertainmentSpace",
// If a work with the uniqueWorkName is already running, it will cancel the
// existing running jobs and replace it with the new instance.
// ExistingPeriodicWorkPolicy#CANCEL_AND_REENQUEUE
     ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
// Recurring Work Request
publishClustersEntertainmentSpace);

}

处理广播 intent

除了通过作业发出发布内容 API 调用外,还需要设置 BroadcastReceiver 来接收内容发布请求。

但是,开发者必须格外小心,不要只依赖于广播,因为广播只有在特定情况(主要是指重新激活应用和强制同步数据的情况)下才会触发。只有在 Engage Service 确定内容可能已过时的情况下,广播才会触发。这样一来,即使用户已很长时间没有打开应用,系统也能更有效地保证用户获得新鲜的内容体验。

必须通过以下两种方式设置 BroadcastReceiver

  • 使用 Context.registerReceiver() 动态注册 BroadcastReceiver 类的实例。这样一来,仍位于内存中的应用即可进行通信。
  • AndroidManifest.xml 文件中使用 <receiver> 标记对实现进行静态声明。这样一来,应用便可以在未运行时接收广播 intent,并且也可以发布内容。