本指南包含一系列与集群发布相关的准则,开发者在与 Engage SDK 集成时不妨加以利用。
推荐集群
集群名称
建议为每个集群提供一个相关且不重复的名称,以便用户更清楚地了解集群的内容。
下面列举了一些根据内容所取的集群名称,您可以参考这些示例:
- 购物相关集群
- 秒杀特惠
- 每周必购
- 与您购买的 Pixel Buds 相关
- 女款雨靴
- 健康类图书集群
- 身心健康
- 为您推荐的健康类图书
- 健身畅销书
集群内容
发布推荐集群时,开发者必须考虑用户是否已登录开发者的应用。
如果用户已登录
如果用户已登录开发者应用,建议开发者发布“个性化内容”集群或“用户生成的内容”集群。这两类内容与用户更相关,因此用户会更愿意通过相应 Google surface 访问开发者应用。
- 可以发布个性化推荐。
- 下面是个性化推荐的一些示例:
- 根据用户的观看记录推荐的热门精选。
- 与用户的阅读记录中的图书类似的图书。
- 用户喜爱的音乐人的歌曲。
- 下面是个性化推荐的一些示例:
- 可以发布用户生成的内容库。
- 下面是用户生成的内容库的一些示例:
- 开发者应用中的用户观看列表。
- 开发者应用中自行报告的“用户喜爱的音乐人”列表。
- 下面是用户生成的内容库的一些示例:
推荐类型 | 内容新鲜度策略 | 内容新鲜度准则 |
---|---|---|
个性化推荐 | 宽松 建议每天更新一次推荐,以便用户每天都能看到新推荐。 |
由于用户对推荐内容没有确切预期,因此可以采用宽松的内容新鲜度策略。 |
用户生成的内容库 | 严格 建议在用户退出开发者应用时更新内容库。 |
请务必使此内容与各种 Google surface 中显示的数据保持同步。原因在于,与个性化推荐不同,用户对这一系列内容有确切预期。发布出现任何严重延迟,都会让用户感到困惑。因此,必须采用严格的内容新鲜度策略。 |
如果用户未登录
如果用户没有登录开发者应用,我们仍建议开发者发布集群,以便鼓励用户通过相应 Google surface 访问开发者应用。
- 应该发布非个性化推荐集群。
- 下面是非个性化推荐的一些示例:
- 本年度最热门的 10 本图书。
- 新上映的电影。
- 热门播客。
- 下面是非个性化推荐的一些示例:
- 发布登录卡片。
- 为了鼓励用户登录开发者应用,开发者可以选择同时发布登录卡片和非个性化推荐集群。如需详细了解如何发布登录卡片,请查看以下部分。
推荐类型 | 内容新鲜度策略 | 内容新鲜度准则 |
---|---|---|
非个性化推荐 | 宽松 建议每天更新一次推荐。 |
由于用户对推荐内容没有确切预期,因此可以采用宽松的内容新鲜度策略。 |
推荐中的登录卡片 | 严格 我们建议在用户退出开发者应用时更新登录卡片状态。 用户登录后,开发者必须通过调用 |
请务必使登录状态与 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,并且也可以发布内容。