本頁面說明如何以程式輔助方式上傳及管理產品。使用 Merchant Products API,您可以在資料來源中插入或更新產品、從帳戶中擷取產品,以及從資料來源中刪除產品。
Merchant Products API 包含兩個資源。
productInputs
代表產品的輸入部分。products
代表從輸入部分建構的已處理產品。
productInputs
可分為主要和補充,這取決於上傳至主要資料來源還是補充資料來源。每個 product
都會由單一主要 productInput
和任意數量的補充 productInputs
建構而成。
您可以使用 Merchant Products API 建立線上或店面目錄,這些目錄中的產品可顯示在多個購物目的地。建立 Merchant Center 帳戶、設定第一個資料來源,並準備好透過 API 上傳初始產品組合後,即可使用 productInputs
資源。
雖然商家可以使用檔案上傳產品 (稱為 PrimaryProductDataSource),但使用 Merchant API 建立及刪除產品有許多優點。這些優點包括回應時間更快,以及能夠即時更新產品,而無需管理大型檔案。透過 API 呼叫所做的產品變更,最多可能需要幾小時才會顯示在購物資料庫中。
必要條件
如果沒有資料來源,請使用 Merchant Data Sources API 或 Merchant Center 建立資料來源。
如果你已使用 Merchant Center UI 或 API 建立資料來源,可以使用 Merchant Products API 新增產品。如果你使用 Content API for Shopping 新增產品,請參閱遷移指南,瞭解如何開始使用 Merchant Products API。
請務必遵守「購物廣告」和「免費產品資訊」政策。購物廣告有權執行這些政策,並在發現違反這些政策的內容或行為時採取適當回應。
資源
products
資源可讓您從 Shopping 資料庫擷取產品資訊。
productInput
資源代表您為產品提交的輸入資料。它也提供方法,讓你一次更新或刪除一或多個產品資訊,或是在批次模式中一次更新或刪除多個產品資訊。productInput
資源必須包含下列欄位:
channel
:產品的管道。offerId
:產品的專屬 ID。contentLanguage
:產品的兩個字母 ISO 639-1 語言代碼。feedLabel
:用於分類及識別產品的標籤。允許的字元上限為 20 個,支援的字元為A-Z
、0-9
、連字號和底線。動態饋給標籤不得包含任何空格。詳情請參閱「使用動態饋給標籤」。
上傳產品輸入內容至帳戶
如要將產品輸入內容上傳至帳戶,請使用 accounts.productInputs.insert
方法。您必須傳遞主要或輔助資料來源的專屬 ID。
以下要求範例說明如何使用 accounts.productInputs.insert
方法,將產品輸入內容上傳至商家帳戶。要求會設定運送價格和區域,以及自訂屬性,例如製造日期和尺寸。
POST https://merchantapi.googleapis.com/products/v1beta/accounts/{ACCOUNT_ID} /productInputs:insert?dataSource={DATASOURCE}
{
"name": "{PRODUCT_TITLE} ",
"versionNumber": {VERSION_NUMBER} ,
"contentLanguage": "{CONTENT_LANGUAGE} ",
"feedLabel": "{FEED_LABEL} ",
"offerId": "{OFFER_ID} ",
"channel": "ONLINE",
"attributes": {
"availability": "in stock",
"imageLink": "{IMAGE_LINK} ",
"link": "{PRODUCT_LINK} ",
"brand": "{BRAND_NAME} ",
"price": {
"currencyCode": "{CURRENCY_CODE} ",
"amountMicros": {PRICE}
},
"color": "red",
"productWeight": {
"value": 320,
"unit": "g"
},
"adult": false,
"shipping": [
{
"country": "GB",
"price": {
"amountMicros": {SHIPPING_COST} ,
"currencyCode": "{CURRENCY_CODE_SHIPPING} "
},
"postalCode": "{SHIPPING_POSTALCODE} ",
"service": "",
"region": "{SHIPPING_REGION} ",
"maxHandlingTime": "{MAX_HANDLING_TIME} ",
"minHandlingTime": "{MIN_HANDLING_TIME} ",
"maxTransitTime": "{MAX_TRANSIT_TIME} ",
"minTransitTime": "{MIN_TRANSIT_TIME} "
}
],
"gender": "Female"
},
"customAttributes": [
{
"name": "size",
"value": "Large"
},
{
"name": "Date of Manufacturing",
"value": "2024-05-05"
}
]
}
更改下列內容:
- {ACCOUNT_ID}:Merchant Center 帳戶的專屬 ID。
- {DATASOURCE}:資料來源的專屬 ID。格式應為
accounts/
{ACCOUNT_ID}/dataSources/
{DATASOURCE_ID}。 - {PRODUCT_TITLE}:產品名稱。
- {VERSION_NUMBER}:產品的版本編號。選用項目。
- {CONTENT_LANGUAGE}:產品的兩個字母 ISO 639-1 語言代碼。必填。
- {FEED_LABEL}:這個標籤可讓您分類及識別產品。允許的字元上限為 20 個,支援的字元包括
A-Z
、0-9
、連字號和底線。動態饋給標籤不得包含任何空格。 - {OFFER_ID}:產品的專屬 ID。必填。
- {IMAGE_LINK}:網站上產品圖片的連結。選用項目。
- {PRODUCT_LINK}:網站上產品的連結。選用項目。
- {CURRENCY_CODE}:價格的幣別,採用 ISO 4217 標準的三個英文字母組成。選用項目。
- {PRICE}:產品價格,以微小數表示。選用項目。
- {SHIPPING_COST}:固定運費價格,以數字表示。選用項目。
- {SHIPPING_POSTALCODE}:套用運費的郵遞區號範圍。選用項目。
- {MAX_HANDLING_TIME}:從收到訂單到出貨之間,最長的處理時間 (以工作天為單位)。選用項目。
- {MIN_HANDLING_TIME}:從收到訂單到出貨之間,最短處理時間的工作天數。值為 0 表示訂單會在收到訂單當天送達。選用項目。
- {MAX_TRANSIT_TIME}:從訂單出貨到送達之間,最長的運送時間 (以工作天為單位)。選用項目。
- {MIN_TRANSIT_TIME}:從訂單出貨到送達之間,最短的運送時間 (以工作天為單位)。值為 0 表示訂單會在出貨當天送達。選用項目。
要求執行成功時,您會看到下列回應:
{
"name": "{PRODUCT_NAME} ",
"product": "{PRODUCT_ID} ",
"channel": "ONLINE",
"offerId": "{OFFER_ID} ",
"contentLanguage": "{CONTENT_LANGUAGE} ",
"feedLabel": "{FEED_LABEL} ",
"versionNumber": "{VERSION_NUMBER} ",
"attributes": {
"link": "{PRODUCT_LINK} ",
"imageLink": "{IMAGE_LINK} ",
"adult": false,
"availability": "in stock",
"brand": "{BRAND_NAME} ",
"color": "red",
"gender": "Female",
"price": {
"amountMicros": "{PRICE} ",
"currencyCode": "{CURRENCY_CODE} "
},
"shipping": [
{
"price": {
"amountMicros": "{SHIPPING_COST} ",
"currencyCode": "{CURRENCY_CODE} "
},
"country": "{SHIPPING_COUNTRY} ",
"region": "{SHIPPING_REGION} ",
"postalCode": "{SHIPPING_POSTALCODE} ",
"minHandlingTime": "{MIN_HANDLING_TIME} ",
"maxHandlingTime": "{MAX_HANDLING_TIME} ",
"minTransitTime": "{MIN_TRANSIT_TIME} ",
"maxTransitTime": "{MAX_TRANSIT_TIME} "
}
],
"productWeight": {
"value": 320,
"unit": "g"
}
},
"customAttributes": [
{
"name": "Size",
"value": "Large"
},
{
"name": "Date of Manufacturing",
"value": "2024-05-05"
}
]
}
如要將產品加入 Merchant Center 帳戶,可以使用 google.shopping.merchant.accounts.v1beta.InsertProductInputSample
方法,如以下範例所示。
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1beta.Attributes;
import com.google.shopping.merchant.products.v1beta.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1beta.ProductInput;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1beta.Shipping;
import com.google.shopping.type.Channel.ChannelEnum;
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();
Attributes attributes =
Attributes.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("in stock")
.setCondition("new")
.setGoogleProductCategory("Media > Books")
.setGtin(0, "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()
.setChannel(ChannelEnum.ONLINE)
.setContentLanguage("en")
.setFeedLabel("label")
.setOfferId("sku123")
.setAttributes(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 `channel~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);
}
}
從帳戶中擷取已處理的產品
如要從帳戶中擷取已處理的產品,請使用 accounts.products.get
方法。插入後,系統可能需要幾分鐘的時間才能顯示已處理的產品。
GET https://merchantapi.googleapis.com/products/v1beta/accounts/{ACCOUNT_ID} /products/{PRODUCT_NAME}
將 {PRODUCT_NAME} 替換為要刪除的產品輸入資源名稱。例如 online~en~US~sku123
。
您可以從 accounts.productInputs.insert
回應中的 product
欄位取得已處理產品的資源名稱。
如要擷取特定 Merchant Center 帳戶的單一產品,可以使用 google.shopping.merchant.accounts.v1beta.GetProductRequest
方法,如以下範例所示。
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1beta.GetProductRequest;
import com.google.shopping.merchant.products.v1beta.Product;
import com.google.shopping.merchant.products.v1beta.ProductsServiceClient;
import com.google.shopping.merchant.products.v1beta.ProductsServiceSettings;
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 {
public static void getProduct(Config config, String product) 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}
GetProductRequest request = GetProductRequest.newBuilder().setName(product).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();
// 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 product = "accounts/{datasource}/products/{productId}";
getProduct(config, product);
}
}
從帳戶中刪除產品輸入內容
如要從帳戶中刪除產品輸入內容,請使用 accounts.productInputs.delete
方法。如要使用 Merchant Products API 刪除產品,必須傳遞產品所屬主要或輔助資料來源的專屬 ID。
以下要求示範如何使用 accounts.productInputs.delete
方法刪除產品輸入內容:
DELETE https://merchantapi.googleapis.com/products/v1beta/accounts/{ACCOUNT_ID} /productInputs/{PRODUCT_NAME} ?dataSource=accounts/{ACCOUNT_ID} /dataSources/{DATASOURCE_ID}
將 {PRODUCT_NAME} 替換為要刪除的產品輸入資源名稱。例如 online~en~US~sku123
。
如要刪除特定 Merchant Center 帳戶的產品,可以使用 google.shopping.merchant.accounts.v1beta.DeleteProductInputRequest
方法,如以下範例所示。
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1beta.DeleteProductInputRequest;
import com.google.shopping.merchant.products.v1beta.ProductInputName;
import com.google.shopping.merchant.products.v1beta.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1beta.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
// channel~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);
}
}
列出帳戶中的產品
如要列出帳戶中的已處理產品,請使用 accounts.products.list
方法,如以下要求所示。
GET https://merchantapi.googleapis.com/products/v1beta/accounts/{ACCOUNT_ID} /products
如要為特定 Merchant Center 帳戶刊登產品,可以使用 google.shopping.merchant.accounts.v1beta.ListProductsRequest
方法,如以下範例所示。
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1beta.ListProductsRequest;
import com.google.shopping.merchant.products.v1beta.Product;
import com.google.shopping.merchant.products.v1beta.ProductsServiceClient;
import com.google.shopping.merchant.products.v1beta.ProductsServiceClient.ListProductsPagedResponse;
import com.google.shopping.merchant.products.v1beta.ProductsServiceSettings;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to list all the products for a given merchant center account */
public class ListProductsSample {
private static String getParent(String accountId) {
return String.format("accounts/%s", accountId);
}
public static void listProducts(Config config) 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();
// Creates parent to identify the account from which to list all products.
String parent = getParent(config.getAccountId().toString());
// Calls the API and catches and prints any network failures/errors.
try (ProductsServiceClient productsServiceClient =
ProductsServiceClient.create(productsServiceSettings)) {
// The parent has the format: accounts/{account}
ListProductsRequest request = ListProductsRequest.newBuilder().setParent(parent).build();
System.out.println("Sending list products request:");
ListProductsPagedResponse response = productsServiceClient.listProducts(request);
int count = 0;
// Iterates over all rows in all pages and prints the datasource in each row.
// Automatically uses the `nextPageToken` if returned to fetch all pages of data.
for (Product product : response.iterateAll()) {
System.out.println(product); // The product includes the `productStatus` field
// That shows approval and disapproval information.
count++;
}
System.out.print("The following count of products were returned: ");
System.out.println(count);
} catch (Exception e) {
System.out.println("An error has occured: ");
System.out.println(e);
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
listProducts(config);
}
}