Content API for Shopping

Content API for Shopping Developer's Guide: PHP

The Google Content API for Shopping PHP Client Library is provided for connecting to the Content API for Shopping server and interpreting the results. This client library is by no means the only way of connecting to the Content API for Shopping server. This document demonstrates how to use the PHP client library for accessing and editing your data.


  1. Introduction
  2. Prerequisites
  3. Setup
  4. Performing authentication
  5. Creating and Editing a Product Object
    1. Sample Product as XML
    2. Building a Product in PHP
    3. Editing a Product in PHP
  6. Managing items
    1. Retrieving all your items
    2. Retrieving a single item
    3. Inserting items
    4. Updating items
    5. Deleting items
  7. Batching
    1. Creating a list of entries to be modified
    2. Batch insert
    3. Batch update
    4. Batch delete
    5. Mixed Batch requests
  8. Error Handling
    1. Errors on Individual Items
    2. Batch Errors
    3. Inspecting Errors
  9. Warnings and Dry-run Mode
  10. Accessing Product Performance Data
  11. The generic projection


The Google Content API for Shopping PHP Client Library is a specific client library tailored to the Content API for Shopping. A custom client class has been defined within the library to represent the data relevant to the API and interact with the Content API server.

As part of this documentation, we provide an example of how you can do this. This example is only meant for teaching how the client library is used. It may not have all the data fields you might want to access; you can find information about fields not used in this example in the library documentation.


This document assumes that you know how to program in PHP, and that you are familiar with the basic concepts of the Google Content API for Shopping.


The PHP client library is available for download from the project page or from the Mercurial repository.

This documentation and the downloadable examples have been written for and tested with version 1.2 of the client library. The latest version is not guaranteed to be backward compatible with this example. You can include the client library in your project by downloading the source and requiring the package in your code:


The library is intended to be self-contained and won't require external packages. The majority of the XML processing work done by the library is accomplished with the help of the native DOMDocument class.

Performing authentication

To make requests to the Content API for Shopping server, you need to be authenticated, which you can do using a number of methods provided by Google. For more information, read the Google Account Authentication documentation. We strongly recommend starting your new applications using OAuth 2.0 as well as migrating existing ones to it. As was recently announced, all authentication protocols other than OAuth 2.0 are being phased out in the near future.

For information specific to the Google Data Protocol, read the Authentication and Authorization documentation. The Google Content API for Shopping PHP Client Library provides a GSC_Client class that can perform authentication and submit API requests. Since the account ID is needed to construct the URL of each request to the Content API for Shopping server, the constructor for GSC_Client takes a string argument to permanently set this value for all requests:

const ACCOUNT_ID = '1234567';

$client = new GSC_Client(ACCOUNT_ID);

Authorizing requests with OAuth 2.0

The details of the authorization process, or "flow," for OAuth 2.0 vary somewhat depending on what kind of application you're writing. The following general process applies to all application types:

  1. When you create your application, you register it with Google. Google then provides information you'll need later, such as a client ID and a client secret.
  2. When your application needs access to user data, it asks Google for a particular scope of access.
  3. Google displays an OAuth dialog to the user, asking them to authorize your application to request some of their data.
  4. If the user approves, then Google gives your application a short-lived access token.
  5. Your application requests user data, attaching the access token to the request.
  6. If Google determines that your request and the token are valid, it returns the requested data.

For detailed information about flows for various types of applications, see Google's OAuth 2.0 documentation. To use OAuth 2.0 with the PHP client library, you can use the GSC_OAuth2Token class.

Creating an Empty Token Object

To create an initial token, you need your client ID and secret from the APIs console

const CLIENT_ID = '';  // Provided in the APIs console
const CLIENT_SECRET = 'SeCr3Tv4lu3';  // Provided in the APIs console
const USER_AGENT = 'content-api-example';

// $client->setOAuth2Token can also be used
Note: The scope for the Content API for Shopping
is automatically used by the library. If you'd like to request access to additional scopes, you can manually set the scope property on the token object with the complete list of requested scopes as a space-delimited string.

Authorizing a Token Object

After you have created this token, you or the user need to authorize the token to make API requests by visiting the OAuth 2.0 authorize URL:

$authorizeUrl = $authToken->generateAuthorizeUrl(APPLICATION_REDIRECT_URI);
echo 'Please visit: ' . $authorizeUrl;
Note: As mentioned in the OAuth 2.0 documentation, if your application loses the refresh token, then it needs to re-prompt the user for consent before obtaining another refresh token. If you need to re-prompt the user for consent, include the approval_prompt parameter in the authorization code request, and set the value to force:
$approvalPrompt = 'force';
$authorizeUrl = $authToken->generateAuthorizeUrl(APPLICATION_REDIRECT_URI,

Exchanging an Authorization Code for an Access Token

After successfully authorizing, the user is redirected to a page that has a value in the query parameter code containing the needed authorization. You can retrieve the query parameters from the redirect URL and pass them to the GSC_OAuth2Token object to retrieve an access token:

$returnedUrl = '';
$url = parse_url($returnedUrl);
parse_str($url['query'], $urlQuery);


Note: If you are within a web application, you can retrieve the code query parameter using $_GET['code']. You can pass the value directly to getAccessToken as a string, since this method takes either a string or an array as input.

Using a Token Object

Finally, to use this token with a client object:


Note: When an access token expires, the API requests signed with that token are rejected. After setting the token on the client with an GSC_OAuth2Token, the client can address such rejections. When the said requests fail, the client uses the authToken to attempt obtaining a new access token (using the refresh token stored on the token object). If it successfully obtains a new access token, the client resends the original API request, signed with the new access token.

ClientLogin for installed/mobile applications

To use a GSC_Client instance to authenticate with ClientLogin, you only need to provide your email and password. In order to use the Content API for Shopping, you need to authenticate against the structuredcontent service, but the GSC_Client handles this automatically:

const EMAIL = '';
const PASSWORD = 'pa$$word';
const APPLICATION_NAME = 'content-api-example';


You simply must call the clientLogin method to complete login. The method sets a private variable on the GSC_Client object (token) which is used to sign requests.

Note: When performing Client Login requests, a source source parameter is required for logging purposes, so we use APPLICATION_NAME to serve this function. You may choose any value you like for the name of your application.

Creating and Editing a Product object

The API represents products as XML objects. Each data item starts with an <entry> tag, includes a set of attributes that describe the said item, and ends with the </entry> tag.

Using the PHP client library, we will construct an example product.

Building a Product in PHP

The PHP client library provides a GSC_Product class with custom getters and setters corresponding to the XML product attributes. This classes abstracts from the creation and the structure of the XML object, allowing you to focus on your data.

The above example doesn't use every single attribute defined by the API; for details on attributes not listed here, check out the documentation for the custom methods defined for the Content API for Shopping. In this example, each type of setter is used at least once to explain the mechanics corresponding to each type of XML attribute.

We start with an empty <entry> element that is the "container" for all our data:

$product = new GSC_Product();

Standard Elements

For the majority of the attributes in the atom, sc, and scp namespaces, adding the attribute to the GSC_Product object simply involves setting the attribute with a string:

    'A great compact body to make it easy to get a great shot everytime.');
$link = '';
$product->setAvailability('in stock');

For the <scp:product_type> element and other attributes that use taxonomy values, the ampersand (&), greater than sign (>), less than sign (<), and some other characters must be escaped as proper XML. Conveniently, this is done automatically by the PHP client library:

$productType = 'Cameras & Optics > Cameras > Digital Cameras';

Elements with Parameters

XML elements that also use parameters must be set by using an additional argument:

$product->setPrice('25.00', 'usd');
$product->setShippingWeight('0.1', 'lb');

Nested Elements

The <scp:shipping> and <scp:tax> elements are nested attributes. The parameters of the addShipping and addTax methods allow you to set each shipping/tax subelement:

$country = 'US';
$region = 'MA';
$price = '5.95';
$priceUnit = 'usd';
$service = 'Speedy Shipping - Ground';
$product->addShipping($country, $region, $price, $priceUnit, $service);

$country = 'US';
$region = 'CA';
$rate = '8.25';
$ship = 'true';
$product->addTax($country, $region, $rate, $ship);

Since there can be more than one tax and shipping type, the methods add another block of XML rather than setting it.

Note: The second shipping value and the second tax value can be added in the same fashion.

Finally, the only remaining attribute from the example XML is the required destination. Like tax and shipping, this is contained in a nested element, so setting the attribute is similar. Again, since it is possible to set more than one required destination, the method adds rather than sets:


Editing a Product in PHP

When making requests, you may also be working with GSC_Product objects that you did not construct yourself, but that you retrieved from your online inventory via a request to the Content API. To edit these objects, you can set the corresponding attribute as you did when first building the object. For example, if the price has lowered from $25 USD to $22.50 USD:

$product->setPrice('22.50', 'usd');

If you have enabled warnings, then you may want to inspect the warnings returned with the product object:

$warnings = $product->getWarnings();

// $warnings is a DOMNodeList
for($index = 0; $index < $warnings->length; $index++) {
    $warning = $warnings->item($index);
    echo 'Code: ' . $product->getWarningCode($warning) . "\n";
    echo 'Domain: ' . $product->getWarningDomain($warning) . "\n";
    echo 'Location: ' . $product->getWarningLocation($warning) . "\n";
    echo 'Message: ' . $product->getWarningMessage($warning) . "\n";

For the product defined above, you may get this output:

Code: validation/missing_recommended
Domain: ProductSearch
Location: google_product_category
Message: We recommend including this attribute.

You can address this error by updating the GSC_Product:

$gpc = 'Cameras & Optics > Cameras > Digital Cameras';

Managing items

All actions on items—getting, inserting, updating, and deleting—can be performed with a GSC_Client object. For each action performed with the client object, an authentication token must be provided, but it is a private variable on the client object. As mentioned before, your account ID is needed to construct each URL (read more in the reference), and the authentication token is needed to sign each request.

The following code snippets assume that the login method has been successfully executed and the token has been set on the client object.

Retrieving all your items

To retrieve the list of data items belonging to your inventory, you make an HTTP GET request to the items feed:

You can use a client object to create and send this request to the Content API for Shopping:

$productFeed = $client->getProducts();

The response productFeed contains a GSC_ProductList object. This object represents the <feed> element that contains a list of <entry> elements, one for each item in the feed. The getProducts method of the GSC_ProductList object returns a list of the GSC_Product objects returned in the feed:

$products = $productFeed->getProducts();
foreach ($products as $product) {
    echo $product->getTitle() . "\n";

Paging through results

For paging through your items, use the max-results and start-token query parameters (see the reference for more details).

To specify the number of items returned by a request, include the number of results you seek as the first optional argument to getProducts. If you don't specify a value, the PHP client library will not append any value to the API request and default value of 25 is used.

$maxResults = '10';
$productFeed = $client->getProducts($maxResults);

If your product inventory exceeds the maximum number of results requested, you need to submit another request to the Content API for Shopping to get the next page of results. In this case, the returned feed contains a link element resembling:

<link rel="next" type="application/atom+xml"

This link contains a token pointing to the next page of results. You can retrieve it from the feed and specify the start token as the second argument to getProducts in the next request:

$startToken = $productFeed->getStartToken();
$nextProductFeed = $client->getProducts($maxResults, $startToken);
Note: If you would like to specify a start token with no max-results parameter, you can send null in the first argument:
$productFeed = $client->getProducts(null, $startToken);

Note: The parameter max-results cannot exceed 250.

Retrieving a single item

You can retrieve a specific item's data by executing an HTTP GET request to its unique URL. This is formed using the item's channel, language, target country, and ID you submitted with the item. To retrieve the item from the above example, the request URL is:

To retrieve this item using the PHP client library:

$id = '123456';
$country = 'US';
$language = 'en';
$product = $client->getProduct($id, $country, $language);

Inserting items

After creating the product item you want to insert, use a client object to send a request to the Content API for Shopping:

$insertedProduct = $client->insertProduct($product);

If the insert succeeds, the variable insertedProduct contains a GSC_Product object parsed from the response. The server returns the item you just inserted, together with some additional attributes for your entry, such as the Atom id element and the published date and time.

Updating items

Updating an item is very similar to inserting it. The only difference with inserting a product is that it first checks if the product is already present in your inventory. By sending an HTTP PUT request to the URL of the item, you will overwrite the old item. The request therefore needs to contain all of the attributes, even those you don't want to change.

To update an item, you can use a client object to send a request to the Content API for Shopping:

$updatedProduct = $client->updateProduct($product);

How the value product is constructed may vary. After inserting a product, you may want to edit the product based on warnings returned from the Content API for Shopping server. Alternatively, changes in your inventory may cause you to first retrieve an item so that you may update its contents.

As with inserting, if the update request succeeds, the variable updatedProduct contains GSC_Product object parsed from the response.

Note: The PHP client library retrieves the URL for the PUT request directly from the <link rel="edit"> element of the product. If this is not set, you set it yourself with the setEditLink method. You can construct it by using the sc:id, sc:target_country, and sc:content_language elements of the product.

Deleting items

For deleting an item, we simply send a delete request to its URL:


This method has no return value, but throws a GSC_ClientError if a response code other than 200 is returned.

Note: The PHP client library retrieves the URL for the DELETE request directly from the <link rel="edit"> element of the product. If this is not set, you set it yourself with the setEditLink method. You can construct it by using the sc:id, sc:target_country, and sc:content_language elements of the product.


When sending many requests, it is better to combine them into a single batch request instead of sending them individually. Batching reduces the time to process your requests, and additionally reduces the load on your servers. For a general introduction to batching, read the GData documentation.

To perform batching with the Content API for Shopping server, create a list of entries to be modified (inserted, updated, deleted) in one batch. Each entry of the list can be a normal GSC_Product object, except that additionally the batch:operation element must be set with the desired operation as the type.

Creating a list of entries to be modified

To tell the Content API for Shopping server what to do with the products in the list that you send as a batch, that is, if it should insert, update, or delete them, you need to add this information to every single product by setting its batch:operation field. Additionally, for update and delete requests, you need to set the atom:id field to the edit link, so that the server can identify the product. For example:

// Retrieve a product to update
list($id, $country, $language) = array('123456', 'US', 'en');
$product = $client->getProduct($id, $country, $language);

// Add batch attributes to the product
// rel="edit" link contains the product's URL
$editLink = $product->getEditLink();

You may set the batch:id field to any value, so that you can more easily identify the products in the server's response. In case of products, it usually makes sense to set the batch ID (batch:id) to the same value as the product ID (sc:id):


Batch insert

To submit a batch of items, all of which need to be inserted, the client object has a special method that handles the setting of the batch operation.

If you have created two items—product1 and product2—you can insert them as follows:

$products = array($product1, $product2);
$insertedFeed = $client->insertProducts($products);

$insertedProducts = $insertedFeed->getProducts();
foreach ($insertedProducts as $product) {
    echo $product->getTitle().
         ' inserted with code '.
         $product->getBatchStatus() . "\n";

To set the batch ID (batch:id) to the product ID (sc:id) or some other value, you'll need to do so on each GSC_Product before calling insertProducts.

Batch update

As described above, a batch update can be accomplished by appending the batch operation and the product ID to the existing product data (with changes/updates included). As with inserting, to submit a batch of items, all of which need to be updated, the client object has a special method that will handle the setting of the batch operation.

For a GSC_Product object returned from the API, the "edit" link contains the unique product URL; proceeding as above:

$editLink = $product->getEditLink();

If the edit link is not set, you need to construct the unique product URL by hand; this can be done using your account ID, along with the sc:product_id, sc:target_country, and sc:content_language attributes of the product as mentioned above.

After setting the atom:id field, you can update the items as follows:

$products = array($product1, $product2);
$updatedFeed = $client->updateProducts($products);

$updatedProducts = $updatedFeed->getProducts();
foreach ($updatedProducts as $product) {
    echo $product->getTitle().
         ' updated with code '.
         $product->getBatchStatus() . "\n";

Batch delete

As described in the GData documentation, a batch delete can be accomplished by including only the batch operation and the product ID. The product URL in the atom:id element should be set to the value of the rel="edit" link of the product as in the updating section.

To submit a batch of items, all of which need to be deleted, the client object has a special method that will handle the setting of the batch operation:

$products = array($product1, $product2);
$deletedFeed = $client->deleteProducts($products);

$deletedProducts = $deletedFeed->getProducts();
foreach ($deletedProducts as $product) {
    echo $product->getTitle().
         ' deleted with code '.
         $product->getBatchStatus() . "\n";

Mixed Batch requests

A batch request can contain any combination of insert, update, and delete entries. You can use one of the client methods defined above (API_VERBProducts), or manually add the batch:operation to each GSC_Product, followed by adding every GSC_Product to an empty GSC_ProductList object.

For example, to mix different operations with three entries (productToInsert, productToUpdate, and productToDelete):

$productsBatch = new GSC_ProductList();


$updateEditLink = $productToUpdate->getEditLink();

$deleteEditLink = $productToDelete->getEditLink();

$mixedFeed = $client->batch($productsBatch);

A request may not contain two or more actions that affect the same product. If it does, there is not necessarily an error message, but the outcome is undefined.

If you are inserting a new product that has the same sc:id as another one of your products that is already stored on the server, then the new product overwrites the previous one. This is another way of updating products.

Error Handling

The examples above do not contain any error-handling code to keep things simple. For more details on the errors that the Content API for Shopping server may return, see the error code list.

Errors on Individual Items

If a non-batch request is rejected by the Content API for Shopping server, the client method returns a GSC_Errors object rather than a GSC_Product object. If you encounter a different error, it is likely caused by an issue other than the PHP client library.

Batch Errors

In a batch request, many operations are combined into one request. Some of these operations may succeed, while some may fail. When batching, the batch request should return an HTTP success code, even if there were errors for individual products. In the batch response, the result of each operation is represented as an <entry> element. For operations that fail, the errors are returned in the following element:

<content type='application/'>
For such errors, the reason field contains the error message you would have received, had you sent the product as an individual request.

To determine if an operation has failed or succeeded, you can check the response code from the <batch:status> element. If the code is something other than 200 or 201, there will be an errors block within the <content> element, which you can access with a custom method on the GSC_Product:

$feed = $client->insertProducts($products);

$products = $feed->getProducts();
foreach ($products as $product) {
    if ($product->getBatchStatus() != '200' &&
        $product->getBatchStatus() != '201') {
        $errors = $product->getErrorsFromBatch();

If an errors element is not found, errors is null; if it is found, a GSC_Errors is returned.

In rare cases, a batch interruption can occur. In this case, you get an entry returned that doesn't contain any product or batch:id, but instead contains the field batch:interrupted. This means that all products that are not reported as processed, have been dropped.

Inspecting Errors

The errors returned by the Content API for Shopping server are in the gd:errors element with a list of gd:error elements corresponding to each error. These errors contain similar information as the warnings elements:

$errorArray = $errors->getErrors();

foreach ($errorArray as $error) {
    echo 'Code: ' . $error->getCode() . "\n";
    echo 'Domain: ' . $error->getDomain() . "\n";
    echo 'Location: ' . $error->getLocation() . "\n";
    echo 'Internal Reason: ' . $error->getInternalReason() . "\n";

Warnings and Dry-run Mode

The Content API for Shopping allows you to run all the requests that modify persistent data (insert, update, delete) in dry-run mode. A dry-run request is similar to a normal request (authentication checks are performed as well as validity checks of the operation and the item), but the final step of persisting the changes is skipped. Dry-run mode is intended to check the validity of your requests. For update and delete operations, the validity of the request is determined independently of the item's existence.

You can set a single request or all operations in a batch to be executed in dry-run, by appending the dry-run query parameter at the end of the batch URL request. The PHP client library does this for you by providing an option to send a request in dry-run mode with an optional boolean argument. This argument defaults to false, but when set to true, the parameter is appended to the query. For example, to test if an insert of product will succeed:

$insertedProduct = $client->insertProduct($product, null, true);

Note: The first optional argument is reserved for enabling warnings, which we discuss below. It is "false"-y by default, so setting it to null retains the default behavior.

The Content API for Shopping can also return warnings, which allow some non-fatal product data issues to be detected.

As with the dry-run mode, warnings are opt-in, and should be enabled by adding the warnings parameter to the request URL. If this parameter is provided, additional warning elements are returned. As noted in the editing section, warnings can be used to make edits to improve your product data. As with dry-run mode, an optional boolean argument can enable warnings:

$insertedProduct = $client->insertProduct($product, true);

When used, the warnings appear in the app:control element. When parsed by the PHP client library, we can access these warnings with the getWarnings method:

$warnings = $insertedProduct->getWarnings();

Accessing Product Performance Data

The Content API for Shopping allows users to view data on how often products have been clicked on Google (for example, Google Shopping and Google Book Search).

To access this data, add the query parameters performance.start and performance.end to the GET request URI when retrieving a list of products. Each of these parameters should be a date, one for the start, and one for the end of the required period of performance data.

This is enabled in the getProducts client method via the third and fourth (optional) arguments in the signature. (Start is the third argument and end is the fourth). To specify these dates, you can use a string date represented as 'YYYY-MM-DD'. For example, to retrieve the product data for for your first 5 products from January 1, 2012 to January 5, 2012:

$maxResults = '5';
$performanceStart = '2012-01-01';
$performanceEnd = '2012-01-05';
$productFeed = $client->getProducts($maxResults, null,
                                    $performanceStart, $performanceEnd);

By enabling this, we can access the performance data for each parsed GSC_Product in the result productFeed using the getDatapoints method:

$products = $productFeed->getProducts();
foreach ($products as $product) {
    echo $product->getTitle() . "\n";

    $datapoints = $product->getDatapoints();

    // $datapoints is a DOMNodeList
    for($index = 0; $index < $datapoints->length; $index++) {
        $datapoint = $datapoints->item($index);
        echo $product->getDatapointPaidClicks($datapoint).
             ' paid clicks on '.
             $product->getDatapointDate($datapoint) . "\n";

The generic projection

The schema projection is used in all of the examples above, but the PHP client library can also handle the generic projection. Product data returned from the generic projection does not have any scp elements; they are all replaced by generic attributes.

Instead of the scp attributes, we get a list of generic attributes (sc:attribute) and generic attribute groups (sc:group).

For example, rather than

<scp:availability>in stock</scp:availability>
you receive
<sc:attribute name="availability">in stock</sc:attribute>

For a group example, rather than

you receive
<sc:group name="tax">
  <sc:attribute name="country">US</sc:attribute>
  <sc:attribute name="region">CA</sc:attribute>
  <sc:attribute name="rate">8.25</sc:attribute>
  <sc:attribute name="tax ship">true</sc:attribute>

The PHP client library handles them as it handles other repeated elements such as shipping; the methods add another block of XML rather than setting it. To construct the group above corresponding to tax and add it to a product entry:

$country = $product->_createAttribute('US', 'country');
$region = $product->_createAttribute('CA', 'region');
$rate = $product->_createAttribute('8.25', 'rate');
$taxShip = $product->_createAttribute('true', 'tax ship');

$attributes = array($country, $region, $rate, $taxShip);
$product->setGroup('tax', $attributes);

In specifying only two arguments, we only used the name attribute of the sc:attribrute XML elements, but it is also possible to use the XML attributes type and unit as the third and fourth arguments to _createAttribute, respectively.

The advantage of this method is that it can be used for products as well as other item categories that might be available in the future. The downside is that locating and using returned attributes becomes more complicated, potentially slower, and error-prone, because of the unsafe conversion logic from standard attributes to generic attributes.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.