La API secundaria Products te permite administrar todo el ciclo de vida de tus productos en Merchant Center. Puedes usarla para subir productos nuevos, actualizar los existentes, recuperar información de productos y borrar los que ya no vendes.
Consideraciones especiales
- Los productos solo se pueden insertar, actualizar o borrar si pertenecen a
fuentes de datos
del tipo
API. No puedes insertar ni actualizar productos en fuentes de datos que usan cargas basadas en archivos. - Para mantener la relevancia de tus productos y evitar que venzan , debes actualizarlos o actualizarlos con una frecuencia regular (al menos cada 30 días).
- El segmento
ProductInput.namees un identificador único del producto. Los productos se identifican con una combinación de idioma, etiqueta de feed y el ID de la oferta, con el formatocontentLanguage~feedLabel~offerId, comoen~US~sku12345. La API de Merchant usa este identificador para compilar nombres de recursosproductyproductInput, por ejemplo,accounts/12345/products/en~US~SKU12345. - Debes
codificar
la parte del identificador
en~US~SKU12345si alguna parte del identificador del producto, como offerId, contiene caracteres reservados para URL o caracteres que usa la API de Merchant, como/,%o~. Para obtener más información, consulta el campoProductInput.name. La parte del identificadoren~US~SKU12345debe estar codificada como URL cuando se incluye en una URL de solicitud.
Requisitos previos
Antes de agregar o administrar productos con la API, debes tener al menos una fuente de datos configurada en tu cuenta de Merchant Center.
Para crear una fuente de datos, usa el método dataSources.create de la API secundaria de fuentes de datos. Para ayudarte a decidir qué tipo de fuente de datos crear, consulta Elige tu estrategia de fuentes de datos y Administra las fuentes de datos de la API para subir productos.
Después de crear una fuente de datos, toma nota de su name (por ejemplo,
accounts/12345/dataSources/67890), ya que la necesitarás para las solicitudes de creación,
actualización o eliminación relacionadas con los productos.
Las fuentes de datos recién creadas se habilitan de forma predeterminada para todos los destinos (también llamados métodos de marketing) que están disponibles para la cuenta. Para obtener más información sobre los destinos posibles, consulta ¿Qué son los métodos de marketing?
Para obtener más información sobre las fuentes de datos, consulta la guía Administra fuentes de datos de la API para subir productos.
Agregar productos
Para agregar un producto nuevo a tu cuenta de Merchant Center, debes insertar un recurso ProductInput en una fuente de datos principal. Esta acción crea el
producto y comienza el procesamiento. Los campos dentro del objeto productAttributes
deben cumplir con las
especificaciones de datos de productos.
Usa el método
productInputs.insert
y proporciona el name de tu fuente de datos principal como el parámetro
dataSource.
En el siguiente ejemplo, se inserta un producto nuevo para una tienda en línea en una fuente de datos principal. El producto tiene algunos atributos, como los siguientes:
- un
title - un
description - un vínculo a una imagen en el campo
imageLink - Vínculos a videos del producto en el campo
videoLinks - Información de
availability - Información de
price - información del producto
condition - Información sobre los códigos comerciales globales de artículos (GTIN)
Para obtener más información sobre los atributos de producto, consulta ProductAttributes.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
"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",
"imageLink": "https://www.example.com/img/SKU12345.jpg",
"videoLinks": [
"https://www.example.com/videos/SKU12345_1.mp4",
"https://www.example.com/videos/SKU12345_2.mp4"
],
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000", // 15.99 USD
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": ["9780007350896", "93433295494587"]
}
}
Una llamada correcta devuelve el recurso ProductInput recién creado. El campo name
contiene el identificador único de esta entrada de producto, y el campo product
contiene el nombre del producto final procesado que puedes usar más adelante para
recuperarlo.
Los campos que se devuelven en una respuesta
productInputs.insert
reflejan los valores de entrada. Los valores procesados que se conservarán
en el productAttributes resultante pueden variar.
{
"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",
"imageLink": "https://www.example.com/img/SKU12345.jpg",
"videoLinks": [
"https://www.example.com/videos/SKU12345_1.mp4",
"https://www.example.com/videos/SKU12345_2.mp4"
],
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": [
"9780007350896"
]
}
}
En las siguientes muestras de código, se indica cómo agregar un producto.
Java
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to insert a product input */
public class InsertProductInputSample {
private static String getParent(String accountId) {
return String.format("accounts/%s", accountId);
}
public static ProductInput insertProductInput(Config config, String dataSource) 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 parent to identify where to insert the product.
String parent = getParent(config.getAccountId().toString());
try (ProductInputsServiceClient productInputsServiceClient =
ProductInputsServiceClient.create(productInputsServiceSettings)) {
// Price to be used for shipping ($33.45).
Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();
Shipping shipping =
Shipping.newBuilder()
.setPrice(price)
.setCountry("GB")
.setService("1st class post")
.build();
Shipping shipping2 =
Shipping.newBuilder()
.setPrice(price)
.setCountry("FR")
.setService("1st class post")
.build();
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)
.setGoogleProductCategory("Media > Books")
.addGtins("9780007350896")
.addShipping(shipping)
.addShipping(shipping2)
.build();
// The datasource can be either a primary or supplemental datasource.
InsertProductInputRequest request =
InsertProductInputRequest.newBuilder()
.setParent(parent)
// You can only insert products into datasource types of Input "API" and "FILE", and
// of Type "Primary" or "Supplemental."
// This field takes the `name` field of the datasource.
.setDataSource(dataSource)
// If this product is already owned by another datasource, when re-inserting, the
// new datasource will take ownership of the product.
.setProductInput(
ProductInput.newBuilder()
.setContentLanguage("en")
.setFeedLabel("GB")
.setOfferId("sku123")
.setProductAttributes(attributes)
.build())
.build();
System.out.println("Sending insert ProductInput request");
ProductInput response = productInputsServiceClient.insertProductInput(request);
System.out.println("Inserted 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("Inserted Product Name below");
System.out.println(response.getProduct());
return response;
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
// Identifies the data source that will own the product input.
String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{INSERT_DATASOURCE_ID}";
insertProductInput(config, dataSource);
}
}
PHP
use Google\ApiCore\ApiException;
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\InsertProductInputRequest;
use Google\Shopping\Merchant\Products\V1\ProductInput;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\Shipping;
use Google\Shopping\Type\Price;
/**
* Uploads a product input to your Merchant Center account.
*/
class InsertProductInput
{
// ENSURE you fill in the datasource ID for the sample to work.
private const DATASOURCE = 'INSERT_DATASOURCE_ID';
/**
* A helper function to create the parent string.
*
* @param array $accountId
* The account that owns the product.
*
* @return string The parent has the format: `accounts/{account_id}`
*/
private static function getParent($accountId)
{
return sprintf("accounts/%s", $accountId);
}
/**
* Uploads a product input to your Merchant Center account. If an input
* with the same feedLabel, contentLanguage, offerId, and dataSource
* already exists, this method replaces that entry.
*
* After inserting, updating, or deleting a product input, it may take several
* minutes before the processed product can be retrieved.
*
* @param array $config
* The configuration data used for authentication and getting the acccount
* ID.
* @param string $dataSource
* The primary or supplemental product data source name. If the
* product already exists and data source provided is different, then the
* product will be moved to a new data source.
* Format: `accounts/{account}/dataSources/{datasource}`.
*
* @return void
*/
public static function insertProductInputSample($config, $dataSource): 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 client.
$productInputsServiceClient = new ProductInputsServiceClient($options);
// Creates parent to identify where to insert the product.
$parent = self::getParent($config['accountId']);
// Calls the API and catches and prints any network failures/errors.
try {
// Price to be used for shipping ($33.45).
$price = new Price(
[
'amount_micros' => 33450000,
'currency_code' => 'USD'
]
);
$shipping = new Shipping(
[
'price' => $price,
'country' => 'GB',
'service' => '1st class post'
]
);
$shipping2 = new Shipping(
[
'price' => $price,
'country' => 'FR',
'service' => '1st class post'
]
);
// Creates the attributes of the product.
$attributes = new ProductAttributes(
[
'title' => 'A Tale of Two Cities',
'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,
'google_product_category' => 'Media > Books',
'gtins' => ['9780007350896'],
'shipping' => [$shipping, $shipping2]
]
);
// Creates the productInput with the fundamental identifiers.
$productInput = new ProductInput(
[
'content_language' => 'en',
'feed_label' => 'label',
'offer_id' => 'sku123ABCD',
'product_attributes' => $attributes
]
);
// Prepares the request message.
$request = new InsertProductInputRequest(
[
'parent' => $parent,
'data_source' => $dataSource,
'product_input' => $productInput
]
);
print "Sending insert ProductInput request\n";
$response = $productInputsServiceClient->insertProductInput($request);
print "Inserted ProductInput Name below\n";
print $response->getName() . "\n";
print "Inserted Product Name below\n";
print $response->getProduct() . "\n";
} catch (ApiException $e) {
print $e->getMessage();
}
}
/**
* Helper to execute the sample.
*
* @return void
*/
public function callSample(): void
{
$config = Config::generateConfig();
// Identifies the data source that will own the product input.
$dataSource = sprintf(
"accounts/%s/dataSources/%s",
$config['accountId'],
self::DATASOURCE
);
// Makes the call to insert a product to the MC account.
self::insertProductInputSample($config, $dataSource);
}
}
// Run the script
$sample = new InsertProductInput();
$sample->callSample();
Python
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1
from google.shopping.merchant_products_v1 import Availability
from google.shopping.merchant_products_v1 import Condition
from google.shopping.type import Price
def create_product_input():
"""Creates a `ProductInput` resource."""
# Creates a shipping setting
price = Price()
price.amount_micros = 33_450_000
price.currency_code = "GBP"
shipping_option_1 = merchant_products_v1.Shipping()
shipping_option_1.price = price
shipping_option_1.country = "GB"
shipping_option_1.service = "1st class post"
price2 = Price()
price2.amount_micros = 33_450_000
price2.currency_code = "EUR"
shipping_option_2 = merchant_products_v1.Shipping()
shipping_option_2.price = price2
shipping_option_2.country = "FR"
shipping_option_2.service = "2nd class post"
# Sets product attributes. Make sure to replace these values with your own.
attributes = merchant_products_v1.ProductAttributes()
attributes.title = "A Tale of Two Cities"
attributes.description = "A classic novel about the French Revolution"
attributes.link = "https://exampleWebsite.com/tale-of-two-cities.html"
attributes.image_link = "https://exampleWebsite.com/tale-of-two-cities.jpg"
attributes.price = price
attributes.availability = Availability.IN_STOCK
attributes.condition = Condition.NEW
attributes.google_product_category = "Media > Books"
attributes.gtins = ["9780007350896"]
attributes.shipping = [shipping_option_1, shipping_option_2]
return merchant_products_v1.ProductInput(
content_language="en",
feed_label="GB",
offer_id="sku123",
product_attributes=attributes,
)
def insert_product_input(account_id: str, data_source: str):
"""Inserts the specified `ProductInput` resource.
Args:
account_id: The Merchant Center account ID.
data_source: The resource name of the data source that will own the product
input.
Returns:
The inserted `ProductInput` resource.
"""
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client.
client = merchant_products_v1.ProductInputsServiceClient(
credentials=credentials
)
parent = f"accounts/{account_id}"
# Creates the request.
request = merchant_products_v1.InsertProductInputRequest(
parent=parent,
# If this product is already owned by another datasource, when
# re-inserting, the new datasource will take ownership of the product.
product_input=create_product_input(),
data_source=data_source,
)
# Makes the request and catches and prints any error messages.
try:
response = client.insert_product_input(request=request)
# 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`
print(f"Input successful: {response}")
return response
except RuntimeError as e:
print("Input failed")
print(e)
# After the product is inserted, the product ID will be returned in the
# response. We recommend that you check the Merchant Center to ensure that
# the product is approved and visible to users before using the product ID
# in any downstream processes.
raise
if __name__ == "__main__":
# Retrieves the Merchant Center account ID from the configuration file.
merchant_account_id = configuration.Configuration().read_merchant_info()
# Identifies the data source that will own the product input.
# You can only insert products into datasource types of Input "API" and
# "FILE", and of Type "Primary" or "Supplemental."
target_data_source = (
f"accounts/{merchant_account_id}/dataSources/[INSERT_DATA_SOURCE_HERE]"
)
insert_product_input(merchant_account_id, target_data_source)
Apps_Script
/**
* Inserts a product into the products list. Logs the API response.
*/
function productInsert() {
// IMPORTANT:
// Enable the Merchant API Products sub-API Advanced Service and call it
// "MerchantApiProducts"
// Replace this with your Merchant Center ID.
const accountId = 'INSERT_MERCHANT_ID';
// Replace this with the Data Source ID you want to use.
const dataSourceId = 'INSERT_DATASOURCE_ID';
// Construct the parent name
const parent = 'accounts/' + accountId;
// Construct the Data Source name
const dataSource = parent + '/dataSources/' + dataSourceId;
// Create a product resource and insert it
const productResource = {
'offerId': 'fromAppsScript',
'contentLanguage': 'en',
'feedLabel': 'US',
'productAttributes': {
'title': 'A Tale of Two Cities',
'description': 'A classic novel about the French Revolution',
'link': 'http://my-book-shop.com/tale-of-two-cities.html',
'imageLink': 'http://my-book-shop.com/tale-of-two-cities.jpg',
'availability': 'IN_STOCK',
'condition': 'new',
'googleProductCategory': 'Media > Books',
'gtins': '[9780007350896]',
'price': {'amountMicros': '2500000', 'currencyCode': 'USD'},
},
};
try {
console.log('Sending insert ProductInput request');
// Call the ProductInputs.insert API method.
const response = MerchantApiProducts.Accounts.ProductInputs.insert(
productResource, parent, {dataSource});
// RESTful insert returns the JSON object as a response.
console.log('Inserted ProductInput below');
console.log(response);
} catch (e) {
console.log('ERROR!');
console.log(e);
}
}
cURL
curl -X POST \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"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",
"imageLink": "https://www.example.com/img/SKU12345.jpg",
"videoLinks": [
"https://www.example.com/videos/SKU12345_1.mp4",
"https://www.example.com/videos/SKU12345_2.mp4"
],
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": ["9780007350896"]
}
}'
Agrega o actualiza la información del producto con una fuente de datos complementaria
Usa una fuente de datos complementaria para proporcionar datos adicionales o anular los datos de los productos que ya existen en una fuente de datos principal. Esto es útil para agregar información, como promociones o etiquetas personalizadas, o para anular datos de productos específicos sin modificar la entrada original del producto.
Para ello, usa el método
productInput.insert,
pero especifica el name de tu fuente de datos complementaria en el
parámetro dataSource. Verifica que offerId, contentLanguage y
feedLabel coincidan con un producto existente.
En este ejemplo, se agrega una etiqueta personalizada a un producto existente con una fuente de datos complementaria.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{SUPPLEMENTAL_DATASOURCE_ID}
{
"offerId": "SKU12345",
"contentLanguage": "en",
"feedLabel": "US",
"productAttributes": {
"customLabel0": "clearance-sale"
}
}
Después de esta llamada, el Product final tendrá customLabel0 establecido en
clearance-sale, suponiendo que la fuente de datos complementaria tenga una prioridad más alta
que la fuente de datos principal en tus reglas del feed, según lo define
default_rule.
Agrega productos de forma asíncrona
Para subir una gran cantidad de productos de manera eficiente, puedes enviar varias solicitudes de inserción de forma simultánea. En lugar de esperar una respuesta para cada solicitud antes de enviar la siguiente, puedes enviarlas de forma asíncrona y controlar las respuestas a medida que lleguen. Este enfoque puede mejorar significativamente la capacidad de procesamiento de la carga de datos.
En las siguientes muestras de código, se indica cómo insertar productos de forma asíncrona. Para obtener información sobre cómo realizar varias solicitudes a la vez con curl, consulta Envía varias solicitudes a la vez.
Java
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.grpc.ChannelPoolSettings;
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to insert a product input */
public class InsertProductInputAsyncSample {
private static String getParent(String accountId) {
return String.format("accounts/%s", accountId);
}
private static String generateRandomString() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder(8);
for (int i = 0; i < 8; i++) {
sb.append(characters.charAt(random.nextInt(characters.length())));
}
return sb.toString();
}
private static ProductInput createRandomProduct() {
Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();
Shipping shipping =
Shipping.newBuilder().setPrice(price).setCountry("GB").setService("1st class post").build();
Shipping shipping2 =
Shipping.newBuilder().setPrice(price).setCountry("FR").setService("1st class post").build();
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)
.setGoogleProductCategory("Media > Books")
.addGtins("9780007350896")
.addShipping(shipping)
.addShipping(shipping2)
.build();
return ProductInput.newBuilder()
.setContentLanguage("en")
.setFeedLabel("CH")
.setOfferId(generateRandomString())
.setProductAttributes(attributes)
.build();
}
public static void asyncInsertProductInput(Config config, String dataSource) throws Exception {
// Obtains OAuth token based on the user's configuration.
GoogleCredentials credential = new Authenticator().authenticate();
// Creates a channel provider. This provider manages a pool of gRPC channels
// to enhance throughput for bulk operations. Each individual channel in the pool
// can handle up to approximately 100 concurrent requests.
//
// Channel: A single connection pathway to the service.
// Pool: A collection of multiple channels managed by this provider.
// Requests are distributed across the channels in the pool.
//
// We recommend estimating the number of concurrent requests you'll make, divide by 50 (50%
// utilization of channel capacity), and set the pool size to that number.
InstantiatingGrpcChannelProvider channelProvider =
InstantiatingGrpcChannelProvider.newBuilder()
.setChannelPoolSettings(ChannelPoolSettings.staticallySized(30))
.build();
// Creates service settings using the credentials retrieved above.
ProductInputsServiceSettings productInputsServiceSettings =
ProductInputsServiceSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(credential))
.setTransportChannelProvider(channelProvider)
.build();
// Creates parent to identify where to insert the product.
String parent = getParent(config.getAccountId().toString());
// Calls the API and catches and prints any network failures/errors.
try (ProductInputsServiceClient productInputsServiceClient =
ProductInputsServiceClient.create(productInputsServiceSettings)) {
// Creates five insert product input requests with random product IDs.
List<InsertProductInputRequest> requests = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
InsertProductInputRequest request =
InsertProductInputRequest.newBuilder()
.setParent(parent)
// You can only insert products into datasource types of Input "API", and of Type
// "Primary" or "Supplemental."
// This field takes the `name` field of the datasource.
.setDataSource(dataSource)
// If this product is already owned by another datasource, when re-inserting, the
// new datasource will take ownership of the product.
.setProductInput(createRandomProduct())
.build();
requests.add(request);
}
System.out.println("Sending insert product input requests");
List<ApiFuture<ProductInput>> futures =
requests.stream()
.map(
request ->
productInputsServiceClient.insertProductInputCallable().futureCall(request))
.collect(Collectors.toList());
// Creates callback to handle the responses when all are ready.
ApiFuture<List<ProductInput>> responses = ApiFutures.allAsList(futures);
ApiFutures.addCallback(
responses,
new ApiFutureCallback<List<ProductInput>>() {
@Override
public void onSuccess(List<ProductInput> results) {
System.out.println("Inserted products below");
System.out.println(results);
}
@Override
public void onFailure(Throwable throwable) {
System.out.println(throwable);
}
},
MoreExecutors.directExecutor());
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
// Identifies the data source that will own the product input.
String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{datasourceId}";
asyncInsertProductInput(config, dataSource);
}
}
Python
import asyncio
import os
import random
import string
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping.merchant_products_v1 import Availability
from google.shopping.merchant_products_v1 import Condition
from google.shopping.merchant_products_v1 import InsertProductInputRequest
from google.shopping.merchant_products_v1 import ProductAttributes
from google.shopping.merchant_products_v1 import ProductInput
from google.shopping.merchant_products_v1 import ProductInputsServiceAsyncClient
from google.shopping.merchant_products_v1 import Shipping
from google.shopping.type import Price
# Enable gRPC connection scaling.
os.environ["GRPC_EXPERIMENTAL_MAX_CONCURRENT_STREAMS_CONNECTION_SCALING"] = (
"true"
)
os.environ["GRPC_EXPERIMENTS"] = "subchannel_connection_scaling"
# Read merchant account information from the configuration file.
_ACCOUNT_ID = configuration.Configuration().read_merchant_info()
# The parent account for the product input.
# Format: accounts/{account}
_PARENT = f"accounts/{_ACCOUNT_ID}"
def _generate_random_string(length: int = 8) -> str:
"""Generates a random string of a given length."""
characters = string.ascii_letters + string.digits
return "".join(random.choice(characters) for _ in range(length))
def _create_random_product() -> ProductInput:
"""Creates a ProductInput with random elements and predefined attributes."""
price = Price(amount_micros=33450000, currency_code="USD")
shipping1 = Shipping(price=price, country="GB", service="1st class post")
shipping2 = Shipping(price=price, country="FR", service="1st class post")
attributes = ProductAttributes(
title="A Tale of Two Cities",
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,
google_product_category="Media > Books",
gtins=["9780007350896"],
shipping=[shipping1, shipping2],
)
return ProductInput(
content_language="en",
feed_label="CH",
offer_id=_generate_random_string(),
product_attributes=attributes,
)
class ClientPool:
"""A simple client pool to distribute requests across multiple clients.
This implements the Client Pool pattern to enhance throughput for bulk
operations, mimicking channel pooling.
"""
def __init__(self, size: int, credentials):
self._pool = [
ProductInputsServiceAsyncClient(credentials=credentials)
for _ in range(size)
]
self._size = size
self._index = 0
def get_client(self) -> ProductInputsServiceAsyncClient:
"""Returns the next client in the pool using round-robin."""
client = self._pool[self._index]
self._index = (self._index + 1) % self._size
return client
async def async_insert_product_input(
client: ProductInputsServiceAsyncClient, request: InsertProductInputRequest
):
"""Inserts product inputs.
Args:
client: The ProductInputsServiceAsyncClient to use.
request: The InsertProductInputRequest to send.
Returns:
The response from the insert_product_input request.
"""
return await client.insert_product_input(request=request)
async def main():
# The ID of the data source that will own the product input.
# This is a placeholder and should be replaced with an actual data source ID.
datasource_id = "<INSERT_DATA_SOURCE_ID_HERE>"
data_source_name = f"accounts/{_ACCOUNT_ID}/dataSources/{datasource_id}"
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client pool with 30 clients to handle concurrent requests.
# We recommend estimating the number of concurrent requests you'll make,
# divide by 50 (50% utilization of channel capacity), and set the pool size to
# that number.
client_pool = ClientPool(size=30, credentials=credentials)
tasks = []
for _ in range(5):
product_input = _create_random_product()
request = InsertProductInputRequest(
parent=_PARENT,
data_source=data_source_name,
product_input=product_input,
)
# Get a client from the pool and create the async task
client = client_pool.get_client()
insert_product_task = asyncio.create_task(
async_insert_product_input(client, request)
)
tasks.append(insert_product_task)
print("Sending insert product input requests")
try:
# Await all tasks to complete concurrently and gather their results
results = await asyncio.gather(*tasks)
print("Inserted products below")
print(results)
except RuntimeError as e:
# Catch and print any exceptions that occur during the API calls.
print(e)
if __name__ == "__main__":
asyncio.run(main())
Agrega productos segmentados para países específicos
Puedes configurar la segmentación por país para productos individuales y, así, anular la configuración de la fuente de datos o segmentar productos cuando la fuente de datos no tenga países definidos.
Países objetivo con el atributo shipping
Si tu fuente de datos no tiene definidos países específicos, puedes segmentar
los países para un producto proporcionando el campo shipping dentro de
productAttributes. Este campo te permite especificar los costos y las reglas de envío para
diferentes países, lo que los segmenta de forma implícita para la publicación.
En este ejemplo, se segmenta un producto para EE.UU. y Canadá proporcionando dos entradas
shipping independientes.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
"offerId": "SKU_SHIP_TARGET",
"contentLanguage": "en",
"feedLabel": "GLOBAL",
"productAttributes": {
"title": "Global T-Shirt",
"link": "https://www.example.com/p/SKU_SHIP_TARGET",
"imageLink": "https://www.example.com/img/SKU_SHIP_TARGET.jpg",
"availability": "IN_STOCK",
"price": {
"amountMicros": "25990000",
"currencyCode": "USD"
},
"shipping": [
{
"country": "US",
"price": {
"amountMicros": "5990000",
"currencyCode": "USD"
}
},
{
"country": "CA",
"price": {
"amountMicros": "10990000",
"currencyCode": "CAD"
}
}
]
}
}
Excluye países y destinos
Si tu fuente de datos ya está segmentada para varios países, puedes excluir un producto para que no se muestre en un subconjunto de esos países o en destinos específicos.
- Usa el atributo
shoppingAdsExcludedCountriespara evitar que un producto aparezca en los anuncios de Shopping de países específicos. - Usa el atributo
excludedDestinationspara evitar que un producto aparezca en métodos de marketing específicos, comoFreeListings.
En este ejemplo, se supone que la segmentación de la fuente de datos incluye a EE.UU., Canadá y México. La solicitud excluye el producto de los anuncios de Shopping en México y del destino de fichas gratuitas por completo.
POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
"offerId": "SKU_EXCLUDE_TARGET",
"contentLanguage": "en",
"feedLabel": "NA",
"productAttributes": {
"title": "North America T-Shirt",
"link": "https://www.example.com/p/SKU_EXCLUDE_TARGET",
"imageLink": "https://www.example.com/img/SKU_EXCLUDE_TARGET.jpg",
"availability": "IN_STOCK",
"price": {
"amountMicros": "19990000",
"currencyCode": "USD"
},
"shoppingAdsExcludedCountries": ["MX"],
"excludedDestinations": ["FREE_LISTINGS"]
}
}
Productos segmentados para destinos específicos
Puedes usar un solo producto para segmentar anuncios para los tipos de destino en línea y locales. Esta función te permite aprovechar la estrategia de varios canales en las campañas de Shopping.
Puedes controlar la segmentación de un producto con las siguientes opciones:
- la configuración si su fuente de datos
- su configuración a nivel del producto individual
Todos los destinos
La segmentación por productos predeterminada admite todos los destinos, de forma similar a la segmentación predeterminada de las fuentes de datos, según tu participación en el programa.
Solo en línea o solo local
Si quieres que un producto esté disponible exclusivamente a través de canales en línea o solo en tiendas físicas, haz lo siguiente:
- Nivel de la fuente de datos: Configura los destinos (también conocidos como métodos de marketing) de tu fuente de datos para que sean solo en línea o locales. Por ejemplo, los anuncios del inventario local y las fichas locales gratuitas son destinos locales. Para obtener más información sobre cómo y dónde se muestran tus productos en Google a los clientes potenciales, consulta ¿Qué son los métodos de marketing? y Descripción general de los anuncios del inventario local y las fichas locales gratuitas.
- A nivel del producto: Independientemente de la configuración de la fuente de datos, puedes segmentar tus productos para destinos específicos a nivel del producto. Establece el
includedDestinationssolo en destinos en línea o locales. Como alternativa, puedes usarexcludedDestinationspara especificar a qué destinos no segmentar. Por ejemplo, puedes usarexcludedDestinationspara evitar que un producto en línea aparezca en destinos locales.
- Información en la tienda para productos locales: Si segmentas tus anuncios para tipos de destinos locales en algunos de tus productos, debes especificar la información en la tienda para ellos. Para obtener más información sobre cómo agregar datos de la tienda a tus productos locales, consulta Inserta información de la tienda.
Obtener información sobre productos
Para recuperar el estado final procesado de un producto, usa el método
products.get. Este método devuelve el recurso Product, que incluye todos los
productAttributes después de que se aplicaron las reglas del feed y las fuentes de datos complementarias, junto con su estado de validación actual.
Puede haber una demora de unos minutos entre el momento en que insertas o actualizas un
ProductInput y el momento en que el Product final está disponible para recuperarlo.
GET https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}
Una solicitud correcta devuelve el recurso Product.
{
"name": "accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}}",
"offerId": "SKU12345",
"contentLanguage": "en",
"feedLabel": "US",
"dataSource": "accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}",
"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",
"imageLink": "https://www.example.com/img/SKU12345.jpg",
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": [
"9780007350896"
]
},
"productStatus": {
"destinationStatuses": [
{
"reportingContext": "SHOPPING_ADS",
"approvedCountries": [
"US"
]
}
],
"creationDate": "2024-05-20T10:00:00Z",
"lastUpdateDate": "2024-05-20T10:05:00Z",
"googleExpirationDate": "2024-06-19T10:05:00Z"
}
}
En las siguientes muestras de código, se indica cómo obtener un producto.
Java
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.io.BaseEncoding;
import com.google.shopping.merchant.products.v1.GetProductRequest;
import com.google.shopping.merchant.products.v1.Product;
import com.google.shopping.merchant.products.v1.ProductsServiceClient;
import com.google.shopping.merchant.products.v1.ProductsServiceSettings;
import java.nio.charset.StandardCharsets;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to get a single product for a given Merchant Center account */
public class GetProductSample {
// Base64Url encoder/decoder without padding
private static final BaseEncoding BASE64URL_NOPADDING = BaseEncoding.base64Url().omitPadding();
// Encodes a string to base64url without padding
public static String encodeProductId(String productId) {
return BASE64URL_NOPADDING.encode(productId.getBytes(StandardCharsets.UTF_8));
}
public static Product getProduct(Config config, String accountId, String productId)
throws Exception {
// Obtains OAuth token based on the user's configuration.
GoogleCredentials credential = new Authenticator().authenticate();
// Creates service settings using the credentials retrieved above.
ProductsServiceSettings productsServiceSettings =
ProductsServiceSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(credential))
.build();
try (ProductsServiceClient productsServiceClient =
ProductsServiceClient.create(productsServiceSettings)) {
// The name has the format: accounts/{account}/products/{productId}
String name = "accounts/" + accountId + "/products/" + productId;
// The name has the format: accounts/{account}/products/{productId}
GetProductRequest request = GetProductRequest.newBuilder().setName(name).build();
System.out.println("Sending get product request:");
Product response = productsServiceClient.getProduct(request);
System.out.println("Retrieved Product below");
System.out.println(response);
return response;
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
String accountId = config.getAccountId().toString();
// The name of the `product`, returned after a `Product.insert` request. We recommend
// having stored this value in your database to use for all future requests.
String productId = "en~GB~sku123"; // Replace with your actual product ID
// Uncomment the following line if the product name contains special characters (such as forward
// slashes) and needs base64url encoding.
// productId = encodeProductId(productId);
getProduct(config, accountId, productId);
}
}
PHP
require_once __DIR__ . '/../../../vendor/autoload.php';
require_once __DIR__ . '/../../Authentication/Authentication.php';
require_once __DIR__ . '/../../Authentication/Config.php';
use Google\ApiCore\ApiException;
use Google\Shopping\Merchant\Products\V1\Client\ProductsServiceClient;
use Google\Shopping\Merchant\Products\V1\GetProductRequest;
/**
* This class demonstrates how to get a single product for a given Merchant
* Center account.
*/
class GetProductSample
{
/**
* A helper function to create the product name string.
*
* @param string $accountId
* The account that owns the product.
* @param string $productId
* The ID of the product.
*
* @return string The name has the format: `accounts/{account}/products/{product}`
*/
private static function getName(string $accountId, string $productId): string
{
return sprintf("accounts/%s/products/%s", $accountId, $productId);
}
/**
* Encodes a string to base64url without padding. This is needed if the
* product ID contains special characters (such as forward slashes) and
* needs base64url encoding.
*
* @param string $productId
* The ID of the product.
*
* @return string The encoded product ID.
*/
public static function encodeProductId(string $productId): string
{
return rtrim(strtr(base64_encode($productId), '+/', '-_'), '=');
}
/**
* Retrieves a product from your Merchant Center account.
*
* @param array $config
* The configuration data used for authentication and getting the
* account ID.
* @param string $productId
* The ID of the product, in the form of
* `contentLanguage~feedLabel~offerId`.
*
* @return void
*/
public static function getProduct(array $config, string $productId): 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 client.
$productsServiceClient = new ProductsServiceClient($options);
// The name has the format: accounts/{account}/products/{productId}
$name = self::getName($config['accountId'], $productId);
// Creates the request.
$request = new GetProductRequest([
'name' => $name
]);
// Calls the API and catches and prints any network failures/errors.
try {
print "Sending get product request:\n";
$response = $productsServiceClient->getProduct($request);
print "Retrieved Product below\n";
// Pretty-prints the JSON representation of the response.
print $response->serializeToJsonString(true) . "\n";
} catch (ApiException $e) {
printf("Call failed with message: %s\n", $e->getMessage());
}
}
/**
* Helper to execute the sample.
*
* @return void
*/
public function callSample(): void
{
$config = Config::generateConfig();
// The name of the `product`, returned after a `Product.insert` request.
// We recommend having stored this value in your database to use for all
// future requests.
$productId = 'en~US~sku123'; // Replace with your actual product ID
// Uncomment the following line if the product name contains special
// characters (such as forward slashes) and needs base64url encoding.
// $productId = self::encodeProductId($productId);
self::getProduct($config, $productId);
}
}
// Runs the sample.
$sample = new GetProductSample();
$sample->callSample();
Python
import base64
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping.merchant_products_v1 import GetProductRequest
from google.shopping.merchant_products_v1 import Product
from google.shopping.merchant_products_v1 import ProductsServiceClient
# This is needed for base64url encoding if product IDs contain special
# characters such as forward slashes.
def encode_product_id(product_id_to_encode: str) -> str:
"""Base64url encodes a string without padding.
Args:
product_id_to_encode: The product ID string to encode.
Returns:
The encoded product ID string.
"""
encoded_bytes = base64.urlsafe_b64encode(product_id_to_encode.encode("utf-8"))
return encoded_bytes.rstrip(b"=").decode("utf-8")
def get_product(account_id_arg: str, product_id_arg: str) -> Product:
"""Retrieves a single product from a Merchant Center account.
Args:
account_id_arg: The ID of the Merchant Center account.
product_id_arg: The ID of the product to retrieve.
Returns:
The retrieved `Product` resource.
"""
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client.
client = ProductsServiceClient(credentials=credentials)
# The name has the format: accounts/{account}/products/{product}
name = f"accounts/{account_id_arg}/products/{product_id_arg}"
# Creates the request.
request = GetProductRequest(name=name)
print("Sending get product request:")
# Makes the request and catches and prints any error messages.
try:
response = client.get_product(request=request)
print("Retrieved Product below")
print(response)
return response
except RuntimeError as e:
print(e)
raise
if __name__ == "__main__":
# Retrieves the configured account ID from the config file.
account_id = configuration.Configuration().read_merchant_info()
# The ID of the product, which is the final component of the product's
# resource name. The product ID is the same as the offer ID.
# For example, `en~US~sku123`.
product_id = "en~US~sku123" # Replace with your actual product ID.
# Uncomment the following line if the product ID contains special characters
# (such as forward slashes) and needs base64url encoding.
# product_id = encode_product_id(product_id)
get_product(account_id, product_id)
Apps_Script
/**
* Get a specific product for a given Merchant Center account.
*/
function getProduct() {
// IMPORTANT:
// Enable the Merchant API Products sub-API Advanced Service and call it
// "MerchantApiProducts"
// Replace this with your Merchant Center ID.
const accountId = '<MERCHANT_CENTER_ID>';
// The ID of the product to retrieve.
// 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.
const productId = '<PRODUCT_ID>';
// Construct the parent name
const parent = 'accounts/' + accountId;
// Construct the product resource name
const name = parent + '/products/' + productId;
try {
console.log('Sending get Product request');
// Call the Products.get API method.
const product = MerchantApiProducts.Accounts.Products.get(name);
console.log(product);
} catch (e) {
console.log('ERROR!');
console.log(e);
}
}
cURL
curl -X GET \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/{PRODUCT_ID}" \
-H "Authorization: Bearer <API_TOKEN>"
Cómo borrar un producto de una fuente de datos
Para borrar una entrada de producto de una fuente de datos específica, usa el método
productInputs.delete.
- Si borras un producto de una fuente de datos principal, se quitará todo el producto,
incluidos sus
productInputscomplementarios, de Merchant Center. - Si borras un producto de una fuente de datos complementaria, solo se quitarán los atributos de esa fuente de datos. El producto en sí permanece, y se obtiene de la fuente de datos principal y de cualquier otra fuente de datos complementaria.
Debes especificar el dataSource del que borrarás la entrada de producto.
DELETE https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/{PRODUCT_ID}?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
Una llamada correcta devuelve una respuesta vacía.
En las siguientes muestras de código, se indica cómo borrar un producto.
Java
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1.DeleteProductInputRequest;
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 shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to delete a product for a given Merchant Center account */
public class DeleteProductInputSample {
public static void deleteProductInput(Config config, String productId, String dataSource)
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();
// Calls the API and catches and prints any network failures/errors.
try (ProductInputsServiceClient productInputsServiceClient =
ProductInputsServiceClient.create(productInputsServiceSettings)) {
DeleteProductInputRequest request =
DeleteProductInputRequest.newBuilder().setName(name).setDataSource(dataSource).build();
System.out.println("Sending deleteProductInput request");
productInputsServiceClient.deleteProductInput(request); // no response returned on success
System.out.println(
"Delete successful, note that it may take a few minutes for the delete to update in"
+ " the system. If you make a products.get or products.list request before a few"
+ " minutes have passed, the old product data may be returned.");
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
// An ID assigned to a product input by Google. In the format
// contentLanguage~feedLabel~offerId
String productId = "en~GB~sku123";
// The name of the dataSource from which to delete the product. If it is a primary feed, this
// will delete the product completely. If it's a supplemental feed, it will only delete the
// product information from that feed, but the product will still be available from the primary
// feed.
String dataSource = "accounts/{account}/dataSources/{dataSource}";
deleteProductInput(config, productId, dataSource);
}
}
PHP
use Google\ApiCore\ApiException;
use Google\Auth\CredentialsLoader;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\DeleteProductInputRequest;
use Google\Shopping\Merchant\Products\V1\ProductInputName;
/**
* This class demonstrates how to delete a productinput for a given Merchant Center
* account.
*/
class DeleteProductInput
{
// ENSURE you fill in the product and datasource ID for the sample to work.
// An ID assigned to a product by Google:
// In the format `contentLanguage~feedLabel~offerId`
private const PRODUCT = 'INSERT_PRODUCT_ID_HERE';
private const DATASOURCE = 'INSERT_DATASOURCE_ID_HERE';
/**
* Deletes a product input to your Merchant Center account.
*
* @param array $config
* The configuration data used for authentication and getting the
* acccount ID.
* @param string $product
* The product ID to delete.
* Format: `accounts/{account}/products/{productId}`.
* @param string $dataSource
* The primary or supplemental product data source name that owns the
* product.
* Format: `accounts/{account}/dataSources/{datasource}`.
*
* @return void
*/
public static function deleteProductInputSample(
$config, $product, $dataSource
): void {
// Obtains OAuth token based on the user's configuration.
$credentials = Authentication::useServiceAccountOrTokenFile();
// Creates service settings using the credentials retrieved above.
$options = ['credentials' => $credentials];
$productInputsServiceClient = new ProductInputsServiceClient($options);
// Calls the API and catches and prints any network failures/errors.
try {
$request = new DeleteProductInputRequest(
[
'name' => $product,
'data_source' => $dataSource
]
);
echo "Sending deleteProductInput request\n";
$productInputsServiceClient->deleteProductInput($request);
echo "Delete successful, note that it may take a few minutes for the "
. "delete to update in the system. If you make a products.get or "
. "products.list request before a few minutes have passed, the old "
. "product data may be returned.\n";
} catch (ApiException $e) {
echo "An error has occurred: \n";
echo $e->getMessage() . "\n";
}
}
/**
* Helper to execute the sample.
*
* @return void
*/
public function callSample(): void
{
$config = Config::generateConfig();
// The productID variable is defined at the top of the file.
$product = ProductInputsServiceClient::productInputName(
$config['accountId'],
self::PRODUCT
);
// The name of the dataSource from which to delete the product.
$dataSource = sprintf(
'accounts/%s/dataSources/%s',
$config['accountId'],
self::DATASOURCE
);
self::deleteProductInputSample($config, $product, $dataSource);
}
}
// Run the script.
$sample = new DeleteProductInput();
$sample->callSample();
Python
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1
def delete_product_input(account_id: str, product_id: str, data_source: str):
"""Deletes the specified `ProductInput` resource.
Args:
account_id: The Merchant Center account ID.
product_id: The ID of the product input to delete, in the format
`contentLanguage~feedLabel~offerId`.
data_source: The resource name of the data source from which to delete the
product.
"""
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client.
client = merchant_products_v1.ProductInputsServiceClient(
credentials=credentials
)
name = f"accounts/{account_id}/productInputs/{product_id}"
# Creates the request.
request = merchant_products_v1.DeleteProductInputRequest(
name=name, data_source=data_source
)
# Makes the request and catch and print any error messages.
try:
client.delete_product_input(request=request)
print("Deletion successful")
except RuntimeError as e:
print("Deletion failed")
print(e)
raise
if __name__ == "__main__":
# Retrieves the Merchant Center account ID from the configuration file.
merchant_account_id = configuration.Configuration().read_merchant_info()
# ENSURE you fill in the product ID and data source for the
# sample to work.
# In the format of `contentLanguage~feedLabel~offerId`
target_product = "[INSERT_PRODUCT_HERE]"
target_data_source = (
f"accounts/{merchant_account_id}/dataSources/[INSERT_DATA_SOURCE_HERE]"
)
delete_product_input(
merchant_account_id, target_product, target_data_source
)
cURL
curl -X DELETE \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/{PRODUCT_ID}?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \
-H "Authorization: Bearer <API_TOKEN>"