Это руководство включает набор рекомендаций по публикации кластера, которые разработчики могут использовать при интеграции с Engage SDK.
Кластеры рекомендаций
Название кластера
Мы рекомендуем предоставить уникальное и актуальное название кластера, которое даст пользователям больше информации о содержимом кластера.
Вот несколько примеров хороших названий кластеров, основанных на содержании:
-  Кластеры, связанные с покупками- Молниеносные предложения
- Еженедельные покупки
- Связано с покупкой Pixel Buds
- Женские резиновые сапоги
 
-  Кластеры книг о здоровье- Здоровье, разум и тело
- Рекомендуется для вас в разделе Здоровье
- Бестселлеры в сфере фитнеса
 
Содержимое кластера
При публикации кластеров рекомендаций разработчики должны учитывать, вошел ли пользователь в приложение разработчика.
Когда пользователь вошел в систему
Если пользователь вошел в приложение разработчика, мы рекомендуем публиковать персонализированные или созданные пользователем кластеры контента. Поскольку персонализированный и созданный пользователями контент более актуален для пользователя, у них больше мотивации посетить приложение разработчика с поверхности Google.
-  Персональные рекомендации могут быть опубликованы.-  Вот несколько примеров персонализированных рекомендаций:- Лучшие подборки на основе истории просмотров пользователя.
- Книги, похожие на книги, находящиеся в истории чтения пользователя.
- Песни любимых исполнителей пользователя.
 
 
-  Вот несколько примеров персонализированных рекомендаций:
-  Библиотеки пользовательского контента могут быть опубликованы.-  Вот несколько примеров библиотек пользовательского контента:- Список наблюдения пользователя из приложения разработчика.
- Список любимых исполнителей пользователя из приложения разработчика, сообщаемый самим пользователем.
 
 
-  Вот несколько примеров библиотек пользовательского контента:
| Тип рекомендации | Стратегия обновления контента | Рекомендации по свежести контента | 
|---|---|---|
| Персонализированные рекомендации | Снисходительный Мы рекомендуем обновлять рекомендации один раз в день, чтобы пользователи могли видеть новые рекомендации ежедневно. | Поскольку у пользователей нет точных ожиданий относительно содержания рекомендаций, стратегия обновления контента может быть снисходительной. | 
| Библиотеки пользовательского контента | Строгий Мы рекомендуем обновлять библиотеку контента, когда пользователи выходят из приложения разработчика. | Важно, чтобы этот контент синхронизировался с данными, отображаемыми на поверхностях Google. Это связано с тем, что в отличие от персонализированных рекомендаций пользователь ожидает точный набор контента. Любая значительная задержка в публикации приведет пользователей в замешательство. Поэтому стратегия обновления контента должна быть строгой. | 
Когда пользователь не вошел в систему
Если пользователь не вошел в приложение разработчика, мы по-прежнему рекомендуем публиковать кластеры, чтобы пользователи могли посещать приложение разработчика из Google.
-  Кластеры неперсонализированных рекомендаций должны быть опубликованы.-  Вот несколько примеров неперсонализированных рекомендаций:- 10 лучших книг, прочитанных в этом году.
- Недавно вышедшие фильмы.
- Трендовые подкасты.
 
 
-  Вот несколько примеров неперсонализированных рекомендаций:
-  Опубликуйте карточку входа.- Чтобы побудить пользователей войти в приложение разработчика, разработчики могут опубликовать карточку входа вместе с кластером неперсонализированных рекомендаций. В разделе ниже вы найдете более подробную информацию о том, как опубликовать карту входа .
 
| Тип рекомендации | Стратегия обновления контента | Рекомендации по свежести контента | 
|---|---|---|
| Неперсонализированные рекомендации | Снисходительный Мы рекомендуем обновлять рекомендации один раз в день. | Поскольку у пользователей нет точных ожиданий относительно содержания рекомендаций, стратегия обновления контента может быть снисходительной. | 
| Карта входа в рекомендациях | Строгий Мы рекомендуем обновлять состояние карты входа, когда пользователи выходят из приложения разработчика.  После того как пользователи вошли в систему, разработчики должны удалить карту, вызвав API  | Важно, чтобы состояние входа было синхронизировано с поверхностью Google. Пользователю сложно увидеть карточку входа на поверхности Google, когда он уже вошел в систему. Поэтому стратегия обновления контента должна быть строгой. | 
Кластеры продолжения
При публикации кластеров продолжения разработчики должны учитывать, вошел ли пользователь в приложение разработчика.
Когда пользователь вошел в систему
-  Кластеры продолжения, созданные пользователями, должны быть опубликованы.-  Вот несколько примеров кластеров продолжения, созданных пользователями:- Продолжить просмотр с того места, на котором остановился пользователь.
- Продолжить чтение с того места, на котором остановился пользователь.
 
 
-  Вот несколько примеров кластеров продолжения, созданных пользователями:
| Тип продолжения | Стратегия обновления контента | Рекомендации по свежести контента | 
|---|---|---|
| Созданные пользователем кластеры продолжения | Строгий Мы рекомендуем обновлять библиотеку контента, когда пользователи выходят из приложения разработчика. | Важно, чтобы этот контент синхронизировался с данными, отображаемыми на поверхностях Google. Это связано с тем, что в отличие от персонализированных рекомендаций пользователь ожидает точный набор контента. Любая значительная задержка в публикации приведет пользователей в замешательство. Поэтому стратегия обновления контента должна быть строгой. | 
Когда пользователь не вошел в систему
Продолжение в первую очередь предназначено для вошедших в систему пользователей; однако вы также можете публиковать кластеры продолжения для вышедших из системы пользователей, если ваше приложение поддерживает гостевые сеансы.
Кластер управления пользователями
Основная цель кластера управления пользователями — подтолкнуть пользователей к выполнению определенных действий в приложении поставщика. Действие входа направляет пользователей на страницу входа в приложение, чтобы приложение могло публиковать контент (или предоставлять более персонализированный контент).
Карта входа
| Атрибут | Требование | Описание | 
|---|---|---|
| Действие Ури | Необходимый | Глубокая ссылка на действие (т. е. переход на страницу входа в приложение) | 
| Изображение | Необязательно: если не указано, необходимо указать название. | Изображение на карте Изображения с соотношением сторон 16x9 и разрешением 1264x712. | 
| Заголовок | Необязательно: если не указано, необходимо предоставить изображение. | Титул на карте | 
| Текст действия | Необязательный | Текст, отображаемый в призыве к действию (т. е. войдите в систему) | 
| Субтитры | Необязательный | Дополнительный субтитр на карте | 
Котлин
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());
Ява
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());
 После того как пользователи вошли в систему, разработчики должны удалить карту, вызвав API deleteUserManagementCluster() .
Обновить статус публикации
Если по каким-либо внутренним бизнес-причинам ни один из кластеров не опубликован, мы настоятельно рекомендуем обновить статус публикации с помощью API updatePublishStatus . Это важно, потому что:
- Предоставление статуса во всех сценариях, даже когда контент опубликован (СТАТУС == ПУБЛИКИРОВАНО), имеет решающее значение для заполнения панелей мониторинга, которые используют этот явный статус для передачи работоспособности и других показателей вашей интеграции.
- Если контент не опубликован, но статус интеграции не нарушен (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
Если контент не публикуется из-за того, что пользователь не вошел в систему, мы рекомендуем опубликовать карту входа. Если по какой-либо причине поставщики не могут опубликовать карту входа, мы рекомендуем вызвать API updatePublishStatus с кодом состояния NOT_PUBLISHED_REQUIRES_SIGN_IN.
Котлин
client.updatePublishStatus( PublishStatusRequest.Builder() .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN) .build())
Ява
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);
}
Обработка намерений трансляции
 Помимо выполнения вызовов API публикации контента через задание, также необходимо настроить BroadcastReceiver для получения запроса на публикацию контента.
Однако разработчикам следует быть осторожными и не полагаться исключительно на широковещательные рассылки , поскольку они запускаются только в определенных сценариях — в основном для повторной активации приложения и принудительной синхронизации данных. Они активируются только тогда, когда служба Engage определяет, что контент может быть устаревшим. Таким образом, появляется большая уверенность в том, что пользователь получит свежий контент, даже если приложение не открывалось в течение длительного времени.
 BroadcastReceiver необходимо настроить двумя следующими способами:
-  Динамически зарегистрируйте экземпляр класса BroadcastReceiverс помощьюContext.registerReceiver(). Это позволяет осуществлять связь с приложениями, которые все еще находятся в памяти.
-  Статически объявите реализацию с помощью тега <receiver>в файлеAndroidManifest.xml. Это позволяет приложению получать широковещательные намерения, когда оно не запущено, а также позволяет приложению публиковать контент.
