Merchant API code sample to insert product input.
AppsScript
//
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
.
/**
*
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'
,
'gtin'
:
'[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
);
}
}
CSharp
// 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.
using
Google.Apis.Auth.OAuth2
;
using
Google.Shopping.Merchant.Products.V1
;
using
Google.Shopping.Type
;
using
System
;
using
static
MerchantApi
.
Authenticator
;
using
Price
=
Google
.
Shopping
.
Type
.
Price
;
namespace
MerchantApi
{
public
class
InsertProductInputSample
{
/// Inserts a product input into a specified data source.
public
void
InsertProductInput
(
string
merchantId
,
string
dataSource
)
{
Console
.
WriteLine
(
"================================================================="
);
Console
.
WriteLine
(
"Inserting a ProductInput into a data source..."
);
Console
.
WriteLine
(
"================================================================="
);
// Authenticate using either oAuth or service account
ICredential
auth
=
Authenticator
.
Authenticate
(
MerchantConfig
.
Load
(),
ProductsServiceClient
.
DefaultScopes
[
0
]);
// Creates the ProductInputsServiceClient.
var
productInputsServiceClient
=
new
ProductInputsServiceClientBuilder
{
Credential
=
auth
}.
Build
();
// The parent account.
string
parent
=
$"accounts/{merchantId}"
;
// The price for shipping.
Price
price
=
new
Price
{
AmountMicros
=
33
_450_000
,
CurrencyCode
=
"USD"
};
// Shipping information for Great Britain.
Shipping
shipping
=
new
Shipping
{
Price
=
price
,
Country
=
"GB"
,
Service
=
"1st class post"
};
// Shipping information for France.
Shipping
shipping2
=
new
Shipping
{
Price
=
price
,
Country
=
"FR"
,
Service
=
"1st class post"
};
// The attributes of the product.
ProductAttributes
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"
,
ImageLink
=
"https://exampleWebsite.com/tale-of-two-cities.jpg"
,
Availability
=
Availability
.
InStock
,
Condition
=
Condition
.
New
,
GoogleProductCategory
=
"Media > Books"
,
Gtins
=
{
"9780007350896"
},
Shipping
=
{
shipping
,
shipping2
}
};
// The product input to insert.
ProductInput
productInput
=
new
ProductInput
{
ContentLanguage
=
"en"
,
FeedLabel
=
"US"
,
OfferId
=
"sku123"
,
ProductAttributes
=
attributes
};
// Creates the request to insert the product input.
// The data source can be a primary or supplemental data source.
// You can only insert products into data sources of type "API" or "FILE".
InsertProductInputRequest
request
=
new
InsertProductInputRequest
{
Parent
=
parent
,
DataSource
=
dataSource
,
ProductInput
=
productInput
};
try
{
Console
.
WriteLine
(
"Sending insert ProductInput request..."
);
ProductInput
response
=
productInputsServiceClient
.
InsertProductInput
(
request
);
Console
.
WriteLine
(
"Inserted ProductInput Name below:"
);
// The last part of the product input name is the product ID assigned by Google.
// Format: `contentLanguage~feedLabel~offerId`
Console
.
WriteLine
(
response
.
Name
);
Console
.
WriteLine
(
"Inserted Product Name below:"
);
Console
.
WriteLine
(
response
.
Product
);
}
catch
(
Exception
e
)
{
Console
.
WriteLine
(
e
.
Message
);
}
}
public
static
void
Main
(
string
[]
args
)
{
MerchantConfig
config
=
MerchantConfig
.
Load
();
string
merchantId
=
config
.
MerchantId
.
Value
.
ToString
();
// The ID of the data source that will own the product input.
// This field takes the `name` of the data source.
// Replace {INSERT_DATASOURCE_ID} with your actual data source ID.
string
dataSourceId
=
"{INSERT_DATASOURCE_ID}"
;
string
dataSource
=
$"accounts/{merchantId}/dataSources/{dataSourceId}"
;
var
sample
=
new
InsertProductInputSample
();
sample
.
InsertProductInput
(
merchantId
,
dataSource
);
}
}
}
Java
// Copyright 2024 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.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
);
}
}
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'
;
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
;
/**
* Inserts a product input for a given Merchant Center account and data source.
* @param {!object} config - The configuration object.
* @param {string} dataSource - The data source name.
*/
async
function
insertProductInput
(
config
,
dataSource
)
{
// Read merchant_id from merchant-info.json.
const
merchantInfo
=
JSON
.
parse
(
fs
.
readFileSync
(
config
.
merchantInfoFile
,
'utf8'
)
);
const
merchantId
=
merchantInfo
.
merchantId
;
// Construct the parent resource name.
// Format: accounts/{account}
const
parent
=
`accounts/
${
merchantId
}
`
;
// Get credentials.
const
authClient
=
await
authUtils
.
getOrGenerateUserCredentials
();
// Create options object for the client.
const
options
=
{
authClient
:
authClient
};
// Create the ProductInputsServiceClient.
const
productInputsClient
=
new
ProductInputsServiceClient
(
options
);
// Define the price objects.
const
shippingPrice
=
{
amountMicros
:
3000000
,
// 3 USD
currencyCode
:
'USD'
,
};
const
price
=
{
amountMicros
:
33450000
,
// 33.45 USD
currency_code
:
'USD'
,
};
// Define shipping details.
const
shipping1
=
{
price
:
shippingPrice
,
country
:
'GB'
,
service
:
'1st class post'
,
};
const
shipping2
=
{
price
:
shippingPrice
,
country
:
'FR'
,
service
:
'1st class post'
,
};
// Define product attributes.
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
,
googleProductCategory
:
'Media > Books'
,
gtins
:
[
'9780007350896'
],
// GTIN is a repeated field
shipping
:
[
shipping1
,
shipping2
],
// Shipping is a repeated field
price
:
price
,
};
// Define the product input object.
const
productInput
=
{
contentLanguage
:
'en'
,
feedLabel
:
'label'
,
offerId
:
'sku123'
,
productAttributes
:
attributes
,
};
// Construct the request object.
const
request
=
{
parent
:
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.
// If this product is already owned by another datasource, when re-inserting,
// the new datasource will take ownership of the product.
dataSource
:
dataSource
,
productInput
:
productInput
,
};
try
{
console
.
log
(
'Sending insert ProductInput request'
);
// Call the API to insert the product input.
const
[
response
,
options
,
rawResponse
]
=
await
productInputsClient
.
insertProductInput
(
request
);
console
.
log
(
'Inserted ProductInput Name below'
);
// The last part of the product name will be the product ID assigned by Google.
// Product ID has the format `contentLanguage~feedLabel~offerId`
console
.
log
(
response
.
name
);
console
.
log
(
'Inserted Product Name below'
);
console
.
log
(
response
.
product
);
console
.
log
(
'Inserted Product below'
);
console
.
log
(
response
);
}
catch
(
error
)
{
console
.
error
(
error
.
message
);
}
}
/**
* Main function to call the insertProductInput function.
*/
async
function
main
()
{
const
config
=
authUtils
.
getConfig
();
// Read merchant_id from merchant-info.json.
const
merchantInfo
=
JSON
.
parse
(
fs
.
readFileSync
(
config
.
merchantInfoFile
,
'utf8'
)
);
const
merchantId
=
merchantInfo
.
merchantId
;
// Identifies the data source that will own the product input.
// Replace {INSERT_DATASOURCE_ID} with the actual ID of your data source.
// Format: accounts/{account}/dataSources/{dataSource}
const
dataSource
=
`accounts/
${
merchantId
}
/dataSources/{INSERT_DATASOURCE_ID}`
;
await
insertProductInput
(
config
,
dataSource
);
}
main
();
PHP
< ?php
/**
* Copyright 2024 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\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();