{"id":21302895,"url":"https://github.com/billgerrard/google-content-api","last_synced_at":"2025-08-11T05:12:05.086Z","repository":{"id":55863509,"uuid":"126528219","full_name":"billgerrard/google-content-api","owner":"billgerrard","description":"Google::ContentAPI - Perl module to interact with Google's Content API for Shopping","archived":false,"fork":false,"pushed_at":"2020-12-11T22:59:19.000Z","size":19,"stargazers_count":1,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-11T20:41:56.897Z","etag":null,"topics":["adwords","content-api","google","google-api","hacktoberfest","perl","shopping"],"latest_commit_sha":null,"homepage":"https://metacpan.org/pod/Google::ContentAPI","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/billgerrard.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-23T19:03:16.000Z","updated_at":"2021-10-04T15:39:15.000Z","dependencies_parsed_at":"2022-08-15T08:00:55.790Z","dependency_job_id":null,"html_url":"https://github.com/billgerrard/google-content-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/billgerrard/google-content-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fgoogle-content-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fgoogle-content-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fgoogle-content-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fgoogle-content-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/billgerrard","download_url":"https://codeload.github.com/billgerrard/google-content-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/billgerrard%2Fgoogle-content-api/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269832914,"owners_count":24482337,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adwords","content-api","google","google-api","hacktoberfest","perl","shopping"],"created_at":"2024-11-21T15:58:12.271Z","updated_at":"2025-08-11T05:12:05.019Z","avatar_url":"https://github.com/billgerrard.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"=head1 NAME\n\nGoogle::ContentAPI - Interact with Google's Content API for Shopping\n\n=head1 DESCRIPTION\n\nAdd, modify and delete items from the Google Merchant Center platform via\nthe Content API for Shopping.\n\nAuthentication is done via Service Account credentials. See the following for details:\nL\u003chttps://developers.google.com/shopping-content/v2/how-tos/service-accounts\u003e\n\nYou will also need to create a Merchant Center Account:\nL\u003chttps://developers.google.com/shopping-content/v2/quickstart\u003e\n\nFor convenience, add your Merchant account ID to the *.json file provided by Google.\nYour complete *.json file, after adding your merchant ID, will look something like this:\n\n  {\n    \"endpoint\": \"https://www.googleapis.com/content/v2.1\",\n    \"merchant_id\": \"123456789\",\n    \"type\": \"service_account\",\n    \"project_id\": \"content-api-194321\",\n    \"private_key_id\": \"11b8e20c2540c788e98b49e623ae8167dc3e4a6f\",\n    \"private_key\": \"-----BEGIN PRIVATE KEY-----\n    ...\n    -----END PRIVATE KEY-----\\n\",\n    \"client_email\": \"google@content-api.iam.gserviceaccount.com\",\n    \"client_id\": \"999999999\",\n    \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",\n    \"token_uri\": \"https://accounts.google.com/o/oauth2/token\",\n    \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",\n    \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/google%40content-api.iam.gserviceaccount.com\"\n  }\n\n=head1 SYNOPSIS\n\n  use Google::ContentAPI;\n  use Data::Dumper;\n\n  my $google = Google::ContentAPI-\u003enew({\n      endpoint =\u003e 'https://www.googleapis.com/content/v2.1',\n      debug =\u003e 0,\n      config_file =\u003e 'content-api-key.json',\n      config_json =\u003e $json_text,\n      merchant_id =\u003e '123456789',\n  });\n\n  my ($result, $products, $batch_id, $product_id);\n\n  # get account auth info (merchantId)\n  $result = $google-\u003eget(\n    resource =\u003e 'accounts',\n    method   =\u003e 'authinfo'\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"authinfo: \\n\". Dumper $result;\n\n  # get status of your merchant center account\n  $result = $google-\u003eget(\n      resource =\u003e 'accountstatuses',\n      method   =\u003e 'get',\n      id =\u003e $google-\u003e{merchant_id} # your merchant ID unless working with multi-client account\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Account status: \\n\". Dumper $result;\n\n  # list status of multi-client accounts (MCA)\n  # This will fail with response code 403 if the account is not a multi-client account.\n  $result = $google-\u003eget(\n      resource =\u003e 'accountstatuses',\n      method   =\u003e 'list',\n      params   =\u003e ['maxResults' =\u003e 10]\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Account status: \\n\". Dumper $result;\n\n  # list products\n\n  $result = $google-\u003eget(\n      resource =\u003e 'products',\n      method   =\u003e 'list',\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Products list: \\n\". Dumper $result;\n\n  # insert a product\n\n  $result = $google-\u003epost(\n      resource =\u003e 'products',\n      method   =\u003e 'insert',\n      body =\u003e {\n        contentLanguage =\u003e 'en',\n        targetCountry =\u003e 'US',\n        channel =\u003e 'online',\n        offerId =\u003e '333333',\n        title =\u003e 'Item title',\n        description =\u003e 'The item description',\n        link =\u003e 'http://www.google.com',\n        imageLink =\u003e 'https://www.google.com/images/logo.png',\n        availability =\u003e 'in stock',\n        condition =\u003e 'new',\n        price =\u003e {\n            value =\u003e '99.95',\n            currency =\u003e 'USD',\n        },\n        shipping =\u003e [\n          {\n            country =\u003e 'US',\n            service =\u003e 'Standard Shipping',\n            price =\u003e {\n                value =\u003e '7.95',\n                currency =\u003e 'USD',\n            },\n          },\n        ],\n        brand =\u003e 'Apple',\n        gtin =\u003e '333333-67890',\n        mpn =\u003e '333333',\n        googleProductCategory =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Apples',\n        productTypes =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Apples',\n        customLabel1 =\u003e 'apples'\n      }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n  # get single product info\n\n  $product_id = '333333';\n  $result = $google-\u003eget(\n      resource =\u003e 'products',\n      method   =\u003e 'get',\n      id =\u003e 'online:en:US:'. $product_id\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Products info: \\n\". Dumper $result;\n\n  # delete a product\n\n  my $del_product_id = '333333';\n  $result = $google-\u003edelete(\n      resource =\u003e 'products',\n      method   =\u003e 'delete',\n      id =\u003e 'online:en:US:'. $del_product_id,\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '204' ? 'success' : 'failure') .\"\\n\"; # 204 = delete success\n\n  # batch insert\n\n  $products = [];\n  $batch_id = 0;\n\n  foreach my $i ('211203'..'211205') {\n      push @$products, {\n          batchId =\u003e ++$batch_id,\n          merchantId =\u003e $google-\u003e{merchant_id},\n          method =\u003e 'insert', # insert / get / delete\n          #productId =\u003e '', # for get / delete\n          product =\u003e { # for insert\n              contentLanguage =\u003e 'en',\n              targetCountry =\u003e 'US',\n              channel =\u003e 'online',\n              offerId =\u003e \"$i\",\n              title =\u003e \"item title $i\",\n              description =\u003e \"The item description for $i\",\n              link =\u003e 'http://www.google.com',\n              imageLink =\u003e 'https://www.google.com/images/logo.png',\n              availability =\u003e 'in stock',\n              condition =\u003e 'new',\n              price =\u003e {\n                  value =\u003e '10.95',\n                  currency =\u003e 'USD',\n              },\n              shipping =\u003e [\n                {\n                  country =\u003e 'US',\n                  service =\u003e 'Standard Shipping',\n                  price =\u003e {\n                      value =\u003e '7.95',\n                      currency =\u003e 'USD',\n                  },\n                },\n              ],\n              brand =\u003e 'Apple',\n              gtin =\u003e \"${i}-67890\",\n              mpn =\u003e \"$i\",\n              googleProductCategory =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Apples',\n              productTypes =\u003e 'Home \u0026 Garden \u003e Household Supplies \u003e Apples',\n              customLabel1 =\u003e 'apples'\n          }\n      };\n  }\n\n  $result = $google-\u003epost(\n      resource =\u003e 'products',\n      method   =\u003e 'batch',\n      body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n  # batch get:\n\n  $products = [];\n  $batch_id = 0;\n  foreach my $product_id ('211203'..'211205') {\n      push @$products, {\n          batchId =\u003e ++$batch_id,\n          merchantId =\u003e $google-\u003e{merchant_id},\n          method =\u003e 'get', # insert / get / delete\n          productId =\u003e 'online:en:US:'. $product_id, # for get / delete\n      };\n  }\n\n  $result = $google-\u003epost(\n      resource =\u003e 'products',\n      method   =\u003e 'batch',\n      body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print Dumper $result;\n\n  # batch delete:\n\n  $products = [];\n  $batch_id = 0;\n  foreach my $product_id ('211203'..'211205') {\n      push @$products, {\n          batchId =\u003e ++$batch_id,\n          merchantId =\u003e $google-\u003e{merchant_id},\n          method =\u003e 'delete', # insert / get / delete\n          productId =\u003e 'online:en:US:'. $product_id, # for get / delete\n      };\n  }\n\n  $result = $google-\u003epost(\n      resource =\u003e 'products',\n      method   =\u003e 'batch',\n      body =\u003e { entries =\u003e $products }\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n\n  # list status of products\n\n  $result = $google-\u003eget(\n      resource =\u003e 'productstatuses',\n      method   =\u003e 'list',\n      params   =\u003e [\n          'maxResults' =\u003e 10\n      ]\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Product status: \\n\". Dumper $result;\n\n  # get status of a specific product\n\n  $product_id = '333333';\n  $result = $google-\u003eget(\n      resource =\u003e 'productstatuses',\n      method   =\u003e 'get',\n      id =\u003e 'online:en:US:'. $product_id\n  );\n  print \"$result-\u003e{code} \". ($result-\u003e{code} eq '200' ? 'success' : 'failure') .\"\\n\";\n  print \"Product status: \\n\". Dumper $result;\n\n=head1 METHODS AND FUNCTIONS\n\n=head2 new()\n\nCreate a new Google::ContentAPI object\n\n=head3 endpoint\n\nAPI endpoint to use.\nv2.1 endpoint is 'https://www.googleapis.com/content/v2.1'.\nv2.0 endpoint is 'https://www.googleapis.com/content/v2'.\nIf not provided, default to v2.0 endpoint for backwards compatibility.\n\n=head3 debug\n\nDisplays API debug information\n\n=head3 config_file\n\nPath and filename of external C\u003c.json\u003e config file.\nEither config_file or config_json must be provided. If both config_file\nand config_json are provided, config_file will be used.\n\n=head3 config_json\n\nText containing contents of the json config. Useful if you want to\nstore the json config in another resource such as a database.\nEither C\u003cconfig_file\u003e or C\u003cconfig_json\u003e must be provided. If both C\u003cconfig_file\u003e\nand C\u003cconfig_json\u003e are provided, C\u003cconfig_file\u003e will be used.\n\n=head3 merchant_id\n\noptional if merchant_id is specified in json config\n\n=head2 ACCOUNTS\n\n=head3 authinfo\n\nReturns information about the authenticated user.\n\n=head2 ACCOUNTSTATUSES\n\n=head3 list\n\nLists the the status of accounts in a Multi-Client account.\nThis will fail with response code C\u003c403\u003e if the account is not a multi-client account.\n\n=head3 get\n\nRetrieves the status of your Merchant Center account.\n\n=head2 PRODUCTS\n\n=head3 custombatch\n\nRetrieves, inserts, and deletes multiple products in a single request.\n\n=head3 insert\n\nUploads a product to your Merchant Center account. If an item with the\nsame channel, contentLanguage, offerId, and targetCountry already exists,\nthis method updates that entry.\n\n=head3 list\n\nLists the products in your Merchant Center account.\n\n=head3 get\n\nRetrieves a product from your Merchant Center account.\n\n=head3 delete\n\nDeletes a product from your Merchant Center account.\n\n=head2 PRODUCTSTATUSES\n\n=head3 list\n\nLists the the status and issues of products in your Merchant Center Account.\n\n=head3 get\n\nRetrieves the status and issues of a specific product.\n\n=head1 UNIMPLEMENTED FEATURES\n\nCertain API methods are not yet implemented (no current personal business need).\n\nA \"custom\" resource is available to perform methods that are not implemented by\nthis module.\n\n  # get an order from the merchant account\n  $result = $google-\u003eget(\n    resource =\u003e 'custom',\n    method   =\u003e 'merchantId/orders/orderId'\n  );\n\n=head1 PREREQUISITES\n\n  JSON\n  Crypt::JWT\n  REST::Client\n  HTML::Entities\n\n=head1 AUTHOR\n\nOriginal Author\nBill Gerrard \u003cbill@gerrard.org\u003e\n\n=head1 COPYRIGHT AND LICENSE\n\nCopyright (C) 2018,2020 Bill Gerrard\n  \nThis library is free software; you can redistribute it and/or modify\nit under the same terms as Perl itself, either Perl version 5.20.2 or,\nat your option, any later version of Perl 5 you may have available.\nDisclaimer of warranty: This program is provided by the copyright holder\nand contributors \"As is\" and without any express or implied warranties.\nThe implied warranties of merchantability, fitness for a particular purpose,\nor non-infringement are disclaimed to the extent permitted by your local\nlaw. Unless required by law, no copyright holder or contributor will be\nliable for any direct, indirect, incidental, or consequential damages\narising in any way out of the use of the package, even if advised of the\npossibility of such damage.\n\n\n=cut\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbillgerrard%2Fgoogle-content-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbillgerrard%2Fgoogle-content-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbillgerrard%2Fgoogle-content-api/lists"}