زیر-API Products به شما امکان میدهد کل چرخه عمر محصولات خود را در مرکز فروشندگان مدیریت کنید. میتوانید از آن برای آپلود محصولات جدید، بهروزرسانی محصولات موجود، بازیابی اطلاعات محصول و حذف محصولاتی که دیگر نمیفروشید استفاده کنید.
ملاحظات ویژه
- محصولات فقط در صورتی میتوانند درج، بهروزرسانی یا حذف شوند که متعلق به منابع داده از نوع
APIباشند. شما نمیتوانید محصولات را در منابع دادهای که از آپلودهای مبتنی بر فایل استفاده میکنند، درج یا بهروزرسانی کنید. - برای اینکه محصولاتتان مرتبط باقی بمانند و از منقضی شدن آنها جلوگیری شود، باید آنها را با یک ریتم منظم (حداقل هر 30 روز یکبار) بهروزرسانی یا بهروزرسانی کنید.
پیشنیازها
قبل از اینکه بتوانید محصولات را با استفاده از API اضافه یا مدیریت کنید، باید حداقل یک منبع داده را در حساب مرکز فروشندگان خود پیکربندی کرده باشید.
برای ایجاد یک منبع داده، از متد dataSources.create از زیر-API منابع داده استفاده کنید. برای دستورالعملهای دقیق، به راهنمای مدیریت منابع داده API برای آپلود محصولات مراجعه کنید. پس از ایجاد یک منبع داده، name آن را یادداشت کنید (برای مثال، accounts/12345/dataSources/67890 )، زیرا برای درخواستهای ایجاد، بهروزرسانی یا حذف مربوط به محصول به آن نیاز خواهید داشت.
اضافه کردن محصول
برای افزودن یک محصول جدید به حساب مرکز فروشندگان خود، باید یک منبع ProductInput را در یک منبع داده اصلی وارد کنید. این عمل محصول را ایجاد کرده و پردازش را شروع میکند. فیلدهای درون شیء productAttributes باید با مشخصات داده Product مطابقت داشته باشند.
از متد productInputs.insert استفاده کنید و name منبع داده اصلی خود را به عنوان پارامتر dataSource ارائه دهید.
این مثال یک محصول جدید برای یک فروشگاه آنلاین را در منبع داده اصلی درج میکند.
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",
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000", // 15.99 USD
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": ["9780007350896", "93433295494587"]
}
}
یک فراخوانی موفق، منبع ProductInput تازه ایجاد شده را برمیگرداند. فیلد name شامل شناسه منحصر به فرد برای این ورودی محصول است و فیلد product شامل نام محصول نهایی و پردازش شدهای است که میتوانید بعداً برای بازیابی آن استفاده کنید.
{
"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",
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": [
"9780007350896"
]
}
}
نمونههای کد زیر نحوه اضافه کردن یک محصول را نشان میدهند.
جاوا
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 void 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());
// Calls the API and catches and prints any network failures/errors.
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("label")
.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());
} 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/{INSERT_DATASOURCE_ID}";
insertProductInput(config, dataSource);
}
}
پی اچ پی
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();
پایتون
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
_ACCOUNT = configuration.Configuration().read_merchant_info()
_PARENT = f"accounts/{_ACCOUNT}"
# You can only insert products into datasource types of Input "API" and
# "FILE", and of Type "Primary" or "Supplemental."
_DATA_SOURCE = "[INSERT_DATA_SOURCE_HERE]"
_DATA_SOURCE_NAME = f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"
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():
"""Inserts the specified `ProductInput` resource."""
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client.
client = merchant_products_v1.ProductInputsServiceClient(
credentials=credentials
)
# 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_NAME,
)
# 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}")
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.
if __name__ == "__main__":
insert_product_input()
اسکریپت برنامهها
/**
* 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.
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 -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",
"availability": "IN_STOCK",
"price": {
"amountMicros": "15990000",
"currencyCode": "USD"
},
"condition": "NEW",
"gtins": ["9780007350896"]
}
}'
اطلاعات محصول را با یک منبع داده تکمیلی اضافه یا بهروزرسانی کنید
از یک منبع داده تکمیلی برای ارائه دادههای اضافی یا جایگزین برای محصولاتی که از قبل در یک منبع داده اصلی وجود دارند، استفاده کنید. این برای افزودن اطلاعاتی مانند تبلیغات، برچسبهای سفارشی یا جایگزین کردن دادههای خاص محصول بدون تغییر ورودی اصلی محصول مفید است.
برای انجام این کار، از متد productInputs.insert استفاده کنید، اما name منبع داده تکمیلی خود را در پارامتر dataSource مشخص کنید. بررسی کنید که offerId ، contentLanguage و feedLabel با یک محصول موجود مطابقت داشته باشند.
این مثال با استفاده از یک منبع داده تکمیلی، یک برچسب سفارشی به یک محصول موجود اضافه میکند.
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"
}
}
پس از این فراخوانی، مقدار customLabel0 Product نهایی روی clearance-sale تنظیم خواهد شد، با فرض اینکه منبع داده تکمیلی در قوانین فید شما، همانطور که توسط default_rule تعریف شده است، اولویت بالاتری نسبت به منبع داده اصلی دارد.
اضافه کردن محصولات به صورت غیرهمزمان
برای آپلود کارآمد تعداد زیادی محصول، میتوانید چندین درخواست درج را همزمان ارسال کنید. به جای اینکه منتظر پاسخ هر درخواست قبل از ارسال درخواست بعدی باشید، میتوانید آنها را به صورت غیرهمزمان ارسال کنید و پاسخها را به محض رسیدن مدیریت کنید. این رویکرد میتواند به طور قابل توجهی توان عملیاتی آپلود دادههای شما را بهبود بخشد.
نمونههای کد زیر نحوه درج محصولات به صورت غیرهمزمان را نشان میدهند. برای کسب اطلاعات در مورد انجام چندین درخواست به طور همزمان با استفاده از curl ، به بخش ارسال چندین درخواست به طور همزمان مراجعه کنید.
جاوا
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.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 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());
// 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);
}
}
پایتون
import asyncio
import functools
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
# 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="Async - 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="US",
offer_id=_generate_random_string(),
product_attributes=attributes,
)
def print_product_input(i, task):
print("Inserted ProductInput number: ", i)
# task.result() contains the response from async_insert_product_input
print(task.result())
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_produc_input request.
"""
print("Sending insert product input requests")
try:
response = await client.insert_product_input(request=request)
# The response is an async corouting inserting the ProductInput.
return response
except RuntimeError as e:
# Catch and print any exceptions that occur during the API calls.
print(e)
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 ProductInputsServiceClient.
client = ProductInputsServiceAsyncClient(credentials=credentials)
tasks = []
for i in range(5):
product_input = _create_random_product()
request = InsertProductInputRequest(
parent=_PARENT,
data_source=data_source_name,
product_input=product_input,
)
# Create the async task
insert_product_task = asyncio.create_task(
async_insert_product_input(client, request)
)
# Add the callback
callback_function = functools.partial(print_product_input, i)
insert_product_task.add_done_callback(callback_function)
# Add the task to our list
tasks.append(insert_product_task)
# Await all tasks to complete concurrently
# The print_product_input callback will be called for each as it finishes
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())
محصولاتی را اضافه کنید که کشورهای خاص را هدف قرار میدهند
شما میتوانید برای محصولات خاص، هدفگذاری کشوری را تنظیم کنید تا تنظیمات منبع داده را نادیده بگیرید، یا زمانی که منبع داده هیچ کشوری تعریف نکرده است، محصولات را هدف قرار دهید.
کشورهای هدف با ویژگی shipping
اگر منبع داده شما کشورهای خاصی را تعریف نکرده باشد، میتوانید با ارائه فیلد shipping در productAttributes ، کشورها را برای یک محصول هدف قرار دهید. این فیلد به شما امکان میدهد هزینهها و قوانین ارسال را برای کشورهای مختلف مشخص کنید و به طور ضمنی آنها را برای ارائه خدمات هدف قرار دهید.
این مثال با ارائه دو ورودی shipping جداگانه، یک محصول را برای ایالات متحده و کانادا هدف قرار میدهد.
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"
}
}
]
}
}
کشورها و مقاصد را حذف کنید
اگر منبع داده شما از قبل چندین کشور را هدف قرار داده است، میتوانید یک محصول را از نمایش در زیرمجموعهای از آن کشورها یا از مقاصد خاص حذف کنید.
- از ویژگی
shoppingAdsExcludedCountriesبرای جلوگیری از نمایش یک محصول در تبلیغات خرید در کشورهای خاص استفاده کنید. - از ویژگی
excludedDestinationsبرای جلوگیری از نمایش یک محصول در روشهای بازاریابی خاص، مانندFreeListings، استفاده کنید.
این مثال فرض میکند که منبع داده، ایالات متحده، کانادا و مکزیک را هدف قرار میدهد. این درخواست، محصول را از تبلیغات خرید در مکزیک و به طور کامل از قسمت لیستهای رایگان حذف میکند.
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"]
}
}
اطلاعات محصول را دریافت کنید
برای بازیابی وضعیت پردازششدهی نهایی یک محصول، از متد products.get استفاده کنید. این متد منبع Product (Product resource) را برمیگرداند که شامل تمام productAttributes پس از اعمال قوانین تغذیه (feed rules) و منابع دادهی تکمیلی، به همراه وضعیت اعتبارسنجی فعلی آن است.
ممکن است بین زمانی که یک ورودی ProductInput را وارد یا بهروزرسانی میکنید و زمانی که Product نهایی برای بازیابی در دسترس قرار میگیرد، چند دقیقه تأخیر وجود داشته باشد.
GET https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/en~US~SKU12345
یک درخواست موفق، منبع Product را برمیگرداند.
{
"name": "accounts/{ACCOUNT_ID}/products/en~US~SKU12345",
"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"
}
}
نمونههای کد زیر نحوه دریافت یک محصول را نشان میدهند.
جاوا
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 void 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();
// Calls the API and catches and prints any network failures/errors.
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);
} catch (Exception e) {
System.out.println(e);
}
}
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~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 = encodeProductId(productId);
getProduct(config, accountId, productId);
}
}
پی اچ پی
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();
پایتون
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 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) -> None:
"""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.
"""
# 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)
except RuntimeError as e:
print(e)
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)
اسکریپت برنامهها
/**
* 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:
// channel~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.
product = MerchantApiProducts.Accounts.Products.get(name);
console.log(product);
} catch (e) {
console.log('ERROR!');
console.log(e);
}
}
حلقه
curl -X GET \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/en~US~SKU12345" \
-H "Authorization: Bearer <API_TOKEN>"
حذف یک محصول از منبع داده
برای حذف یک ورودی محصول از یک منبع داده خاص، از متد productInputs.delete استفاده کنید.
- اگر از یک منبع داده اصلی حذف کنید، کل محصول شامل ورودیهای تکمیلی
ProductInputsآن از مرکز فروشندگان حذف میشود. - اگر از یک منبع داده تکمیلی حذف کنید، فقط ویژگیهای آن منبع داده از محصول حذف میشوند. خود محصول باقی میماند، که از منبع داده اصلی و هر منبع داده تکمیلی دیگری تأمین میشود.
شما باید dataSource را که میخواهید ورودی محصول را از آن حذف کنید، مشخص کنید.
DELETE https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
یک فراخوانی موفق، یک پاسخ خالی برمیگرداند.
نمونههای کد زیر نحوه حذف یک محصول را نشان میدهند.
جاوا
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.");
} 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 = "online~en~label~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);
}
}
پی اچ پی
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();
پایتون
from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1
_ACCOUNT = 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`
_PRODUCT = "[INSERT_PRODUCT_HERE]"
_DATA_SOURCE = "[INSERT_DATA_SOURCE_HERE]"
_NAME = f"accounts/{_ACCOUNT}/productInputs/{_PRODUCT}"
_DATA_SOURCE_NAME = f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"
def delete_product_input():
"""Deletes the specified `ProductInput` resource."""
# Gets OAuth Credentials.
credentials = generate_user_credentials.main()
# Creates a client.
client = merchant_products_v1.ProductInputsServiceClient(
credentials=credentials
)
# Creates the request.
request = merchant_products_v1.DeleteProductInputRequest(
name=_NAME, data_source=_DATA_SOURCE_NAME
)
# 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)
if __name__ == "__main__":
delete_product_input()
حلقه
curl -X DELETE \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \
-H "Authorization: Bearer <API_TOKEN>"