Skip to main content

Google Merchant Center CLI for the Merchant API v1 — products, feeds, reports, promotions. JSON output, jq-friendly.

Project description

gmc-cli — Google Merchant Center CLI

CI PyPI License: Apache-2.0

A standalone command-line client for the Google Merchant API v1 (merchantapi.googleapis.com) — the GA replacement for the Content API for Shopping, which Google retires in August 2026.

Drive your Merchant Center from the terminal (or from an AI agent): products, feeds, performance reports, price benchmarks, promotions, account settings. One auditable codebase, credentials never leave your machine, all output is JSON on stdout — pipe it to jq.

pipx install gmc-cli

gmc auth login --client-id= --client-secret= --merchant-id=1234567890
gmc register-gcp          # one-time Google requirement, see below

gmc products issues-summary | jq '.top_issue_codes'
gmc report performance --start 2026-06-01 --end 2026-06-30 --order-by clicks

Why

  • CLI, not SaaS: no third-party service proxies your Merchant Center data.
  • Merchant API v1: built on the new GA API, not the deprecated Content API v2.1.
  • Read-first safety model: only three write commands exist, deletes require --yes, and a global --dry-run prints the exact HTTP request instead of sending it.
  • Agent-friendly: predictable JSON output and one flat command tree make it easy to hand to Claude/other AI agents as a tool.

Install

pipx install gmc-cli        # recommended (isolated)
# or: pip install gmc-cli

From source:

git clone https://github.com/almoretti/gmc-cli && cd gmc-cli
./setup.sh                  # local venv + editable install; run via ./gmc

Setup

1. Create an OAuth client (one-time, ~3 minutes)

  1. Go to Google Cloud Console → pick or create a project.
  2. Enable the Merchant API.
  3. APIs & Services → Credentials → Create Credentials → OAuth client ID → Desktop app. Copy the client ID and secret.
  4. If the OAuth consent screen is in Testing mode, add yourself as a test user (and note refresh tokens expire after 7 days until you publish the app to In production).

2. Log in

gmc auth login --client-id=xxx --client-secret=xxx --merchant-id=1234567890

Opens a browser — sign in with a Google account that has access to your Merchant Center (the numeric merchant ID is in the top-right of merchants.google.com). Credentials are saved to ~/.config/gmc-cli/credentials.json (chmod 600) and refresh automatically.

3. Register your GCP project (one-time, mandatory)

Google requires the GCP project behind your OAuth client to be registered as a developer with the merchant account, or every API call returns 401:

gmc register-gcp --developer-email you@example.com
gmc auth check    # should print your account name and "ok": true

Idempotent — safe to re-run.

Alternative credentials

  • Service account (headless automation): set GMC_SERVICE_ACCOUNT_KEY to a JSON key path, and add the service account's email as a user in Merchant Center → Settings → People and access.
  • Env/dotenv: GMC_ACCOUNT_ID, GMC_SUBACCOUNT_ID (act on an MCA sub-account), GMC_OAUTH_TOKEN. A .env in the working directory is read.
  • ADC fallback: gcloud auth application-default login with the content scope.

Resolution order: GMC_SERVICE_ACCOUNT_KEYGMC_OAUTH_TOKEN~/.config/gmc-cli/credentials.json → ADC. Merchant ID: --merchant-idGMC_SUBACCOUNT_ID/GMC_ACCOUNT_ID → saved config.

Commands

gmc auth login | check | init --client-secrets FILE
gmc register-gcp [--developer-email EMAIL]        # one-time per GCP project
gmc account get | list | issues | users | programs | shipping | homepage | business-info
gmc products list [--limit N] [--full]
gmc products get|status ID                        # ID = contentLanguage~feedLabel~offerId
gmc products disapproved                          # all disapproved products (via Reports)
gmc products issues-summary                       # issue codes ranked by frequency
gmc products insert --product @p.json --data-source accounts/…/dataSources/…   (WRITE)
gmc products delete ID --data-source … --yes                                   (WRITE)
gmc report query "SELECT … FROM product_performance_view WHERE …"
gmc report performance --start YYYY-MM-DD --end YYYY-MM-DD [--order-by clicks] [--top N]
gmc report zero-clicks [--min-impressions N] [--start …] [--end …]
gmc report price-competitiveness | price-insights | demoted
gmc report best-sellers [--country GB] [--granularity WEEKLY|MONTHLY]
gmc report competitors [--country GB] [--category 469] [--traffic-source ALL|ADS|ORGANIC]
gmc datasources list | get ID | fetch ID          # fetch = WRITE, triggers feed re-crawl
gmc promotions list | get ID
gmc regions | quotas | return-policies
gmc raw GET|POST|PATCH|PUT|DELETE <path> [--body JSON] [--param k=v]   # escape hatch

Global flags: --merchant-id ID, --dry-run (print writes instead of sending), -v (retry diagnostics), --version.

Defaults note: report shortcuts default to --country GB and --category 469 (Health & Beauty) — override for your market (category IDs).

Examples

# What's broken in my feed, ranked by issue code?
gmc products issues-summary | jq '.top_issue_codes'

# Top products by clicks, last 30 days, as TSV
gmc report performance --start 2026-06-09 --end 2026-07-08 \
  | jq -r '.results[].productPerformanceView | [.offerId, .clicks, .impressions] | @tsv'

# Where am I priced above the market benchmark?
gmc report price-competitiveness | jq '.results[].priceCompetitivenessProductView
  | select((.price.amountMicros|tonumber) > (.benchmarkPrice.amountMicros|tonumber))'

# Force an immediate re-fetch of a scheduled feed
gmc datasources list | jq -r '.dataSources[].dataSourceId'
gmc datasources fetch 123456789

# Preview a product upsert without sending it
gmc --dry-run products insert --product @sku.json --data-source accounts/…/dataSources/…

# Anything the built-ins don't cover
gmc raw GET conversions/v1/accounts/1234567890/conversionSources

Safety model

  • Reads are unrestricted; writes exist only for products insert/delete and datasources fetch; delete requires --yes.
  • Global --dry-run short-circuits any write and prints the exact request.
  • Retries with exponential backoff + Retry-After on 429/5xx.
  • gmc raw can perform any method — use deliberately.
  • Product inserts only work against API-type data sources; feeds fetched from files/Sheets can't be written via the API (use datasources fetch to trigger re-crawls instead, or overlay a supplemental API data source).

Merchant API v1 notes (learned the hard way)

  • Product IDs: contentLanguage~feedLabel~offerId (e.g. en~GB~SKU123).
  • Product writes go through productInputs:insert (upsert — full body overwrites) and always require a dataSource.
  • v1 vs v1beta field changes: gtingtins (list), attributesproductAttributes, enums are UPPER_CASE strings, channel/taxes removed.
  • Report dialect rules (all verified live; the built-in shortcuts handle them):
    • ctrclick_through_rate; conversion_value_microsconversion_value
    • product_performance_view requires a date condition in WHERE
    • price_competitiveness_product_view requires report_country_code + id in SELECT
    • price_insights_product_view requires id in SELECT
    • best_sellers_* requires report_date, report_granularity, report_country_code, report_category_id in SELECT and a report_granularity WHERE condition
    • competitive_visibility_* requires report_country_code, report_category_id, traffic_source in SELECT and WHERE conditions on date, report_category_id, traffic_source

Testing

./test.sh runs a 45-check functional suite against whatever merchant account you're logged into: every read command live, every write in --dry-run only, plus the guard rails. It never mutates your feed.

Acknowledgements

Endpoint conventions were originally mapped out by studying kiwoongeom/gmc-mcp (MIT), an MCP server for the same API. No code was copied; this project exists for people who want a plain CLI with no MCP layer.

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gmc_cli-0.1.0.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gmc_cli-0.1.0-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file gmc_cli-0.1.0.tar.gz.

File metadata

  • Download URL: gmc_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 20.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gmc_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6ac4007028d81cb2ea9d01558024ffd889a4fccab3907e9bb98dba10f4f17b9f
MD5 44954759008310738695b9b19a2253ca
BLAKE2b-256 63d685ab73cf942f54567ef591f11ee618c9e6acd1d3202791ac16c3375e7753

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmc_cli-0.1.0.tar.gz:

Publisher: publish.yml on almoretti/gmc-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file gmc_cli-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gmc_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 18.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gmc_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 de413b05bf0a06f8ac85e407c1e2a03c58c6cf57959b483fbc10136d857a567f
MD5 f6bd74f49fd6107fd5f7a251bfdfef84
BLAKE2b-256 5f66bcba5eb5288bbbcf5d44eb96baf235ee24fea853547f667ce9d2559787c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for gmc_cli-0.1.0-py3-none-any.whl:

Publisher: publish.yml on almoretti/gmc-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page