Merchant API code sample to update a product input.
Java
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
shopping.merchant.samples.products.v1
;
import
com.google.api.gax.core.FixedCredentialsProvider
;
import
com.google.auth.oauth2.GoogleCredentials
;
import
com.google.protobuf.FieldMask
;
import
com.google.shopping.merchant.datasources.v1.DataSourceName
;
import
com.google.shopping.merchant.products.v1.Availability
;
import
com.google.shopping.merchant.products.v1.Condition
;
import
com.google.shopping.merchant.products.v1.ProductAttributes
;
import
com.google.shopping.merchant.products.v1.ProductInput
;
import
com.google.shopping.merchant.products.v1.ProductInputName
;
import
com.google.shopping.merchant.products.v1.ProductInputsServiceClient
;
import
com.google.shopping.merchant.products.v1.ProductInputsServiceSettings
;
import
com.google.shopping.merchant.products.v1.UpdateProductInputRequest
;
import
com.google.shopping.type.CustomAttribute
;
import
shopping.merchant.samples.utils.Authenticator
;
import
shopping.merchant.samples.utils.Config
;
/** This class demonstrates how to update a product input */
public
class
UpdateProductInputSample
{
public
static
void
updateProductInput
(
Config
config
,
String
productId
,
String
dataSourceId
)
throws
Exception
{
// Obtains OAuth token based on the user's configuration.
GoogleCredentials
credential
=
new
Authenticator
().
authenticate
();
// Creates service settings using the credentials retrieved above.
ProductInputsServiceSettings
productInputsServiceSettings
=
ProductInputsServiceSettings
.
newBuilder
()
.
setCredentialsProvider
(
FixedCredentialsProvider
.
create
(
credential
))
.
build
();
// Creates product name to identify product.
String
name
=
ProductInputName
.
newBuilder
()
.
setAccount
(
config
.
getAccountId
().
toString
())
.
setProductinput
(
productId
)
.
build
()
.
toString
();
// Just productAttributes and customAttributes can be updated
FieldMask
fieldMask
=
FieldMask
.
newBuilder
()
.
addPaths
(
"product_attributes.title"
)
.
addPaths
(
"product_attributes.description"
)
.
addPaths
(
"product_attributes.link"
)
.
addPaths
(
"product_attributes.image_link"
)
.
addPaths
(
"product_attributes.availability"
)
.
addPaths
(
"product_attributes.condition"
)
.
addPaths
(
"product_attributes.gtins"
)
.
addPaths
(
"custom_attributes.mycustomattribute"
)
.
build
();
// Calls the API and catches and prints any network failures/errors.
try
(
ProductInputsServiceClient
productInputsServiceClient
=
ProductInputsServiceClient
.
create
(
productInputsServiceSettings
))
{
ProductAttributes
attributes
=
ProductAttributes
.
newBuilder
()
.
setTitle
(
"A Tale of Two Cities"
)
.
setDescription
(
"A classic novel about the French Revolution"
)
.
setLink
(
"https://exampleWebsite.com/tale-of-two-cities.html"
)
.
setImageLink
(
"https://exampleWebsite.com/tale-of-two-cities.jpg"
)
.
setAvailability
(
Availability
.
IN_STOCK
)
.
setCondition
(
Condition
.
NEW
)
.
addGtins
(
"9780007350896"
)
.
build
();
// The datasource can be either a primary or supplemental datasource.
String
dataSource
=
DataSourceName
.
newBuilder
()
.
setAccount
(
config
.
getAccountId
().
toString
())
.
setDatasource
(
dataSourceId
)
.
build
()
.
toString
();
UpdateProductInputRequest
request
=
UpdateProductInputRequest
.
newBuilder
()
.
setUpdateMask
(
fieldMask
)
// You can only update product attributes and custom_attributes
.
setDataSource
(
dataSource
)
.
setProductInput
(
ProductInput
.
newBuilder
()
.
setName
(
name
)
.
setProductAttributes
(
attributes
)
.
addCustomAttributes
(
CustomAttribute
.
newBuilder
()
.
setName
(
"mycustomattribute"
)
.
setValue
(
"Example value"
)
.
build
())
.
build
())
.
build
();
System
.
out
.
println
(
"Sending update ProductInput request"
);
ProductInput
response
=
productInputsServiceClient
.
updateProductInput
(
request
);
System
.
out
.
println
(
"Updated ProductInput Name below"
);
// The last part of the product name will be the product ID assigned to a product by Google.
// Product ID has the format `contentLanguage~feedLabel~offerId`
System
.
out
.
println
(
response
.
getName
());
System
.
out
.
println
(
"Updated Product below"
);
System
.
out
.
println
(
response
);
}
catch
(
Exception
e
)
{
System
.
out
.
println
(
e
);
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Config
config
=
Config
.
load
();
// An ID assigned to a product by Google. In the format
// contentLanguage~feedLabel~offerId
String
productId
=
"en~label~sku123"
;
// Replace with your product ID.
// Identifies the data source that will own the product input.
String
dataSourceId
=
"{INSERT_DATASOURCE_ID}"
;
// Replace with your datasource ID.
updateProductInput
(
config
,
productId
,
dataSourceId
);
}
}
Node.js
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
'use strict'
;
// This sample demonstrates how to update a ProductInput for a given merchant.
const
fs
=
require
(
'fs'
);
const
authUtils
=
require
(
'../../authentication/authenticate.js'
);
const
{
ProductInputsServiceClient
,
}
=
require
(
'@google-shopping/products'
).
v1
;
const
{
protos
,
}
=
require
(
'@google-shopping/products'
);
const
Availability
=
protos
.
google
.
shopping
.
merchant
.
products
.
v1
.
Availability
;
const
Condition
=
protos
.
google
.
shopping
.
merchant
.
products
.
v1
.
Condition
;
/**
* Performs the actual API call to update the product input.
*
* @param {!object} authClient - An authenticated Google Auth client.
* @param {string} accountId - The ID of the merchant account.
* @param {string} productId - The ID of the product to update.
* @param {string} dataSourceId - The ID of the data source.
*/
async
function
callUpdateProductInput
(
authClient
,
accountId
,
productId
,
dataSourceId
)
{
// Create a new ProductInputsServiceClient with the authenticated client.
const
productInputsServiceClient
=
new
ProductInputsServiceClient
({
authClient
:
authClient
,
});
// Construct the full name of the product input resource.
// Format: accounts/{account}/productinputs/{productinput}
const
name
=
`accounts/
${
accountId
}
/productInputs/
${
productId
}
`
;
// Define the FieldMask to specify which fields of the product input to
// update. According to the API, only 'attributes' and 'customAttributes' can
// be updated this way.
const
fieldMask
=
{
paths
:
[
'product_attributes.title'
,
'product_attributes.description'
,
'product_attributes.link'
,
'product_attributes.image_link'
,
'product_attributes.availability'
,
'product_attributes.condition'
,
'product_attributes.gtins'
,
'custom_attributes.mycustomattribute'
,
// This path targets a custom
// attribute by its name.
],
};
// Prepare the new attributes for the product.
const
attributes
=
{
title
:
'A Tale of Two Cities'
,
description
:
'A classic novel about the French Revolution'
,
link
:
'https://exampleWebsite.com/tale-of-two-cities.html'
,
imageLink
:
'https://exampleWebsite.com/tale-of-two-cities.jpg'
,
availability
:
Availability
.
IN_STOCK
,
condition
:
Condition
.
NEW
,
gtin
:
[
'9780007350896'
],
// GTIN is a repeated field, so it's provided as an array.
};
// Construct the full name of the data source resource.
// The datasource can be either a primary or supplemental datasource.
// Format: accounts/{account}/dataSources/{datasource}
const
dataSource
=
`accounts/
${
accountId
}
/dataSources/
${
dataSourceId
}
`
;
// Prepare the ProductInput object with the new data.
const
productInput
=
{
name
:
name
,
// The resource name of the product input being updated.
productAttributes
:
attributes
,
customAttributes
:
[
{
name
:
'mycustomattribute'
,
value
:
'Example value'
,
},
],
};
// Construct the update request object.
const
request
=
{
productInput
:
productInput
,
updateMask
:
fieldMask
,
dataSource
:
dataSource
,
};
console
.
log
(
'Sending update ProductInput request'
);
// Make the API call to update the product input.
// The response is an array, with the first element being the updated
// ProductInput object.
const
[
response
]
=
await
productInputsServiceClient
.
updateProductInput
(
request
);
console
.
log
(
'Updated ProductInput Name below'
);
// The response contains the updated ProductInput. Its 'name' field is the
// full resource name, which includes the Google-assigned product ID (format:
// contentLanguage~feedLabel~offerId).
console
.
log
(
response
.
name
);
console
.
log
(
'Updated Product below'
);
console
.
log
(
response
);
// Log the full response object.
}
/**
* Main function to orchestrate the product input update.
* It handles configuration, authentication, and calls the core update logic.
*/
async
function
main
()
{
// These are the IDs for the product and data source to be used in the update.
// The productId is an ID assigned by Google, typically in the format:
// contentLanguage~feedLabel~offerId. Replace 'online~en~label~sku123'
// with your specific product ID.
const
productId
=
'en~label~sku123'
;
// The dataSourceId identifies the data source that will own the product
// input. Replace '{INSERT_DATASOURCE_ID}' with your actual data source ID.
const
dataSourceId
=
'{INSERT_DATASOURCE_ID}'
;
try
{
// Load application configuration, which includes the path to
// merchant-info.json.
const
config
=
authUtils
.
getConfig
();
// Read the Merchant Center account ID from the merchant-info.json file.
const
merchantInfo
=
JSON
.
parse
(
fs
.
readFileSync
(
config
.
merchantInfoFile
,
'utf8'
));
const
accountId
=
merchantInfo
.
merchantId
;
// Authenticate and get an OAuth2 client.
const
authClient
=
await
authUtils
.
getOrGenerateUserCredentials
();
// Call the helper function to perform the product input update.
// Ensure accountId is a string as it's part of a resource name.
await
callUpdateProductInput
(
authClient
,
accountId
.
toString
(),
productId
,
dataSourceId
);
}
catch
(
error
)
{
console
.
error
(
error
);
process
.
exitCode
=
1
;
}
}
main
();
PHP
< ?php
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once __DIR__ . '/../../../vendor/autoload.php';
require_once __DIR__ . '/../../Authentication/Authentication.php';
require_once __DIR__ . '/../../Authentication/Config.php';
use Google\ApiCore\ApiException;
use Google\Protobuf\FieldMask;
use Google\Shopping\Merchant\Products\V1\Availability;
use Google\Shopping\Merchant\Products\V1\Condition;
use Google\Shopping\Merchant\Products\V1\ProductAttributes;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\ProductInput;
use Google\Shopping\Merchant\Products\V1\UpdateProductInputRequest;
use Google\Shopping\Type\CustomAttribute;
/**
* This class demonstrates how to update a product input.
*/
class UpdateProductInputSample
{
// An ID assigned to a product by Google. In the format
// contentLanguage~feedLabel~offerId
// Please ensure this product ID exists for the update to succeed.
private const PRODUCT_ID = "online~en~label~sku123";
// Identifies the data source that will own the product input.
// Please ensure this data source ID exists.
private const DATASOURCE_ID = "<INSERT_DATASOURCE_ID>";
/**
* Helper function to construct the full product input resource name.
*
* @param string $accountId The merchant account ID.
* @param string $productInputId The product input ID (e.g., "online~en~label~sku123").
* @return string The full product input resource name.
*/
private static function getProductInputName(string $accountId, string $productInputId): string
{
return sprintf("accounts/%s/productInputs/%s", $accountId, $productInputId);
}
/**
* Helper function to construct the full data source resource name.
*
* @param string $accountId The merchant account ID.
* @param string $dataSourceId The data source ID.
* @return string The full data source resource name.
*/
private static function getDataSourceName(string $accountId, string $dataSourceId): string
{
return sprintf("accounts/%s/dataSources/%s", $accountId, $dataSourceId);
}
/**
* Updates an existing product input in your Merchant Center account.
*
* @param array $config The configuration array containing the account ID.
* @param string $productId The ID of the product input to update.
* @param string $dataSourceId The ID of the data source.
*/
public static function updateProductInput(
array $config,
string $productId,
string $dataSourceId
): void {
// Gets the OAuth credentials to make the request.
$credentials = Authentication::useServiceAccountOrTokenFile();
// Creates options config containing credentials for the client to use.
$options = ['credentials' => $credentials];
// Creates a ProductInputsServiceClient.
$productInputsServiceClient = new ProductInputsServiceClient($options);
// Construct the full resource name of the product input to be updated.
$name = self::getProductInputName($config['accountId'], $productId);
// Define the FieldMask to specify which fields to update.
// Only 'attributes' and 'custom_attributes' can be specified in the
// FieldMask for product input updates.
$fieldMask = new FieldMask([
'paths' => [
"product_attributes.title",
"product_attributes.description",
"product_attributes.link",
"product_attributes.image_link",
"product_attributes.availability",
"product_attributes.condition",
"product_attributes.gtin",
"custom_attributes.mycustomattribute" // Path for a specific custom attribute
]
]);
// Calls the API and handles any network failures or errors.
try {
// Define the new attributes for the product.
$attributes = new ProductAttributes([
'title' => 'A Tale of Two Cities 3',
'description' => 'A classic novel about the French Revolution',
'link' => 'https://exampleWebsite.com/tale-of-two-cities.html',
'image_link' => 'https://exampleWebsite.com/tale-of-two-cities.jpg',
'availability' => Availability::IN_STOCK,
'condition' => Condition::PBNEW,
'gtins' => ['9780007350896'] // GTIN is a repeated field.
]);
// Construct the full data source name.
// This specifies the data source context for the update.
$dataSource = self::getDataSourceName($config['accountId'], $dataSourceId);
// Create the ProductInput object with the desired updates.
// The 'name' field must match the product input being updated.
$productInput = new ProductInput([
'name' => $name,
'product_attributes' => $attributes,
'custom_attributes' => [ // Provide the list of custom attributes.
new CustomAttribute([
'name' => 'mycustomattribute',
'value' => 'Example value'
])
]
]);
// Create the UpdateProductInputRequest.
$request = new UpdateProductInputRequest([
'update_mask' => $fieldMask,
'data_source' => $dataSource,
'product_input' => $productInput
]);
print "Sending update ProductInput request\n";
// Make the API call to update the product input.
$response = $productInputsServiceClient->updateProductInput($request);
print "Updated ProductInput Name below\n";
// The name of the updated product input.
// The last part of the product name is the product ID (e.g., contentLanguage~feedLabel~offerId).
print $response->getName() . "\n";
print "Updated Product below\n";
// Print the full updated product input object.
print_r($response);
} catch (ApiException $e) {
printf("ApiException caught: %s\n", $e->getMessage());
}
}
/**
* Executes the UpdateProductInput sample.
*/
public function callSample(): void
{
$config = Config::generateConfig();
$productId = self::PRODUCT_ID;
$dataSourceId = self::DATASOURCE_ID;
self::updateProductInput($config, $productId, $dataSourceId);
}
}
// Run the script.
$sample = new UpdateProductInputSample();
$sample->callSample();
Python
# -*- coding: utf-8 -*-
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A module to update a product input."""
from
examples.authentication
import
configuration
from
examples.authentication
import
generate_user_credentials
from
google.protobuf
import
field_mask_pb2
from
google.shopping.merchant_products_v1
import
Availability
from
google.shopping.merchant_products_v1
import
Condition
from
google.shopping.merchant_products_v1
import
ProductAttributes
from
google.shopping.merchant_products_v1
import
ProductInput
from
google.shopping.merchant_products_v1
import
ProductInputsServiceClient
from
google.shopping.merchant_products_v1
import
UpdateProductInputRequest
from
google.shopping.type
import
CustomAttribute
# Fetches the Merchant Center account ID from the authentication examples.
# This ID is needed to construct resource names for the API.
_ACCOUNT_ID
=
configuration
.
Configuration
()
.
read_merchant_info
()
def
update_product_input
(
account_id
:
str
,
product_id
:
str
,
data_source_id
:
str
):
"""Updates an existing product input for a specific account.
Args:
account_id: The Merchant Center account ID.
product_id: The ID of the product input to update. This ID is assigned by
Google and has the format `contentLanguage~feedLabel~offerId`.
data_source_id: The ID of the data source that owns the product input.
"""
# Obtains OAuth credentials for authentication.
credentials
=
generate_user_credentials
.
main
()
# Creates a ProductInputsServiceClient instance.
client
=
ProductInputsServiceClient
(
credentials
=
credentials
)
# Constructs the full resource name for the product input.
# Format: accounts/{account}/productInputs/{productinput}
name
=
f
"accounts/
{
account_id
}
/productInputs/
{
product_id
}
"
# Defines the FieldMask to specify which fields of the product input
# are being updated. Only 'attributes' and 'custom_attributes' can be updated.
field_mask
=
field_mask_pb2
.
FieldMask
(
paths
=
[
"product_attributes.title"
,
"product_attributes.description"
,
"product_attributes.link"
,
"product_attributes.image_link"
,
"product_attributes.availability"
,
"product_attributes.condition"
,
"product_attributes.gtins"
,
"custom_attributes.mycustomattribute"
,
]
)
# Prepares the new attribute values for the product.
attributes
=
ProductAttributes
(
title
=
"A Tale of Two Cities updated"
,
description
=
"A classic novel about the French Revolution"
,
link
=
"https://exampleWebsite.com/tale-of-two-cities.html"
,
image_link
=
"https://exampleWebsite.com/tale-of-two-cities.jpg"
,
availability
=
Availability
.
IN_STOCK
,
condition
=
Condition
.
NEW
,
gtins
=
[
"9780007350896"
],
# GTIN is a repeated field.
)
# Constructs the full resource name for the data source.
# The data source can be primary or supplemental.
# Format: accounts/{account}/dataSources/{datasource}
data_source
=
f
"accounts/
{
account_id
}
/dataSources/
{
data_source_id
}
"
# Prepares the ProductInput object with the updated information.
product_input_data
=
ProductInput
(
name
=
name
,
product_attributes
=
attributes
,
custom_attributes
=
[
CustomAttribute
(
name
=
"mycustomattribute"
,
value
=
"Example value"
)
],
)
# Creates the UpdateProductInputRequest.
request
=
UpdateProductInputRequest
(
update_mask
=
field_mask
,
data_source
=
data_source
,
product_input
=
product_input_data
,
)
# Sends the update request to the API.
try
:
print
(
"Sending update ProductInput request"
)
response
=
client
.
update_product_input
(
request
=
request
)
print
(
"Updated ProductInput Name below"
)
# The response includes the name of the updated product input.
# The last part of the product name is the product ID assigned by Google.
print
(
response
.
name
)
print
(
"Updated Product below"
)
print
(
response
)
except
RuntimeError
as
e
:
# Catches and prints any errors that occur during the API call.
print
(
e
)
if
__name__
==
"__main__"
:
# The ID of the product to be updated.
# This ID is assigned by Google and typically follows the format:
# contentLanguage~feedLabel~offerId
# Replace with an actual product ID from your Merchant Center account.
product_id_to_update
=
"online~en~label~sku123"
# The ID of the data source that will own the updated product input.
# Replace with an actual data source ID from your Merchant Center account.
data_source_id_for_update
=
"<INSERT_DATA_SOURCE_ID>"
update_product_input
(
_ACCOUNT_ID
,
product_id_to_update
,
data_source_id_for_update
)