The Products sub-API lets you make partial updates to your existing products. This is ideal for frequently changing data, such as price and availability, as it avoids the need to resubmit the entire product for a small change. However, you should regularly reinsert products to make sure all product data is in sync.
В этом руководстве описано, как использовать метод productinputs.patch для обновления ваших товаров.
Предварительные требования
Для обновления продукта вам потребуется следующее:
- Существующий продукт, который необходимо обновить. Чтобы узнать, как создавать продукты, см. руководство «Добавление и управление продуктами» .
- The
nameof the data source that the product input belongs to (for example,accounts/12345/dataSources/67890). To learn how to find this, see the Manage API data sources for product uploads guide.
Обновите сведения о конкретном товаре.
Чтобы изменить некоторые параметры товара, например, его цену или наличие, без повторной отправки всей информации, используйте метод productInputs.patch .
В параметре updateMask можно указать, какие поля вы хотите изменить. Параметр updateMask представляет собой список полей, разделенных запятыми, которые вы хотите обновить. Метод patch работает следующим образом:
- Поля в
updateMaskи body: Эти поля обновляются новыми значениями. - Поля в
updateMask, но не в body: Эти поля удаляются из поля ввода продукта. - Поля, не включенные в
updateMask: эти поля остаются без изменений. - Параметр
updateMaskопущен: Обновляются все поля, указанные в теле запроса. Поля, не указанные в теле запроса, не удаляются из поля ввода продукта.
Вот пример данных о продукте до обновления:
{
"name": "accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345",
"product": "accounts/{ACCOUNT_ID}/products/en~US~SKU12345",
"offerId": "SKU12345",
"contentLanguage": "en",
"feedLabel": "US",
"productAttributes": {
"title": "Classic Cotton T-Shirt",
"description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
"link": "https://www.example.com/p/SKU12345",
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": [
"9780007350896"
],
"imageLink": "https://www.example.com/image/SKU12345"
}
}
В этом примере обновляются title и availability товара, а также удаляется imageLink . description и price не включены в updateMask и останутся без изменений.
PATCH https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?updateMask=productAttributes.title,productAttributes.availability,productAttributes.imageLink&dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
"productAttributes": {
"title": "Classic Cotton T-Shirt - New Edition",
"availability": "OUT_OF_STOCK",
"description": "A comfortable T-shirt from premium cotton, newer edition.",
"price": {
"amountMicros": "9990000",
"currencyCode": "USD"
}
}
}
A successful call returns the updated ProductInput resource. The title and availability are updated, and the imageLink is removed because it was in the updateMask but not in the request body. The description and price remain unchanged as they were not listed in updateMask .
{
"name": "accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345",
"product": "accounts/{ACCOUNT_ID}/products/en~US~SKU12345",
"offerId": "SKU12345",
"contentLanguage": "en",
"feedLabel": "US",
"productAttributes": {
"title": "Classic Cotton T-Shirt - New Edition",
"description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
"link": "https://www.example.com/p/SKU12345",
"availability": "OUT_OF_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": [
"9780007350896"
],
}
}
Приведенные ниже примеры кода демонстрируют, как обновить товар.
Java
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.protobuf.FieldMask;
import com.google.shopping.merchant.datasources.v1.DataSourceName;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputName;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.UpdateProductInputRequest;
import com.google.shopping.type.CustomAttribute;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to update a product input */
public class UpdateProductInputSample {
public static void updateProductInput(Config config, String productId, String dataSourceId)
throws Exception {
// Obtains OAuth token based on the user's configuration.
GoogleCredentials credential = new Authenticator().authenticate();
// Creates service settings using the credentials retrieved above.
ProductInputsServiceSettings productInputsServiceSettings =
ProductInputsServiceSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(credential))
.build();
// Creates product name to identify product.
String name =
ProductInputName.newBuilder()
.setAccount(config.getAccountId().toString())
.setProductinput(productId)
.build()
.toString();
// Just productAttributes and customAttributes can be updated
FieldMask fieldMask =
FieldMask.newBuilder()
.addPaths("product_attributes.title")
.addPaths("product_attributes.description")
.addPaths("product_attributes.link")
.addPaths("product_attributes.image_link")
.addPaths("product_attributes.availability")
.addPaths("product_attributes.condition")
.addPaths("product_attributes.gtins")
.addPaths("custom_attributes.mycustomattribute")
.build();
// Calls the API and catches and prints any network failures/errors.
try (ProductInputsServiceClient productInputsServiceClient =
ProductInputsServiceClient.create(productInputsServiceSettings)) {
ProductAttributes attributes =
ProductAttributes.newBuilder()
.setTitle("A Tale of Two Cities")
.setDescription("A classic novel about the French Revolution")
.setLink("https://exampleWebsite.com/tale-of-two-cities.html")
.setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
.setAvailability(Availability.IN_STOCK)
.setCondition(Condition.NEW)
.addGtins("9780007350896")
.build();
// The datasource can be either a primary or supplemental datasource.
String dataSource =
DataSourceName.newBuilder()
.setAccount(config.getAccountId().toString())
.setDatasource(dataSourceId)
.build()
.toString();
UpdateProductInputRequest request =
UpdateProductInputRequest.newBuilder()
.setUpdateMask(fieldMask)
// You can only update product attributes and custom_attributes
.setDataSource(dataSource)
.setProductInput(
ProductInput.newBuilder()
.setName(name)
.setProductAttributes(attributes)
.addCustomAttributes(
CustomAttribute.newBuilder()
.setName("mycustomattribute")
.setValue("Example value")
.build())
.build())
.build();
System.out.println("Sending update ProductInput request");
ProductInput response = productInputsServiceClient.updateProductInput(request);
System.out.println("Updated ProductInput Name below");
// The last part of the product name will be the product ID assigned to a product by Google.
// Product ID has the format `contentLanguage~feedLabel~offerId`
System.out.println(response.getName());
System.out.println("Updated Product below");
System.out.println(response);
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
// An ID assigned to a product by Google. In the format
// contentLanguage~feedLabel~offerId
String productId = "en~label~sku123"; // Replace with your product ID.
// Identifies the data source that will own the product input.
String dataSourceId = "{INSERT_DATASOURCE_ID}"; // Replace with your datasource ID.
updateProductInput(config, productId, dataSourceId);
}
}
PHP
use Google\ApiCore\ApiException;
use Google\Protobuf\FieldMask;
use Google\Shopping\Merchant\Products\V1\Availability;
use Google\Shopping\Merchant\Products\V1\Condition;
use Google\Shopping\Merchant\Products\V1\ProductAttributes;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\ProductInput;
use Google\Shopping\Merchant\Products\V1\UpdateProductInputRequest;
use Google\Shopping\Type\CustomAttribute;
/**
* This class demonstrates how to update a product input.
*/
class UpdateProductInputSample
{
// An ID assigned to a product by Google. In the format
// contentLanguage~feedLabel~offerId
// Please ensure this product ID exists for the update to succeed.
private const PRODUCT_ID = "en~label~sku123";
// Identifies the data source that will own the product input.
// Please ensure this data source ID exists.
private const DATASOURCE_ID = "<INSERT_DATASOURCE_ID>";
/**
* Helper function to construct the full product input resource name.
*
* @param string $accountId The merchant account ID.
* @param string $productInputId The product input ID (e.g., "en~label~sku123").
* @return string The full product input resource name.
*/
private static function getProductInputName(string $accountId, string $productInputId): string
{
return sprintf("accounts/%s/productInputs/%s", $accountId, $productInputId);
}
/**
* Helper function to construct the full data source resource name.
*
* @param string $accountId The merchant account ID.
* @param string $dataSourceId The data source ID.
* @return string The full data source resource name.
*/
private static function getDataSourceName(string $accountId, string $dataSourceId): string
{
return sprintf("accounts/%s/dataSources/%s", $accountId, $dataSourceId);
}
/**
* Updates an existing product input in your Merchant Center account.
*
* @param array $config The configuration array containing the account ID.
* @param string $productId The ID of the product input to update.
* @param string $dataSourceId The ID of the data source.
*/
public static function updateProductInput(
array $config,
string $productId,
string $dataSourceId
): void {
// Gets the OAuth credentials to make the request.
$credentials = Authentication::useServiceAccountOrTokenFile();
// Creates options config containing credentials for the client to use.
$options = ['credentials' => $credentials];
// Creates a ProductInputsServiceClient.
$productInputsServiceClient = new ProductInputsServiceClient($options);
// Construct the full resource name of the product input to be updated.
$name = self::getProductInputName($config['accountId'], $productId);
// Define the FieldMask to specify which fields to update.
// Only 'attributes' and 'custom_attributes' can be specified in the
// FieldMask for product input updates.
$fieldMask = new FieldMask([
'paths' => [
"product_attributes.title",
"product_attributes.description",
"product_attributes.link",
"product_attributes.image_link",
"product_attributes.availability",
"product_attributes.condition",
"product_attributes.gtin",
"custom_attributes.mycustomattribute" // Path for a specific custom attribute
]
]);
// Calls the API and handles any network failures or errors.
try {
// Define the new attributes for the product.
$attributes = new ProductAttributes([
'title' => 'A Tale of Two Cities 3',
'description' => 'A classic novel about the French Revolution',
'link' => 'https://exampleWebsite.com/tale-of-two-cities.html',
'image_link' => 'https://exampleWebsite.com/tale-of-two-cities.jpg',
'availability' => Availability::IN_STOCK,
'condition' => Condition::PBNEW,
'gtins' => ['9780007350896'] // GTIN is a repeated field.
]);
// Construct the full data source name.
// This specifies the data source context for the update.
$dataSource = self::getDataSourceName($config['accountId'], $dataSourceId);
// Create the ProductInput object with the desired updates.
// The 'name' field must match the product input being updated.
$productInput = new ProductInput([
'name' => $name,
'product_attributes' => $attributes,
'custom_attributes' => [ // Provide the list of custom attributes.
new CustomAttribute([
'name' => 'mycustomattribute',
'value' => 'Example value'
])
]
]);
// Create the UpdateProductInputRequest.
$request = new UpdateProductInputRequest([
'update_mask' => $fieldMask,
'data_source' => $dataSource,
'product_input' => $productInput
]);
print "Sending update ProductInput request\n";
// Make the API call to update the product input.
$response = $productInputsServiceClient->updateProductInput($request);
print "Updated ProductInput Name below\n";
// The name of the updated product input.
// The last part of the product name is the product ID (e.g., contentLanguage~feedLabel~offerId).
print $response->getName() . "\n";
print "Updated Product below\n";
// Print the full updated product input object.
print_r($response);
} catch (ApiException $e) {
printf("ApiException caught: %s\n", $e->getMessage());
}
}
/**
* Executes the UpdateProductInput sample.
*/
public function callSample(): void
{
$config = Config::generateConfig();
$productId = self::PRODUCT_ID;
$dataSourceId = self::DATASOURCE_ID;
self::updateProductInput($config, $productId, $dataSourceId);
}
}
// Run the script.
$sample = new UpdateProductInputSample();
$sample->callSample();
Python
"""A module to update a product input."""
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.protobuf import field_mask_pb2
from google.shopping.merchant_products_v1 import Availability
from google.shopping.merchant_products_v1 import Condition
from google.shopping.merchant_products_v1 import ProductAttributes
from google.shopping.merchant_products_v1 import ProductInput
from google.shopping.merchant_products_v1 import ProductInputsServiceClient
from google.shopping.merchant_products_v1 import UpdateProductInputRequest
from google.shopping.type import CustomAttribute
# Fetches the Merchant Center account ID from the authentication examples.
# This ID is needed to construct resource names for the API.
_ACCOUNT_ID = configuration.Configuration().read_merchant_info()
def update_product_input(account_id: str, product_id: str, data_source_id: str):
"""Updates an existing product input for a specific account.
Args:
account_id: The Merchant Center account ID.
product_id: The ID of the product input to update. This ID is assigned by
Google and has the format `contentLanguage~feedLabel~offerId`.
data_source_id: The ID of the data source that owns the product input.
"""
# Obtains OAuth credentials for authentication.
credentials = generate_user_credentials.main()
# Creates a ProductInputsServiceClient instance.
client = ProductInputsServiceClient(credentials=credentials)
# Constructs the full resource name for the product input.
# Format: accounts/{account}/productInputs/{productinput}
name = f"accounts/{account_id}/productInputs/{product_id}"
# Defines the FieldMask to specify which fields of the product input
# are being updated. Only 'attributes' and 'custom_attributes' can be updated.
field_mask = field_mask_pb2.FieldMask(
paths=[
"product_attributes.title",
"product_attributes.description",
"product_attributes.link",
"product_attributes.image_link",
"product_attributes.availability",
"product_attributes.condition",
"product_attributes.gtins",
"custom_attributes.mycustomattribute",
]
)
# Prepares the new attribute values for the product.
attributes = ProductAttributes(
title="A Tale of Two Cities updated",
description="A classic novel about the French Revolution",
link="https://exampleWebsite.com/tale-of-two-cities.html",
image_link="https://exampleWebsite.com/tale-of-two-cities.jpg",
availability=Availability.IN_STOCK,
condition=Condition.NEW,
gtins=["9780007350896"], # GTIN is a repeated field.
)
# Constructs the full resource name for the data source.
# The data source can be primary or supplemental.
# Format: accounts/{account}/dataSources/{datasource}
data_source = f"accounts/{account_id}/dataSources/{data_source_id}"
# Prepares the ProductInput object with the updated information.
product_input_data = ProductInput(
name=name,
product_attributes=attributes,
custom_attributes=[
CustomAttribute(
name="mycustomattribute", value="Example value"
)
],
)
# Creates the UpdateProductInputRequest.
request = UpdateProductInputRequest(
update_mask=field_mask,
data_source=data_source,
product_input=product_input_data,
)
# Sends the update request to the API.
try:
print("Sending update ProductInput request")
response = client.update_product_input(request=request)
print("Updated ProductInput Name below")
# The response includes the name of the updated product input.
# The last part of the product name is the product ID assigned by Google.
print(response.name)
print("Updated Product below")
print(response)
except RuntimeError as e:
# Catches and prints any errors that occur during the API call.
print(e)
if __name__ == "__main__":
# The ID of the product to be updated.
# This ID is assigned by Google and typically follows the format:
# contentLanguage~feedLabel~offerId
# Replace with an actual product ID from your Merchant Center account.
product_id_to_update = "en~label~sku123"
# The ID of the data source that will own the updated product input.
# Replace with an actual data source ID from your Merchant Center account.
data_source_id_for_update = "<INSERT_DATA_SOURCE_ID>"
update_product_input(
_ACCOUNT_ID, product_id_to_update, data_source_id_for_update
)
cURL
curl --location --request PATCH 'https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?updateMask=productAttributes.title,productAttributes.description&dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}' \
--header 'Authorization: Bearer <API_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{
"productAttributes": {
"title": "A Tale of Two Cities",
"description": "A classic novel about the French Revolution"
}
}'
Обновление с использованием пользовательских атрибутов
Обновить как стандартные, так и пользовательские атрибуты можно за один вызов. Чтобы обновить пользовательский атрибут, добавьте префикс customAttributes перед его именем в параметре updateMask .
В этом примере выполняется несколько действий в одном запросе:
- Обновляет стандартный атрибут
titleнапрямую. - Обновляет существующий пользовательский атрибут (
myCustomAttrToBeUpdated). - Вставляет новый пользовательский атрибут (
myCustomAttrToBeInserted). - Удаляет существующий пользовательский атрибут (
myCustomAttrToBeDeleted).
PATCH https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?updateMask=productAttributes.title,customAttributes.myCustomAttrToBeInserted,customAttributes.myCustomAttrToBeUpdated,customAttributes.myCustomAttrToBeDeleted&dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
"productAttributes": {
"title": "ProductTitle Updated"
},
"customAttributes": [
{
"name": "description",
"value": "A newly updated description."
},
{
"name": "myCustomAttrToBeUpdated",
"value": "myCustomAttrToBeUpdated updated value"
},
{
"name": "myCustomAttrToBeInserted",
"value": "new from update"
}
]
}
В случае успешного выполнения запроса возвращается обновленный ProductInput , отражающий все указанные изменения.
Понимание обновлений пользовательских атрибутов
You can use the customAttributes field to update attributes that you have defined yourself. These don't map to the standard specification and will be stored as custom attributes on the final product.
Как обрабатываются обновления продукта
When you send a patch request, the update is applied to the specific ProductInput data before any of the rules are applied. This results in consistent behavior between inserting and updating products.
Вот как обрабатывается ваше обновление:
Обновление входных данных: Ваш запрос
patchизменяет конкретныйProductInputсвязанный с предоставленным вами источником данных.Обработка и слияние: После обновления входных данных начинается обработка:
- Feed Rules and Supplemental Data Sources: Rules configured on the primary source of the product combine the
ProductInputfrom primary and supplemental sources. These rules can change attributes or derive new ones. To learn more about setting up the rules, see Set up your attribute rules . - Другие источники данных: Данные из других источников (например, автоматические улучшения) также объединяются с данными из основного источника.
- Проверка достоверности: Объединенные данные проверяются на соответствие спецификации данных о продукте и правилам Google в сфере онлайн-торговли.
- Feed Rules and Supplemental Data Sources: Rules configured on the primary source of the product combine the
Final Product: The result of this pipeline is the final, processed
Productresource that can be returned usingproducts.getorproducts.list. This is also the version of the product that is shown in Merchant Center and is eligible to appear in different destinations.
Because of this multi-step process, there is a delay, typically a few minutes, between when you send an update request and when the changes are reflected in the final Product resource that you can retrieve with products.get .
Пример: Обновление продукта с единственным основным входным параметром.
Это наиболее распространенный сценарий использования. Продукт существует в одном основном источнике данных, и вы хотите обновить некоторые из его атрибутов.
- Исходное состояние: В вашем основном источнике данных существует товар
en~US~SKU12345сtitle: "Classic T-Shirt"иprice: 15.99 USD. - Запрос на обновление: Вы отправляете запрос
patch, чтобы обновитьpriceдо14.99 USDи установитьavailability«out of stock. - Обработка:
- Обновлены
ProductInputдля артикулаSKU12345.
- Обновлены
- Итоговый продукт: Итоговый
Productтеперь имеетtitle: "Classic T-Shirt",price: 14.99 USDиavailability: "out of stock".
Пример: Обновление продукта с добавлением дополнительных данных и правил.
В этом примере показано, как правила обработки данных могут влиять на обновление, приводя к применению одних изменений и отмене других.
- Исходное состояние:
- Основной ввод:
en~US~SKU12345имеетtitle: "Great T-Shirt"иdescription: "A great short-sleeve t-shirt.". - Дополнительная информация: У этого же товара есть запись в дополнительном источнике данных с
title: "Awesome T-Shirt"иdescription: "An awesome short-sleeve t-shirt.". - Правило для ввода данных: установлено правило, которое берет
titleиз дополнительного источника данных. Правило дляdescriptionотсутствует. - Результат: Итоговый обработанный
Productимеетtitle: "Awesome T-Shirt"иdescription: "A great short-sleeve t-shirt.".
- Основной ввод:
- Запрос на обновление: Вы отправляете запрос
patchдля обновления основного источника данных, устанавливаяtitleна"Fantastic T-Shirt"иdescriptionна"A fantastic short-sleeve t-shirt.". - Обработка:
- В поле
ProductInputв основном источнике данных обновлены следующие параметрыtitle: "Fantastic T-Shirt"иdescription: "A fantastic short-sleeve t-shirt.". - Конвейер обработки запущен.
- В отношении
titleправило фида предписывает, что значение из дополнительного источника данных (Awesome T-Shirt) имеет приоритет и переопределяет ваше обновление. - Для
description, поскольку нет переопределяющего правила, используется обновленное значение из основного входного параметра (A fantastic short-sleeve t-shirt.»).
- В поле
- Конечный продукт: Название конечного
ProductостаетсяAwesome T-Shirt(ваше обновление было перезаписано), но его описание теперь звучитA fantastic short-sleeve t-shirt.(ваше обновление было применено).
Выберите между обновлениями и дополнительными источниками данных.
Изменять данные о продукте можно либо с помощью productinputs.patch , либо путем вставки данных в дополнительные источники данных. Наилучший выбор зависит от вашей стратегии управления данными.
Во избежание непредсказуемых результатов мы рекомендуем не использовать одновременно productinputs.patch и дополнительные источники данных для управления одними и теми же данными о продукте.
Вот подробное сравнение:
| Особенность | productinputs.patch (Обновления) | Дополнительные источники данных |
|---|---|---|
| Лучше всего подходит для | Быстрые, частые, частичные изменения существующих данных (например, цены, наличия). | Логическое разделение данных, управление различными атрибутами различными системами или сложные переопределения на основе правил. |
| Механизм | Изменяет существующий объект ProductInput на месте. | Создает новый, отдельный ProductInput в дополнительном источнике данных. |
| Детализация данных | Обрабатывает определенные поля одного ProductInput . | Обрабатывает весь ProductInput в рамках дополнительного источника. |
| Упорство | Изменения сохраняются до тех пор, пока тот же самый ProductInput не будет перезаписан путем полной insert или другого patch . | Сохранение данных контролируется правилами обработки. При наличии приоритета в правилах, данные могут неограниченно перезаписывать основные данные. |
| Взаимодействие правил | Может использоваться без правил подачи данных, поскольку обновляет существующий источник данных и ProductInput . | Требуется явно настроить правило в основном источнике для связи с дополнительным источником. |
| Настройка источника данных | Работает с существующим источником данных. Новые источники не требуются. | Требуется создание и управление отдельными дополнительными источниками данных, а также их связывание с помощью правил передачи данных. |