NAME

  Google::ContentAPI - Interact with Google's Content API for Shopping

DESCRIPTION

  Add, modify and delete items from the Google Merchant Center platform via
  the Content API for Shopping.

  Authentication is done via Service Account credentials. See the following for details:
  https://developers.google.com/shopping-content/v2/how-tos/service-accounts

  You will also need to create a Merchant Center Account:
  https://developers.google.com/shopping-content/v2/quickstart

  For convenince, add your Merchant account ID to the *.json file provided by Google.
  Your complete *.json file, after adding your merchant ID, will look something like this:

  {
    "merchant_id": "123456789",
    "type": "service_account",
    "project_id": "content-api-194321",
    "private_key_id": "11b8e20c2540c788e98b49e623ae8167dc3e4a6f",
    "private_key": "-----BEGIN PRIVATE KEY-----
    ...
    -----END PRIVATE KEY-----\n",
    "client_email": "google@content-api.iam.gserviceaccount.com",
    "client_id": "999999999",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/google%40content-api.iam.gserviceaccount.com"
  }

SYNOPSIS

  use Google::ContentAPI;
  use Data::Dumper;

  my $google = Google::ContentAPI->new({
      debug => 0,
      config_file => 'content-api-key.json',
      config_json => $json_text,
      merchant_id => '123456789',
  });

  my ($result, $products, $batch_id, $product_id);

  # get account auth info (merchantId)
  $result = $google->get(
    resource => 'accounts',
    method   => 'authinfo'
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "authinfo: \n". Dumper $result;

  # get status of your merchant center account
  $result = $google->get(
      resource => 'accountstatuses',
      method   => 'get',
      id => $google->{merchant_id} # your merchant ID unless working with multi-client account
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Account status: \n". Dumper $result;

  # list status of multi-client accounts (MCA)
  # This will fail with response code 403 if the account is not a multi-client account.
  $result = $google->get(
      resource => 'accountstatuses',
      method   => 'list',
      params   => ['maxResults' => 10]
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Account status: \n". Dumper $result;

  # list products

  $result = $google->get(
      resource => 'products',
      method   => 'list',
      params   => ['includeInvalidInsertedItems' => 'true']
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Products list: \n". Dumper $result;

  # insert a product

  $result = $google->post(
      resource => 'products',
      method   => 'insert',
      params   => ['dryRun' => 'true'],
      body => {
        contentLanguage => 'en',
        targetCountry => 'US',
        channel => 'online',
        offerId => '333333',
        title => 'Item title',
        description => 'The item description',
        link => 'http://www.google.com',
        imageLink => 'https://www.google.com/images/logo.png',
        availability => 'in stock',
        condition => 'new',
        price => {
            value => '99.95',
            currency => 'USD',
        },
        shipping => [
          {
            country => 'US',
            service => 'Standard Shipping',
            price => {
                value => '7.95',
                currency => 'USD',
            },
          },
        ],
        brand => 'Apple',
        gtin => '333333-67890',
        mpn => '333333',
        googleProductCategory => 'Home & Garden > Household Supplies > Apples',
        productType => 'Home & Garden > Household Supplies > Apples',
        customLabel1 => 'apples'
      }
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";

  # get single product info

  $product_id = '333333';
  $result = $google->get(
      resource => 'products',
      method   => 'get',
      id => 'online:en:US:'. $product_id
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Products info: \n". Dumper $result;

  # delete a product

  my $del_product_id = '333333';
  $result = $google->delete(
      resource => 'products',
      method   => 'delete',
      id => 'online:en:US:'. $del_product_id,
      #params   => ['dryRun' => 'true']
  );
  print "$result->{code} ". ($result->{code} eq '204' ? 'success' : 'failure') ."\n"; # 204 = delete success

  # batch insert

  $products = [];
  $batch_id = 0;

  foreach my $i ('211203'..'211205') {
      push @$products, {
          batchId => ++$batch_id,
          merchantId => $google->{merchant_id},
          method => 'insert', # insert / get / delete
          #productId => '', # for get / delete
          product => { # for insert
              contentLanguage => 'en',
              targetCountry => 'US',
              channel => 'online',
              offerId => "$i",
              title => "item title $i",
              description => "The item description for $i",
              link => 'http://www.google.com',
              imageLink => 'https://www.google.com/images/logo.png',
              availability => 'in stock',
              condition => 'new',
              price => {
                  value => '10.95',
                  currency => 'USD',
              },
              shipping => [
                {
                  country => 'US',
                  service => 'Standard Shipping',
                  price => {
                      value => '7.95',
                      currency => 'USD',
                  },
                },
              ],
              brand => 'Apple',
              gtin => "${i}-67890",
              mpn => "$i",
              googleProductCategory => 'Home & Garden > Household Supplies > Apples',
              productType => 'Home & Garden > Household Supplies > Apples',
              customLabel1 => 'apples'
          }
      };
  }

  $result = $google->post(
      resource => 'products',
      method   => 'batch',
      #params   => ['dryRun' => 'true'],
      body => { entries => $products }
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";

  # batch get:

  $products = [];
  $batch_id = 0;
  foreach my $product_id ('211203'..'211205') {
      push @$products, {
          batchId => ++$batch_id,
          merchantId => $google->{merchant_id},
          method => 'get', # insert / get / delete
          productId => 'online:en:US:'. $product_id, # for get / delete
      };
  }

  $result = $google->post(
      resource => 'products',
      method   => 'batch',
      #params   => ['dryRun' => 'true'],
      body => { entries => $products }
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print Dumper $result;

  # batch delete:

  $products = [];
  $batch_id = 0;
  foreach my $product_id ('211203'..'211205') {
      push @$products, {
          batchId => ++$batch_id,
          merchantId => $google->{merchant_id},
          method => 'delete', # insert / get / delete
          productId => 'online:en:US:'. $product_id, # for get / delete
      };
  }

  $result = $google->post(
      resource => 'products',
      method   => 'batch',
      #params   => ['dryRun' => 'true'],
      body => { entries => $products }
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";

  # list status of products

  $result = $google->get(
      resource => 'productstatuses',
      method   => 'list',
      params   => [
          'includeInvalidInsertedItems' => 'true',
          'maxResults' => 10
      ]
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Product status: \n". Dumper $result;

  # get status of a specific product

  $product_id = '333333';
  $result = $google->get(
      resource => 'productstatuses',
      method   => 'get',
      id => 'online:en:US:'. $product_id
  );
  print "$result->{code} ". ($result->{code} eq '200' ? 'success' : 'failure') ."\n";
  print "Product status: \n". Dumper $result;

METHODS AND FUNCTIONS

new()

  Create a new Google::ContentAPI object

debug

  Displays API debug information

config_file

  Path and filename of external .json config file.
  Either config_file or config_json must be provided. If both config_file
  and config_json are provided, config_file will be used.

config_json

  Text containing contents of the json config. Useful if you want to
  store the json config in another resource such as a database.
  Either config_file or config_json must be provided. If both config_file
  and config_json are provided, config_file will be used.

merchant_id

  optional if merchant_id is specificed in json config

ACCOUNTS

authinfo

  Returns information about the authenticated user.

ACCOUNTSTATUSES

list

  Lists the the status of accounts in a Multi-Client account.
  This will fail with response code 403 if the account is not a multi-client account.

get

  Retrieves the status of your Merchant Center account.

PRODUCTS

custombatch

  Retrieves, inserts, and deletes multiple products in a single request.

insert

  Uploads a product to your Merchant Center account. If an item with the
  same channel, contentLanguage, offerId, and targetCountry already exists,
  this method updates that entry.

list

  Lists the products in your Merchant Center account.

get

  Retrieves a product from your Merchant Center account.

delete

  Deletes a product from your Merchant Center account.

PRODUCTSTATUSES

list

  Lists the the status and issues of products in your Merchant Center Account.

get

  Retrieves the status and issues of a specific product.

UNIMPLEMENTED FEATURES

  Certain API methods are not yet implemented (no current personal business need).

  A "custom" resource is available to perform methods that are not implemented by
  this module.

  # get an order from the merchant account
  $result = $google->get(
    resource => 'custom',
    method   => 'merchantId/orders/orderId'
  );

PREREQUISITES

  JSON
  Crypt::JWT
  REST::Client
  HTML::Entities

AUTHOR

  Original Author
  Bill Gerrard <bill@gerrard.org>

COPYRIGHT AND LICENSE

  Copyright (C) 2018 Bill Gerrard

  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself, either Perl version 5.20.2 or,
  at your option, any later version of Perl 5 you may have available.
  Disclaimer of warranty: This program is provided by the copyright holder
  and contributors "As is" and without any express or implied warranties.
  The implied warranties of merchantability, fitness for a particular purpose,
  or non-infringement are disclaimed to the extent permitted by your local
  law. Unless required by law, no copyright holder or contributor will be
  liable for any direct, indirect, incidental, or consequential damages
  arising in any way out of the use of the package, even if advised of the
  possibility of such damage.