googleclientlibraries

If your goal is to keep your Google Shopping Campaigns clean with accurate product data, availability, and pricing, then programmatic access via Google’s Content API for Shopping is the way to go. This is especially true for companies that have a large amount of products that move with high velocity, or have constant price changes. Using any one of the Google’s API Client Libraries to do things like this is a little easier since they have abstracted away some of the grittier details.  In most scenarios like this, the application is usually run on some server which in turn calls the Google API.  However, the user who owns the data behind the API is not around to grant such access.  This is where Service Accounts come into play.

I had previously wrote a Getting Started guide which should help you get familiar with the Content API for Shopping using OAuth authentication.  In this post we will take some of those previous examples and change them up a bit to use a Service Account.  I’ll walk through setting up the Service Account in Google’s Developer Console, and the code to make the API call. There are few things that you need to setup which you can find in my previous post.

What happens during the Authentication Process

Things are different in Service Account scenarios in that your application does not require user consent to get access to that user’s data.  So how does the respective API know that the application calling on behalf of the Service Account is fact the right authorized entity?  There are 3 components required to establish a trusted connection that are all created inside the Google Developer Console when creating a Service Account:

  • Client ID for the Service Account
  • Email address for the Service Account
  • A public and private key pair used for encryption

When your application makes the respective API call it must use an access token on each request. This is the sequence of events:

  • Your application uses the private key for the Service account to digitally sign a JSON Web Token (JWT) to make a request for an “access” token.  The private key generated in the Google Developer Console is unique and only available to you, and is only available the first time you create it.  You should keep this safe.  If you happen to lose it, you’ll need to generate a new key which is a bit of a hassle.
  • After signing and encrypting the JWT with the private key using the Service Account’s Email address, the only entity that can decrypt the JWT is the Google Authentication server that possesses the corresponding public key.  If the Google Authentication server successfully decrypts the JWT using the public key, it knows that the corresponding Service Account identified by the email address is in fact the right entity.  At this point the access token is returned to your application.
  • Subsequent calls to the respective API are made with this access token.

Next we’ll cover the configuration steps to make this happen:

Step 1: Creating the Client ID for a Service Account

Head over to the Google Developer Console and navigate to the “Credentials” menu under “API’s and Auth”.  From there click on “Create new Client ID”:

create_service_account_step1

Select the “Service Account” option:

create service account step 2

As soon as you create the Service Account, the system will generate a Client ID, email address, and a public/private key pair.  The private key is immediately downloaded to your browser.  Save this private key safely somewhere.  There is a password that comes with this private key that you will need later.  The password is “notasecret” and is the same for every private key that is generated. This is OK since you are the only one in possession of this private key.:

create service account step 3

You will notice a client ID and email address are also created for the Service Account you just created.  Make note of the email address as you will need this later:

create service account step 4

Step 2: Granting Permissions inside Google Merchant Center for the Client ID

This next step is very important and is not called out very clearly in Google’s documentation and is very easy to miss.   Just because you can digitally sign JWT’s and Google’s authentication server can verify your application is calling on behalf of the Service Account, it doesn’t mean your application can access just any account’s data behind the API whether that be Google Analytics, Google Merchant Center, Adwords, etc.   In this example we are going have our program call the Content API for Shopping to retrieve a product from the corresponding Google Merchant Center account.

Login to the corresponding Google Merchant Center Account and navigate to the “Users” menu under “Settings”.  Enter the Service Account email address here and grant it “Standard” access.

create service account step 5

Keep in mind this example is for a Service Account to access data within Google Merchant Center. If you are writing an application to access AdWords, Google Analytics, or some other Google platform you will need to do something similar in terms of granting the Service Account’s email the appropriate level of access.

Step 3: Converting the PKCS12 key to PEM format

When I first tried to use the private key in my program I received this error:

Error 3: PKCS12 format is not supported by the PyCrypto library. 

NotImplementedError: PKCS12 format is not supported by the PyCrypto library. Try converting to a “PEM” (openssl pkcs12 -in xxxxx.p12 -nodes -nocerts > privatekey.pem) or using PyOpenSSL if native code is an option.

Apparently the private key format (PKCS12) generated from the Google Developer Console is not compatible with the PyCrypto module 2.6.1 that I installed to handle encryption.  Use OpenSSL to convert the private key to the PEM format by typing this on the command line:

openssl pkcs12 -in [your PKCS12 private key from the Google Developer Console].p12 -nodes -nocerts > ConvertedPrivateKey.pem

*Note: I had installed Win32 OpenSSL as explained in my previous post. The openssl.exe is located in the “bin” directory where Win32 OpenSSL was installed and was added to my PATH environment variable for easy access.

You will be asked to enter a password at which point type in “notasecret”. The corresponding private key will be created in the PEM format.  Open up this file and delete the header contents and re-save the file:

create a service account step 6

Step 4: Calling the Content API for Shopping

The entire code listing for this example can be found on GitHub.  The program takes in two arguments, the Merchant Center account ID and the corresponding ID of the product you wish to retrieve using a Service Account.  Make sure the private key file you created in Step 3 is accessible by this program (I kept the private key file in the same directory of this program to keep things simple for this example). Replace the corresponding client_email with the Service Account’s email address (line 25)  and edit line 47 with the name of your private key file:

with open([Your PEM Key].pem) as f:

Save the python program.  You can now start the program as follows:

python serviceaccount_product_get.py [yourMerchantCenterID] [productID]

Next, we’ll walk through some of the important parts of the code to explain what’s going on.

As mentioned earlier, in order to get an access token to call the respective API, you must create a signed JSON Web Token (JWT). Creating an instance of a SignedJwtAssertionCredentials object is accomplished by passing in your client_email address for the Service Account (Step 1), your private key (Step 3), and something called a “scope”.   This is a string that informs Google the type of access you want when making the API call to the underlying resource.  Many of the scopes can be found in Google’s OAuth 2.0 Playground site.  In our example we are looking to make the call to the Content API for Shopping, and the respective scope is “https://www.googleapis.com/auth/content “:

credentials = SignedJwtAssertionCredentials(
    client_email,
    private_key,
    “https://www.googleapis.com/auth/content “)

This next line authorizes an Http() object with the appropriate credentials:

http_auth = credentials.authorize(Http())

Creating the service object and passing in the authorized Http object:

contentService = build(“content”,
     “v2”,
     http=http_auth)

Setting up the request for the products().get method to retrieve the product:

request = contentService.products().get(merchantId=merchant_id,                productId=online:en:US:+product_id)

Making the call to the API:

result = request.execute()

There you have it!  There is a lot of setup work to get things ready when using a Service Account, but once that’s done you can focus on the core parts of your server to server based application.  You can learn more about the various API’s through Google’s API explorer which comes in handy when you’re testing request and response formats: https://developers.google.com/apis-explorer/