Повышайте вовлеченность пользователей, обращаясь к ним там, где они находятся. Интегрируйте Engage SDK, чтобы показывать персональные рекомендации и контент, который пользователи не досмотрели, на разных платформах на устройстве, например в подборках, Entertainment Space и Google Play. Интеграция добавляет менее 50 КБ (в сжатом виде) к среднему размеру APK и занимает у разработчиков около недели. Подробную информацию вы найдете на нашем сайте.
В этом руководстве содержатся инструкции для партнеров-разработчиков по передаче контента, связанного с едой (заказ еды, отзывы о еде или ресторанах, поиск ресторанов, подписки на доставку еды, рецепты), на платформу Google Play Обзор.
Поддерживаемые категории и платформы
Доступность платформ Engage SDK зависит от категории контента в приложении. В таблице ниже указано, какие требования нужно выполнить, чтобы ваши товары показывались на разных платформах.
| Статус | Категория контента или сценарий использования | Поддерживаемые платформы |
|---|---|---|
|
Поддерживается (Доступно на всех платформах) |
|
|
| Чего пользователь не может |
|
Навыки работы с Android
Посмотреть на GitHubИнтегрируйте Engage SDK
android skills add engage-sdk-integrationСведения об интеграции
В этом разделе подробно описаны шаги, модели данных и терминология, необходимые для интеграции с Engage SDK для контента о еде.
Терминология
Интеграция включает пять типов кластеров: Рекомендации, Избранное, Корзина, Список покупок и Повторный заказ.
Рекомендации – персонализированные предложения, связанные с едой, от одного партнера-разработчика. Рекомендации могут быть персонализированными или общими (например, "Новинки со скидкой"). Используйте их, чтобы показывать рецепты, магазины, блюда или продукты.
- Кластер рекомендаций может состоять из страниц
ProductEntity,StoreEntityилиRecipeEntity, но не из страниц разных типов.
Рисунок. ProductEntity, StoreEntity и RecipeEntity. (*Интерфейс показан только для иллюстрации.) - Кластер рекомендаций может состоять из страниц
В кластере Рекомендуемые показываются объекты от разных партнеров-разработчиков. В верхней части интерфейса будет только один кластер "Рекомендуемые", который будет иметь приоритет над всеми кластерами рекомендаций. Каждый партнер-разработчик сможет транслировать до 10 объектов в кластере "Рекомендуемые".
Рисунок. Рекомендуемая группа с RecipeEntity. (*Интерфейс показан только для иллюстрации.) Кластер Корзина с продуктами позволяет пользователям увидеть, что они добавили в корзины в приложениях разных партнеров, и завершить покупки. Есть один кластер "Корзина с продуктами".
В кластере корзины должно быть указано общее количество товаров в корзине. Также можно добавить изображения X товаров из корзины пользователя.
Рисунок. Кластер "Корзина с продуктами" от одного партнера. (*Интерфейс приведен только для примера.)
В кластере Список покупок показываются списки покупок из приложений разных партнеров-разработчиков. Это напоминает пользователям о необходимости вернуться в приложение, чтобы обновить или завершить список. Есть один кластер "Список покупок".
Рисунок. Кластер "Список покупок" от одного партнера. (*Интерфейс приведен только для примера.) В кластере Повторный заказ показываются предыдущие заказы от нескольких партнеров-разработчиков, сгруппированные в одном интерфейсе. Это побуждает пользователей сделать повторный заказ. В кластере Reorder есть только один кластер.
В кластере повторного заказа должно быть указано общее количество товаров в предыдущем заказе пользователя, а также один из следующих элементов:
- Изображения X товаров из предыдущего заказа пользователя.
- Ярлыки для X товаров в предыдущем заказе пользователя.
Рисунок. Кластер повторного заказа еды от одного партнера. (*Интерфейс приведен только для примера.)
Подготовка
Минимальный уровень API: 19.
Добавьте библиотеку com.google.android.engage:engage-core в приложение:
dependencies {
// Make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.engage:engage-core:1.6.0'
}
Сводка
Дизайн основан на реализации привязанной службы.
На данные, которые может публиковать клиент, распространяются следующие ограничения для разных типов кластеров:
| Тип кластера | Ограничения кластера | Максимальное количество объектов в кластере |
|---|---|---|
| Кластеры рекомендаций | Не более 7 | Не более 50 (ProductEntity, RecipeEntity или StoreEntity). |
| Рекомендуемый кластер | Не более 1 | Не более 20 (ProductEntity, RecipeEntity или StoreEntity) |
| Кластер "Корзина с продуктами" | Не более 1 | Не более 3 FoodShoppingCart |
| Кластер "Список покупок" | Не более 1 | Не более 3 FoodShoppingList |
| Кластер повторного заказа еды | Не более 1 | Не более 1 ReorderEntity |
Шаг 1. Укажите данные о компании
В SDK определены разные объекты, представляющие каждый тип товара. Для категории "Еда" поддерживаются следующие объекты:
ProductEntityStoreEntityRecipeEntityFoodShoppingCartFoodShoppingListFoodReorderCluster
В таблицах ниже перечислены доступные атрибуты и требования для каждого типа.
ProductEntity
Объект ProductEntity представляет собой отдельный элемент (например, продукт, блюдо из ресторана или промоакцию), который партнеры-разработчики хотят опубликовать.
ProductEntity
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| Постеры | Обязательно | Добавьте хотя бы одно изображение. | Ознакомьтесь со спецификациями изображений. |
| URI действия | Обязательно |
Ссылка на контент в приложении, которая ведет на страницу с подробными сведениями о товаре. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
URI |
| Название | Необязательно | Название товара. | Произвольный текст Рекомендуемый размер текста: менее 90 символов (слишком длинный текст может быть сокращен). |
| Цена – текущая | Условно обязательно | Текущая цена товара. Обязателен, если указана зачеркнутая цена. |
Произвольный текст |
| Цена – зачеркнутая | Необязательно | Исходная цена объекта, которая зачеркнута в интерфейсе. | Произвольный текст |
| Уточнение | Необязательно | Уточнение, в котором рассказывается о промоакции, событии или обновлении, связанном с товаром (если доступно). | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Мелкий шрифт в уточнении | Необязательно | Текст мелким шрифтом для уточнения. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Оценка (необязательно). Примечание. Все оценки показываются в виде звезд. | |||
| Оценка – максимальное значение | Необязательно | Максимальное значение оценочной шкалы. Обязательно, если указано текущее значение оценки. |
Число >= 0,0 |
| Оценка – текущее значение | Необязательно | Текущее значение оценочной шкалы. Обязательно, если указано максимальное значение оценки. |
Число >= 0,0 |
| Рейтинг – количество | Необязательно | Количество оценок товара. Примечание. Укажите это поле, если ваше приложение управляет тем, как количество отображается пользователям. Используйте краткую строку. Например, если количество равно 1 000 000, используйте сокращение "1 млн", чтобы число не обрезалось на экранах меньшего размера. |
Строка |
| Рейтинг – количество оценок | Необязательно | Количество оценок товара. Примечание. Заполните это поле, если вы не обрабатываете логику сокращения самостоятельно. Если указаны оба значения, пользователям будет показываться Count. |
Долгота |
| DisplayTimeWindow (необязательно) – задает временной интервал, в течение которого контент будет показываться на платформе. | |||
| Временная метка начала | Необязательно |
Временная метка, после которой контент должен показываться на платформе. Если правило не настроено, контент может показываться на платформе. |
Временная метка в миллисекундах с начала отсчета |
| Временная метка окончания | Необязательно |
Временная метка, после которой контент больше не показывается на платформе. Если правило не настроено, контент может показываться на платформе. |
Временная метка в миллисекундах с начала отсчета |
StoreEntity
Объект StoreEntity представляет отдельный магазин, который партнеры-разработчики хотят опубликовать, например ресторан или продуктовый магазин.
StoreEntity
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| Постеры | Обязательно | Добавьте хотя бы одно изображение. | Ознакомьтесь со спецификациями изображений. |
| URI действия | Обязательно | Ссылка на контент в приложении, которая ведет на страницу с информацией о магазине. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
URI |
| Название | Необязательно | Название магазина. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен и дополнен многоточием. |
| Местоположение | Необязательно | Местоположение магазина. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен и дополнен многоточием. |
| Уточнение | Необязательно | Выноска с информацией о промоакции, событии или обновлении в магазине (если есть). | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Мелкий шрифт в уточнении | Необязательно | Текст мелким шрифтом для уточнения. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Описание | Необязательно | Описание магазина. | Произвольный текст Рекомендуемая длина текста: до 90 символов. Если текст слишком длинный, он может быть сокращен. |
| Категория | Необязательно | Категория магазина. В контексте заведений общественного питания это может быть тип кухни, например "французская", "современная американская", "рамен", "изысканная". |
Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Примечание. Все оценки отображаются в виде звезд. | |||
| Оценка – максимальное значение | Необязательно | Максимальное значение оценочной шкалы. Обязательно, если указано текущее значение оценки. |
Число >= 0,0 |
| Оценка – текущее значение | Необязательно | Текущее значение оценочной шкалы. Обязательно, если указано максимальное значение оценки. |
Число >= 0,0 |
| Рейтинг – количество | Необязательно | Количество оценок магазина. Примечание. Заполните это поле, если хотите контролировать, как информация будет показываться пользователям. Укажите краткую строку, которая может быть показана пользователю. Например, если количество равно 1 000 000, используйте сокращение "1 млн", чтобы оно не усекалось на экранах меньшего размера. |
Строка |
| Рейтинг – количество оценок | Необязательно | Количество оценок магазина. Примечание. Заполните это поле, если не хотите самостоятельно настраивать логику сокращения. Если указаны оба значения, пользователям будет показываться Count. |
Долгота |
RecipeEntity
Объект RecipeEntity представляет рецепт, который партнеры-разработчики хотят опубликовать.
RecipeEntity
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| Постеры | Обязательно | Добавьте хотя бы одно изображение. | Ознакомьтесь со спецификациями изображений. |
| URI действия | Обязательно | Ссылка на контент в приложении, которая ведет на страницу с подробной информацией о рецепте. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
URI |
| Название | Необязательно | Название рецепта. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен и дополнен многоточием. |
| Автор | Необязательно | Автор рецепта. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен и дополнен многоточием. |
| Время приготовления | Необязательно | Время приготовления блюда. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен и дополнен многоточием. |
| Уточнение | Необязательно | Информация о промоакции, событии или обновлении, связанных с рецептом (если есть). | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Категория | Необязательно | Категория рецепта. | Произвольный текст Рекомендуемая длина текста: до 45 символов. Если текст слишком длинный, он может быть сокращен. |
| Описание | Необязательно | Описание рецепта. | Произвольный текст Рекомендуемая длина текста: до 90 символов. Если текст слишком длинный, он может быть сокращен. |
| Примечание. Все оценки показываются в виде звезд. | |||
| Оценка – максимальное значение | Необязательно | Максимальное значение оценочной шкалы. Обязательно, если указано текущее значение оценки. |
Число >= 0,0 |
| Оценка – текущее значение | Необязательно | Текущее значение оценочной шкалы. Обязательно, если указано максимальное значение оценки. |
Число >= 0,0 |
| Рейтинг – количество | Необязательно | Количество оценок рецепта. Примечание. Заполните это поле, если хотите контролировать, как информация будет показываться пользователям. Укажите краткую строку, которая может быть показана пользователю. Например, если количество равно 1 000 000, используйте сокращение "1 млн", чтобы оно не усекалось на экранах меньшего размера. |
Строка |
| Рейтинг – количество оценок | Необязательно | Количество оценок рецепта. Примечание. Заполните это поле, если не хотите самостоятельно настраивать логику сокращения. Если указаны оба значения, пользователям будет показываться Count. |
Долгота |
FoodShoppingCart
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| URI действия | Обязательно |
Ссылка на контент в приложении партнера, которая ведет к корзине. Примечание. Ссылки на контент можно использовать для атрибуции. Часто задаваемые вопросы |
URI |
| Количество элементов | Обязательно | Количество товаров (а не только количество продуктов) в корзине. Например, если в корзине три апельсина и одно яблоко, то значение должно быть равно 4. |
Целое число >= 1 |
| Временная метка последнего взаимодействия пользователя | Обязательно | Количество миллисекунд, прошедших с начала эпохи, определяющее, когда пользователь в последний раз взаимодействовал с корзиной. | Временная метка в миллисекундах с начала отсчета |
| Название | Необязательно | Название корзины, например Корзина. Если разработчик не указал заголовок, по умолчанию используется Ваша корзина. |
Произвольный текст Рекомендуемая длина текста: не более 25 символов. Если текст слишком длинный, он может быть сокращен. |
| Текст действия | Необязательно |
Текст призыва к действию на кнопке корзины, например Ваша корзина. Если разработчик не указал текст действия, по умолчанию используется Посмотреть корзину. Этот атрибут поддерживается в версии 1.1.0 и более поздних. |
Строка |
| Изображения корзины | Необязательно | Изображения каждого товара в корзине. Можно добавить до 10 изображений в порядке приоритета. Количество показываемых изображений зависит от типа устройства. |
Ознакомьтесь со спецификациями изображений. |
| Ярлыки объектов | Необязательно | Список ярлыков для товаров в списке покупок. Фактическое количество ярлыков зависит от типа устройства. |
Список ярлыков в виде текста Рекомендуемая длина текста: не более 20 символов. Если текст слишком длинный, он может быть сокращен. |
| DisplayTimeWindow (необязательно) – задает временной интервал, в течение которого контент будет показываться на платформе. | |||
| Временная метка начала | Необязательно |
Временная метка, после которой контент должен показываться на платформе. Если правило не настроено, контент может показываться на платформе. |
Временная метка в миллисекундах с начала отсчета |
| Временная метка окончания | Необязательно |
Временная метка, после которой контент больше не показывается на платформе. Если правило не настроено, контент может показываться на платформе. |
Временная метка в миллисекундах с начала отсчета |
FoodShoppingList
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| URI действия | Обязательно |
Ссылка на контент в приложении партнера, которая ведет к списку покупок. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
URI |
| Количество элементов | Обязательно | Количество товаров в списке покупок. | Целое число >= 1 |
| Временная метка последнего взаимодействия пользователя | Обязательно | Количество миллисекунд, прошедших с начала эпохи, определяющее время последнего взаимодействия пользователя со списком покупок. | Временная метка в миллисекундах с начала отсчета |
| Название | Необязательно |
Название списка, например Список покупок. Если разработчик не указал название, по умолчанию используется Список покупок. |
Произвольный текст Рекомендуемая длина текста: не более 25 символов. Если текст слишком длинный, он может быть сокращен. |
| Ярлыки объектов | Обязательно | Список ярлыков для товаров в списке покупок. Необходимо указать хотя бы один ярлык. Максимальное количество ярлыков – 10. Они должны быть перечислены в порядке приоритета. Количество ярлыков, которые будут показаны, зависит от типа устройства. |
Список ярлыков в виде текста Рекомендуемая длина текста: не более 20 символов. Если текст слишком длинный, он может быть сокращен. |
FoodReorderCluster
| Атрибут | Требования | Описание | Формат |
|---|---|---|---|
| URI действия | Обязательно |
Ссылка на контент в приложении партнера, по которой можно повторить заказ. Примечание. Ссылки на контент можно использовать для атрибуции. Ознакомьтесь с разделом часто задаваемых вопросов |
URI |
| Текст действия | Необязательно |
Текст призыва к действию на кнопке повторного заказа, например Заказать снова. Если разработчик не указал текст действия, по умолчанию используется Заказать снова. Этот атрибут поддерживается в версии 1.1.0 и более поздних. |
Строка |
| Количество элементов | Обязательно |
Количество товаров (не только количество продуктов) в предыдущем заказе. Например, если в предыдущем заказе было три маленьких кофе и один круассан, то это число должно быть равно четырем. |
Целое число >= 1 |
| Название | Обязательно | Название товара, который вы хотите заказать повторно. | Произвольный текст Рекомендуемая длина текста: не более 40 символов. Если текст слишком длинный, он может быть сокращен. |
| Ярлыки объектов | Необязательно (Если не указано, необходимо предоставить изображения постеров) |
Список ярлыков товаров для предыдущего заказа. Можно указать до 10 ярлыков в порядке приоритета. Фактическое количество ярлыков зависит от типа устройства. |
Список произвольного текста Рекомендуемый размер текста для каждого ярлыка: менее 20 символов. (Слишком длинный текст может быть сокращен многоточием.) |
| Постеры | Необязательно (Если не указано, необходимо указать ярлыки объектов) |
Изображения товаров из предыдущего заказа. Вы можете добавить до 10 изображений в порядке приоритета. Количество показываемых изображений зависит от типа устройства. |
Ознакомьтесь со спецификациями изображений. |
Требования к картинкам
В таблице ниже приведены требования к объектам изображений.
| Соотношение сторон | Минимальный размер (пиксели) | Рекомендуемый размер (пиксели) |
|---|---|---|
Квадрат (1:1). Предпочтительный |
300x300 | 1200x1200 |
| Горизонтальное (1,91:1) | 600x314 | 1200x628 |
| Вертикальное (4:5) | 480x600 | 960x1200 |
Форматы файлов
PNG, JPG, статический GIF, WebP
Максимальный размер файла
5120 КБ
Дополнительные рекомендации
- Рекомендуемые пределы допустимой области изображения: важный контент должен занимать центральные 80% изображения.
- Используйте прозрачный фон, чтобы изображение правильно отображалось в светлой и темной темах.
Шаг 2. Предоставьте данные о кластере
Рекомендуется выполнять публикацию контента в фоновом режиме (например, с помощью WorkManager) и запланировать ее на регулярной основе или на основе событий (например, каждый раз, когда пользователь открывает приложение или когда пользователь только что добавил что-то в свою корзину).
AppEngageFoodClient отвечает за публикацию кластеров продуктов питания.
Для публикации кластеров в клиенте используются следующие API:
isServiceAvailablepublishRecommendationClusterspublishFeaturedClusterpublishFoodShoppingCartspublishFoodShoppingListspublishReorderClusterpublishUserAccountManagementRequestupdatePublishStatusdeleteRecommendationsClustersdeleteFeaturedClusterdeleteFoodShoppingCartClusterdeleteFoodShoppingListClusterdeleteReorderClusterdeleteUserManagementClusterdeleteClusters
isServiceAvailable
Этот API используется, чтобы проверить, доступен ли сервис для интеграции и можно ли показывать контент на устройстве.
Для Engage SDK версии 1.6.0 и выше (рекомендуется)
Навыки работы с Android
Посмотреть на GitHubИнтеграция Engage SDK
android skills add engage-sdk-integrationUse the engage-sdk-integration skill to use Engage SDK 1.6.0 and refactor isServiceAvailable to pass ServiceAvailabilityRequest for publishing all cluster types.Вы можете проверить доступность сервиса для каждого типа кластера, который вы собираетесь опубликовать. API isServiceAvailable принимает объект запроса ServiceAvailabilityRequest, который содержит типы кластеров, для которых необходимо проверить доступность сервиса. В таблице ниже приведены значения перечисления ClusterType, необходимые для ServiceAvailabilityRequest.
| Тип кластера | Константа типа кластера | Целочисленное значение |
|---|---|---|
| Неизвестно | TYPE_UNKNOWN |
0 |
| Кластер рекомендаций | TYPE_RECOMMENDATION |
1 |
| Рекомендуемый кластер | TYPE_FEATURED |
2 |
| Кластер продолжения | TYPE_CONTINUATION |
3 |
| Кластер повторного заказа еды | TYPE_FOOD_REORDER |
5 |
| Кластер "Корзина с продуктами" | TYPE_FOOD_SHOPPING_CART |
6 |
| Кластер "Список покупок" | TYPE_FOOD_SHOPPING_LIST |
7 |
| Кластер управления пользователями | TYPE_ENGAGEMENT |
8 |
| Кластер подписок | TYPE_SUBSCRIPTION |
12 |
Kotlin
val request = ServiceAvailabilityRequest.Builder()
.addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
.addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
.build()
client.isServiceAvailable(request).addOnCompleteListener { task ->
if (task.isSuccessful) {
val availabilityMap = task.result
if (availabilityMap[ClusterType.TYPE_CONTINUATION] == true) {
// Proceed with publishing continuation content
}
if (availabilityMap[ClusterType.TYPE_RECOMMENDATION] == true) {
// Proceed with publishing recommendation content
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
}
Java
ServiceAvailabilityRequest request =
new ServiceAvailabilityRequest.Builder()
.addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
.addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
.build();
client.isServiceAvailable(request).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Map<Integer, Boolean> availabilityMap = task.getResult();
if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_CONTINUATION))) {
// Proceed with publishing continuation content
}
if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_RECOMMENDATION))) {
// Proceed with publishing recommendation content
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
});
Функция условной доступности сервиса
В некоторых интегрированных приложениях запрашивается специальная конфигурация, которая периодически включает и отключает сервис Engage, чтобы снизить общую стоимость. Однако такая стратегия периодического приема контента негативно влияет на удобство использования: устаревший контент не будет показываться, а некоторые платформы не будут обслуживаться.
Начиная с версии 1.6.0 Engage SDK позволяет проверять доступность определенных типов кластеров. Если ваше приложение использует прерывистую передачу данных:
- Кластеры продолжения (например, "Корзина", "Список покупок" и "Повторный заказ") остаются включенными по умолчанию на всех поддерживаемых устройствах.
- Другие типы кластеров (например, рекомендации) включаются и отключаются периодически.
Если эта конфигурация по умолчанию вам не подходит, напишите на адрес engage-developers@google.com.
Для версий SDK до 1.6.0 (поддержка прекращена)
Kotlin
client.isServiceAvailable.addOnCompleteListener { task ->
if (task.isSuccessful) {
// Handle IPC call success
if(task.result) {
// Service is available on the device, proceed with content publish
// calls.
} else {
// Service is not available, no further action is needed.
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
}
Java
client.isServiceAvailable().addOnCompleteListener(task - > {
if (task.isSuccessful()) {
// Handle success
if(task.getResult()) {
// Service is available on the device, proceed with content publish
// calls.
} else {
// Service is not available, no further action is needed.
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
});
publishRecommendationClusters
Этот API используется для публикации списка объектов RecommendationCluster.
Объект RecommendationCluster может иметь следующие атрибуты:
| Атрибут | Требования | Описание |
|---|---|---|
| Список ProductEntity, StoreEntity или RecipeEntity | Обязательно | Список объектов, составляющих рекомендации для этого кластера. Объекты в одном кластере должны быть одного типа. |
| Название | Обязательно | Название кластера рекомендаций (например, Большие скидки на меню ко Дню благодарения). Рекомендуемая длина текста: до 25 символов. Если текст слишком длинный, он может быть сокращен. |
| Подзаголовок | Необязательно | Подзаголовок кластера рекомендаций. |
| URI действия | Необязательно |
Ссылка на контент в приложении партнера, где пользователи могут посмотреть полный список рекомендаций. Примечание. Ссылки на контент можно использовать для атрибуции. Часто задаваемые вопросы |
Kotlin
client.publishRecommendationClusters(
PublishRecommendationClustersRequest.Builder()
.addRecommendationCluster(
RecommendationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.setTitle("Big savings on Thanksgiving menu")
.build())
.build())
Java
client.publishRecommendationClusters(
new PublishRecommendationClustersRequest.Builder()
.addRecommendationCluster(
new RecommendationCluster.Builder()
.addEntity(entity1)
.addEntity(entity2)
.setTitle("Big savings on Thanksgiving menu")
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Все существующие данные кластера рекомендаций удаляются.
- Данные из запроса анализируются и сохраняются в новых кластерах рекомендаций.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishFeaturedCluster
Этот API используется для публикации объекта FeaturedCluster.
Kotlin
client.publishFeaturedCluster(
PublishFeaturedClusterRequest.Builder()
.setFeaturedCluster(
FeaturedCluster.Builder()
...
.build())
.build())
Java
client.publishFeaturedCluster(
new PublishFeaturedClusterRequest.Builder()
.setFeaturedCluster(
new FeaturedCluster.Builder()
...
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
FeaturedClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленной группе.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishFoodShoppingCarts
Этот API используется для публикации списка объектов FoodShoppingCart.
Kotlin
client.publishFoodShoppingCarts(
PublishFoodShoppingCartsRequest.Builder()
.addFoodShoppingCart(
FoodShoppingCart.Builder()
...
.build())
.build())
Java
client.publishFoodShoppingCarts(
new PublishFoodShoppingCartsRequest.Builder()
.addFoodShoppingCart(
new FoodShoppingCart.Builder()
...
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
FoodShoppingCartот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере корзины.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishFoodShoppingLists
Этот API используется для публикации списка объектов FoodShoppingList.
Kotlin
client.publishFoodShoppingLists(
PublishFoodShoppingListsRequest.Builder()
.addFoodShoppingList(
FoodShoppingList.Builder()
...
.build())
.build())
Java
client.publishFoodShoppingLists(
new PublishFoodShoppingListsRequest.Builder()
.addFoodShoppingList(
new FoodShoppingList.Builder()
...
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
FoodShoppingListот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере списка покупок.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishReorderCluster
Этот API используется для публикации объекта FoodReorderCluster.
Kotlin
client.publishReorderCluster(
PublishReorderClusterRequest.Builder()
.setReorderCluster(
FoodReorderCluster.Builder()
...
.build())
.build())
Java
client.publishReorderCluster(
new PublishReorderClusterRequest.Builder()
.setReorderCluster(
new FoodReorderCluster.Builder()
...
.build())
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
FoodReorderClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере повторного заказа.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
publishUserAccountManagementRequest
Этот API используется для публикации карточки входа . Действие "Войти" направляет пользователей на страницу входа в приложение, чтобы оно могло публиковать контент (или предоставлять более персонализированный контент).
В карточке входа содержатся следующие метаданные:
| Атрибут | Требования | Описание |
|---|---|---|
| URI действия | Обязательно | Ссылка на контент для действия (например, переход на страницу входа в приложение) |
| Изображение | Необязательно. Если не указано, необходимо указать название. |
Изображение на карточке Изображения с соотношением сторон 16:9 и разрешением 1264 x 712. |
| Название | Необязательно. Если не указано, необходимо добавить изображение. | Название на карточке |
| Текст действия | Необязательно | Текст, который будет показываться в призыве к действию (например, "Войти") |
| Подзаголовок | Необязательно | Необязательный подзаголовок на карточке |
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()
client.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();
client.publishUserAccountManagementRequest(
new PublishUserAccountManagementRequest.Builder()
.setSignInCardEntity(SIGN_IN_CARD_ENTITY)
.build());
Когда сервис получает запрос, в рамках одной транзакции выполняются следующие действия:
- Существующие данные
UserAccountManagementClusterот партнера-разработчика удаляются. - Данные из запроса анализируются и сохраняются в обновленном кластере UserAccountManagementCluster.
В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
updatePublishStatus
Если по какой-либо внутренней причине ни один из кластеров не опубликован, мы настоятельно рекомендуем обновить статус публикации с помощью API updatePublishStatus. Это важно по следующим причинам :
- Указывать статус нужно во всех случаях, даже когда контент опубликован (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
Если контент не публикуется из-за того, что пользователь не вошел в аккаунт, Google рекомендует опубликовать карточку входа. Если по какой-либо причине поставщики не могут опубликовать карточку входа, мы рекомендуем вызвать API updatePublishStatus с кодом статуса 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());
deleteRecommendationsClusters
Этот API используется для удаления контента из кластеров рекомендаций.
Kotlin
client.deleteRecommendationsClusters()
Java
client.deleteRecommendationsClusters();
Когда сервис получает запрос, он удаляет существующие данные из кластеров рекомендаций. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteFeaturedCluster
Этот API используется для удаления контента из рекомендуемой группы.
Kotlin
client.deleteFeaturedCluster()
Java
client.deleteFeaturedCluster();
Когда сервис получает запрос, он удаляет существующие данные из рекомендуемого кластера. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteFoodShoppingCartCluster
Этот API используется для удаления контента из кластера корзины покупок в разделе "Еда".
Kotlin
client.deleteFoodShoppingCartCluster()
Java
client.deleteFoodShoppingCartCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера Food Shopping Cart. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteFoodShoppingListCluster
Этот API используется для удаления контента кластера списка покупок продуктов.
Kotlin
client.deleteFoodShoppingListCluster()
Java
client.deleteFoodShoppingListCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера списка покупок. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteReorderCluster
Этот API используется для удаления контента FoodReorderCluster.
Kotlin
client.deleteReorderCluster()
Java
client.deleteReorderCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера Reorder. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteUserManagementCluster
Этот API используется для удаления контента кластера UserAccountManagement.
Kotlin
client.deleteUserManagementCluster()
Java
client.deleteUserManagementCluster();
Когда сервис получает запрос, он удаляет существующие данные из кластера UserAccountManagement. В случае ошибки весь запрос отклоняется и сохраняется существующее состояние.
deleteClusters
Этот API используется для удаления контента кластера определенного типа.
Kotlin
client.deleteClusters(
DeleteClustersRequest.Builder()
.addClusterType(ClusterType.TYPE_FEATURED)
.addClusterType(ClusterType.TYPE_RECOMMENDATION)
...
.build())
Java
client.deleteClusters(
new DeleteClustersRequest.Builder()
.addClusterType(ClusterType.TYPE_FEATURED)
.addClusterType(ClusterType.TYPE_RECOMMENDATION)
...
.build());
Когда сервис получает запрос, он удаляет существующие данные из всех кластеров, соответствующих указанным типам. Клиенты могут передавать один или несколько типов кластеров. В случае ошибки весь запрос отклоняется, а существующее состояние сохраняется.
Обработка ошибок
Настоятельно рекомендуется отслеживать результаты выполнения задач, полученные от API публикации, чтобы можно было предпринять последующие действия по восстановлению и повторной отправке успешной задачи.
client.publishRecommendationClusters(
new PublishRecommendationClustersRequest.Builder()
.addRecommendationCluster(...)
.build())
.addOnCompleteListener(
task -> {
if (task.isSuccessful()) {
// do something
} else {
Exception exception = task.getException();
if (exception instanceof AppEngageException) {
@AppEngageErrorCode
int errorCode = ((AppEngageException) exception).getErrorCode();
if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
// do something
}
}
}
});
Ошибка возвращается как AppEngageException с указанием причины в виде кода ошибки.
| Код ошибки | Название ошибки | Примечание |
|---|---|---|
1 |
SERVICE_NOT_FOUND |
Сервис недоступен на этом устройстве. |
2 |
SERVICE_NOT_AVAILABLE |
Сервис доступен на устройстве, но не в момент вызова (например, он отключен). |
3 |
SERVICE_CALL_EXECUTION_FAILURE |
Не удалось выполнить задачу из-за проблем с потоками. В этом случае можно повторить попытку. |
4 |
SERVICE_CALL_PERMISSION_DENIED |
Вызывающий абонент не может выполнить вызов сервиса. |
5 |
SERVICE_CALL_INVALID_ARGUMENT |
Запрос содержит недопустимые данные (например, количество кластеров превышает допустимое). |
6 |
SERVICE_CALL_INTERNAL |
Ошибка на стороне сервиса. |
7 |
SERVICE_CALL_RESOURCE_EXHAUSTED |
Вызов сервиса выполняется слишком часто. |
Шаг 3. Обработка намерений широковещательной рассылки
Помимо вызовов API для публикации контента через задание, также необходимо настроить BroadcastReceiver для получения запроса на публикацию контента.
Цель широковещательных намерений – повторная активация приложения и принудительная синхронизация данных. Широковещательные намерения не предназначены для частой отправки. Он запускается, только когда сервис Google Play Объекты определяет, что контент может быть устаревшим (например, ему неделя). Это позволяет пользователю видеть актуальный контент, даже если приложение не запускалось в течение длительного периода времени.
BroadcastReceiver необходимо настроить двумя способами:
Динамически зарегистрируйте экземпляр класса
BroadcastReceiverс помощьюContext.registerReceiver(). Это позволяет приложениям, которые все ещё находятся в памяти, обмениваться данными.
Kotlin
class AppEngageBroadcastReceiver : BroadcastReceiver(){
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION
// broadcast is received
// Trigger featured cluster publish when PUBLISH_FEATURED broadcast is
// received
// Trigger food shopping cart cluster publish when PUBLISH_FOOD_SHOPPING_CART broadcast
// is received
// Trigger food shopping list cluster publish when PUBLISH_FOOD_SHOPPING_LIST broadcast
// is received
// Trigger reorder cluster publish when PUBLISH_REORDER_CLUSTER broadcast is
// received
}
fun registerBroadcastReceivers(context: Context){
var context = context
context = context.applicationContext
// Register Recommendation Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register Featured Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_FEATURED),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register food Shopping Cart Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_FOOD_SHOPPING_CART),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register food Shopping List Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_FOOD_SHOPPING_LIST),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
// Register Reorder Cluster Publish Intent
context.registerReceiver(AppEngageBroadcastReceiver(),
IntentFilter(Intents.ACTION_PUBLISH_REORDER_CLUSTER),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null)
}
Java
class AppEngageBroadcastReceiver extends BroadcastReceiver {
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
// is received
// Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received
// Trigger food shopping cart cluster publish when PUBLISH_FOOD_SHOPPING_CART broadcast is
// received
// Trigger food shopping list cluster publish when PUBLISH_FOOD_SHOPPING_LIST broadcast is
// received
// Trigger reorder cluster publish when PUBLISH_REORDER_CLUSTER broadcast is
// received
}
public static void registerBroadcastReceivers(Context context) {
context = context.getApplicationContext();
// Register Recommendation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_RECOMMENDATION),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register food Shopping Cart Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_FOOD_SHOPPING_CART),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register food Shopping List Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_FOOD_SHOPPING_LIST),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
// Register Reorder Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_REORDER_CLUSTER),
com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
/*scheduler=*/null);
}
Статически объявите реализацию с помощью тега
<receiver>в файлеAndroidManifest.xml. Это позволяет приложению получать намерения широковещательной рассылки, когда оно не запущено, а также публиковать контент.
<application>
<receiver
android:name=".AppEngageBroadcastReceiver"
android:permission="com.google.android.engage.REQUEST_ENGAGE_DATA"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_CART" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_LIST" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.food.PUBLISH_REORDER_CLUSTER" />
</intent-filter>
</receiver>
</application>
Сервис будет отправлять следующие намерения:
com.google.android.engage.action.PUBLISH_RECOMMENDATIONПри получении этого намерения рекомендуется начать вызовpublishRecommendationClusters.com.google.android.engage.action.PUBLISH_FEATUREDПри получении этого намерения рекомендуется начать вызовpublishFeaturedCluster.com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_CARTПри получении этого намерения рекомендуется начать вызовpublishFoodShoppingCarts.com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_LISTПри получении этого намерения рекомендуется начать вызовpublishFoodShoppingLists.com.google.android.engage.action.food.PUBLISH_REORDER_CLUSTERПри получении этого намерения рекомендуется начать вызовpublishReorderCluster.
Процесс интеграции
Пошаговые инструкции по проверке интеграции после ее завершения можно найти в руководстве по интеграции для разработчиков.
Часто задаваемые вопросы
Часто задаваемые вопросы об Engage SDK
Контакт
Если у вас возникнут вопросы в процессе интеграции, свяжитесь с engage-developers@google.com. Наши специалисты ответят вам в ближайшее время.
Дальнейшие действия
После завершения интеграции выполните следующие действия:
- Отправьте письмо на адрес
engage-developers@google.comи прикрепите к нему интегрированный APK-файл, готовый к тестированию в Google. - Google проверит, правильно ли работает интеграция. Если потребуются изменения, Google свяжется с вами и сообщит необходимые сведения.
- Если тестирование прошло успешно и изменения не требуются, Google сообщит вам, что вы можете опубликовать обновленный и интегрированный APK-файл в Google Play.
- После того как Google подтвердит, что обновленный APK-файл опубликован в Google Play, ваши кластеры Рекомендации, Рекомендуемые, Корзина, Список покупок и Повторный заказ будут опубликованы и станут видны пользователям.