Google Merchant Center — Setup
How to obtain a Google OAuth client_id / client_secret, configure them in admin settings, and pick (or create) a Merchant Center data source for the sync to target.
How to obtain a Google OAuth client_id / client_secret, configure them in admin settings, and pick (or create) a Merchant Center data source for the sync to target.
Scope of this doc: the one-time credential + data-source acquisition flow. The rest of the integration — OAuth handshake, bootstrap sync, field mapping, RBAC, operational behaviour — lives in
docs/separated/admin/google-merchant/*.
Prerequisites
- A Google account with Standard or Admin access to the target Merchant Center account. Verify at
merchants.google.com→ Settings → Users. - The numeric Merchant ID from the Merchant Center dashboard URL (
https://merchants.google.com/mc/overview?a=<MERCHANT_ID>). - The public API base URL for the environment you're configuring (e.g.
https://api.your-shop.comfor production).
Step 1 — Create or pick a Google Cloud project
Open console.cloud.google.com and either select an existing project or create a new one. One project per environment (dev / staging / prod) is cleanest; one shared project works too if you register multiple redirect URIs on a single OAuth client.
Step 2 — Enable the Merchant API
Cloud Console → APIs & Services → Library → search for Merchant API → Enable.
This is the only API the plugin calls. (We target the stable merchantapi_products_v1 and merchantapi_datasources_v1 surfaces — the legacy "Content API for Shopping" is deprecated and not used.)
Step 3 — Configure the OAuth consent screen
Cloud Console → APIs & Services → OAuth consent screen.
-
User Type:
- Internal — recommended if the operator uses Google Workspace. No Google review required; only accounts in your Workspace org can consent.
- External — required for personal Gmail accounts. Stays in "Testing" mode (no review required) as long as you add the operator's email under "Test users".
-
App info:
- App name: anything identifying the integration to the operator (e.g.
Acme Storefront — Merchant Sync). - User support email: the operator's contact.
- Authorized domains: the apex domain of the API host (e.g.
your-shop.comif the API isapi.your-shop.com).
- App name: anything identifying the integration to the operator (e.g.
-
Scopes → Add or remove scopes → tick:
https://www.googleapis.com/auth/contentThis is the only scope the plugin requests. The same scope authorizes both the legacy Content API and the new Merchant API.
-
Test users (External + Testing only): add the operator's Google account email — the one that will complete the consent flow.
-
Save.
Step 4 — Create the OAuth 2.0 Client ID
Cloud Console → APIs & Services → Credentials → Create credentials → OAuth client ID.
-
Application type: Web application
-
Name: e.g.
Acme Storefront — Merchant Sync (prod) -
Authorized redirect URIs: add the exact callback URL for this environment:
{API_BASE_URL}/admin/google-merchant/oauth/callbackEnvironment Redirect URI Local dev http://localhost:3000/admin/google-merchant/oauth/callbackStaging https://api-staging.your-shop.com/admin/google-merchant/oauth/callbackProduction https://api.your-shop.com/admin/google-merchant/oauth/callbackGoogle compares this byte-for-byte at callback time. Any mismatch (extra slash, wrong protocol, wrong port) fails with
redirect_uri_mismatch. HTTPS is required for any non-localhosthost.
Click Create. Google shows the generated Client ID and Client secret — copy both. The secret is shown only at creation time; if you lose it, regenerate.
Step 5 — Configure credentials in admin settings
Set the following keys under the google_merchant group in admin scope. Use the admin UI or:
PUT /admin/settings
Content-Type: application/json
{
"scope": "admin",
"group": "google_merchant",
"values": {
"client_id": "1234567890-abcdef.apps.googleusercontent.com",
"client_secret": "GOCSPX-...",
"merchant_id": "123456789",
"redirect_uri": "https://api.your-shop.com/admin/google-merchant/oauth/callback"
}
}| Key | Source |
|---|---|
client_id | Step 4 |
client_secret | Step 4 — SENSITIVE; treat like a password |
merchant_id | Prerequisites — numeric ID from the Merchant Center URL |
redirect_uri | Step 4 — must match exactly one of the URIs registered on the OAuth client |
redirect_uri is optional if PUBLIC_API_URL is set in the environment — the plugin will derive the callback URL automatically. Setting it explicitly is recommended for production so it can't drift on an env-var change.
Step 6 — Complete the OAuth handshake
Before you can list or create data sources, the OAuth credentials need to be persisted. Run the connect flow:
GET /admin/google-merchant/oauth/start→ returns a Google consent URL.- The admin completes consent in the browser.
- Google redirects to
/admin/google-merchant/oauth/callbackand the plugin stores the access + refresh tokens.
Verify with GET /admin/google-merchant/status — configuration.oauthClient should now read "configured".
Step 7 — Pick or create a Merchant Center data source
The Merchant API requires every product input to be attributed to a data source. Operators have two ways to set this up:
Option A — Pick an existing data source
GET /admin/google-merchant/data-sourcesReturns the data sources visible to the connected Google account. Example response:
{
"data": [
{
"id": "104628",
"name": "accounts/123456/dataSources/104628",
"displayName": "Primary feed",
"input": "API",
"isPrimary": true,
"contentLanguage": "en",
"feedLabel": "IN"
},
{
"id": "211774",
"name": "accounts/123456/dataSources/211774",
"displayName": "Manual CSV uploads",
"input": "FILE",
"isPrimary": true,
"contentLanguage": "en",
"feedLabel": "IN"
}
]
}Only entries with input: "API" and isPrimary: true are valid sync targets. Once the admin picks one, write the numeric id to settings:
PUT /admin/settings
{ "scope": "admin", "group": "google_merchant", "values": { "data_source_id": "104628" } }Option B — Create a new data source
If no existing source fits (most common scenario for a fresh integration), create one:
POST /admin/google-merchant/data-sources
Content-Type: application/json
{ "displayName": "Supercommerce API feed" }contentLanguage and feedLabel are optional — when omitted, the plugin fills them from the language / country settings. The response is a single DataSourceSummary:
{
"data": {
"id": "318204",
"name": "accounts/123456/dataSources/318204",
"displayName": "Supercommerce API feed",
"input": "API",
"isPrimary": true,
"contentLanguage": "en",
"feedLabel": "IN"
}
}Write the id to data_source_id the same way as Option A.
Verifying the configuration
GET /admin/google-merchant/statusExpected response after credentials + data source are set, but before the OAuth handshake (or after — both shapes are useful):
{
"connected": true,
"configuration": {
"oauthClient": "configured",
"feed": "configured",
"missingKeys": []
},
"merchantAccount": { "merchantId": "123456789", "reachable": true, ... },
"dataSource": {
"dataSourceId": "318204",
"name": "accounts/123456/dataSources/318204"
},
"counts": { ... }
}configuration.feed: "configured" confirms client_id + client_secret + merchant_id + data_source_id + country/language/currency/storefront URL are all set. Proceed to the bootstrap-sync doc next.
Remaining configuration
The google_merchant group also accepts these admin settings — covered in the implementation docs:
| Key | Default | Purpose |
|---|---|---|
country / language / currency | IN / en / INR | Locale stamped on every product |
storefront_base_url | — | Public storefront origin |
storefront_product_path | /product/{slug} | Path template appended to base URL |
default_google_product_category, default_condition, identifier_exists_fallback | — | Per-feed defaults |
sync_enabled, sync_interval_seconds, batch_size, max_attempts | — | Worker behaviour |