How to Add Inventory in Google Merchant Center?
To add inventory in Google Merchant Center (GMC), inventory data is managed through your product data sources.
For in-store products, inventory is provided using local inventory feeds, which are configured under Settings โ Data sources โ Supplemental sources.
You can supply this data by connecting a supported provider, uploading a feed file (via HTTPS, SFTP, or manual upload), or enabling automatic inventory reporting from your website, where supported.
A primary product feed must already be active, and your website must allow Google crawlers to access product and availability data.
For online-only products, inventory is handled directly within the primary product feed, which must be correctly configured and submitted through Product sources. Availability and pricing in this feed determine how products appear across Google surfaces.
What Does โInventoryโ Mean in Google Merchant Center?
In Merchant Center, inventory is not a single feature. It is handled through three distinct but related mechanisms:
- Primary product data
Availability and price are included directly in your main product feed. - Local inventory (supplemental)
Store-level stock and price overrides are used for in-store availability and pickup experiences. - Inventory updates via API
Programmatic updates for availability, quantity, and price at scale.
Google treats inventory accuracy as a policy requirement, not just a performance signal.
Ways to Add Inventory to Merchant Center
You have several methods depending on your setup and need:
a) Product Feed (Primary)
This is the standard way to upload inventory data along with all product attributes. You include availability, price, and stock-related attributes in your product feed file.
This gets consumed as part of your main product catalog.
b) Manual Entry (Product Editor)
For a few products or one-off updates:
- Go to Products โ All products
- Click Add products
- Choose โAdd new products one by oneโ
- Fill in availability and other required fields
- Save the product
Note: This is not practical for large catalogs.
c) Automated Online Store Sync
If you use Shopify, BigCommerce, or similar:
- Connect your platform in Merchant Center
- The system will automatically fetch product and inventory data
- Changes on your store reflect in Merchant Center within ~24โ48 hours
d) Local Inventory Feed (Supplemental)
This is required if you have brick-and-mortar store stock and want Google to show in-store availability or enable Local Inventory Ads.
Step-by-Step: Adding Local Inventory in Merchant Center
Local inventory feeds provide per-store stock and availability details (e.g., store A has 10 units, store B has 3 units).
Prerequisites
โ A Merchant Center account
โ Primary product feed already set up
โ Store locations configured in GMC
โ Optional: Google Business Profile linked (recommended for local programs)
Step 1: Log in and Navigate to Data Sources
- Sign in to Google Merchant Center.
- Click Settings โ Data Sources.
- Select Product sources โ Supplemental sources.
Step 2: Add Local Inventory
Click Add local inventory.
Choose how you want to send the local inventory feed:
- Enter a link to your file (HTTP/HTTPS/SFTP)
- Upload a file from your computer
- Schedule SFTP or Google Cloud Storage fetch
Step 3: Define Language and Feed Labels
After selecting the input method:
- Choose the **language**
- Assign a **feed label**ย ย
Note: The label must match the language and feed label used in your product feed if you want local inventory linked properly. :contentReference[oaicite:13]{index=13}
Step 4: Schedule Fetch and Finish
- If using a URL, set the **fetch schedule** (default ~24 hrs).ย ย
- Save the feed.ย ย
- Google will start parsing inventory data; global sync may take up to 24 hours initially. :contentReference[oaicite:14]{index=14}
Below are example CSV + XML schemas you can upload as a Local inventory data source in Merchant Center, and a Python script that automates store-level inventory updates via the Content API for Shopping v2.1.
All attribute names/values align to Google Merchant Center Help and the official API reference.
1) Local Inventory Feed โ CSV schema + examples (Merchant Center upload)
Required columns (minimum viable local inventory feed)
Google requires these fields for local inventory data:
- id
- store_code
- availability
Availability supported values include: in_stock, limited_availability, on_display_to_order, out_of_stock.
Recommended columns (common in production)
- price (store-specific override)
- sale_price
- sale_price_effective_date
- quantity (optional; if provided alongside availability, Google may classify based on the lower signal)
- Store pickup: pickup_method (optional since Sep 1, 2024), pickup_sla (required when using store pickup)
- Local delivery: local_shipping_label
CSV template (schema)
id,store_code,availability,quantity,price,sale_price,sale_price_effective_date,pickup_method,pickup_sla,local_shipping_label
CSV example (two stores, one SKU)
id,store_code,availability,quantity,price,sale_price,sale_price_effective_date,pickup_method,pickup_sla,local_shipping_label
SKU-10001,STORE-001,in_stock,12,149.00 USD,129.00 USD,2026-01-01T00:00Z/2026-01-07T23:59Z,buy,same day,Sameday
SKU-10001,STORE-002,limited_availability,2,149.00 USD,,,reserve,next day,
2) Local Inventory Feed โ XML schema + example (RSS 2.0)
Merchant Center supports XML feeds using an RSS 2.0 structure with the g: namespace.
XML example
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>Local Inventory Feed</title>
<link>https://example.com</link>
<description>Store-level inventory updates</description>
<item>
<g:id>SKU-10001</g:id>
<g:store_code>STORE-001</g:store_code>
<g:availability>in_stock</g:availability>
<g:quantity>12</g:quantity>
<g:price>149.00 USD</g:price>
<g:sale_price>129.00 USD</g:sale_price>
<g:sale_price_effective_date>2026-01-01T00:00Z/2026-01-07T23:59Z</g:sale_price_effective_date>
<g:pickup_method>buy</g:pickup_method>
<g:pickup_sla>same day</g:pickup_sla>
<g:local_shipping_label>Sameday</g:local_shipping_label>
</item>
<item>
<g:id>SKU-10001</g:id>
<g:store_code>STORE-002</g:store_code>
<g:availability>limited_availability</g:availability>
<g:quantity>2</g:quantity>
<g:price>149.00 USD</g:price>
<g:pickup_method>reserve</g:pickup_method>
<g:pickup_sla>next day</g:pickup_sla>
</item>
</channel>
</rss>
The required attributes for local inventory remain id, store_code, and availability.
3) Automating store inventory updates via the Content API (localinventory.custombatch)
What you can update via API
The local inventory service supports updates per store using:
- Required:
storeCode+productId(productId in URL / request entry) - Optional:
quantity,price,salePrice,salePriceEffectiveDate,availability,pickupMethod,pickupSla,instoreProductLocation.
Endpoint + auth scope (v2.1)
POST https://shoppingcontent.googleapis.com/content/v2.1/localinventory/batch- OAuth scope:
https://www.googleapis.com/auth/content
4) Python script (reads CSV โ pushes updates with localinventory.custombatch)
This script:
- Reads a CSV shaped like the template above
- Builds batch entries
- Sends
localinventory.custombatchupdates
You must already be enrolled in a local program and have local products set up; local inventory attaches to existing local products.
import csv
import json
import os
import requests
from google.oauth2 import service_account
from google.auth.transport.requests import Request
# ----------------------------
# Config
# ----------------------------
SERVICE_ACCOUNT_JSON = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "service-account.json")
MERCHANT_ID = os.environ.get("GMC_MERCHANT_ID") # e.g., "123456789"
CSV_PATH = os.environ.get("LOCAL_INVENTORY_CSV", "local_inventory.csv")
SCOPE = "https://www.googleapis.com/auth/content"
BATCH_ENDPOINT = "https://shoppingcontent.googleapis.com/content/v2.1/localinventory/batch"
def get_access_token() -> str:
"""
Uses a service account to obtain an access token.
The service account must be granted access to your Merchant Center account.
"""
creds = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_JSON,
scopes=[SCOPE],
)
creds.refresh(Request())
return creds.token
def parse_money(value: str):
"""
Converts '149.00 USD' -> {'value': '149.00', 'currency': 'USD'}
"""
if not value:
return None
parts = value.strip().split()
if len(parts) != 2:
raise ValueError(f"Invalid money format: {value!r} (expected 'NUMBER CURRENCY')")
amount, currency = parts
return {"value": amount, "currency": currency}
def build_batch_entries(csv_path: str, merchant_id: str):
entries = []
batch_id = 1
with open(csv_path, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
product_id = row["id"].strip()
store_code = row["store_code"].strip()
availability = (row.get("availability") or "").strip()
quantity_raw = (row.get("quantity") or "").strip()
price_raw = (row.get("price") or "").strip()
sale_price_raw = (row.get("sale_price") or "").strip()
sale_price_effective_date = (row.get("sale_price_effective_date") or "").strip()
pickup_method = (row.get("pickup_method") or "").strip()
pickup_sla = (row.get("pickup_sla") or "").strip()
# local_shipping_label is not a field on the API localInventory object in v2.1;
# itโs typically provided via feed uploads, not the localinventory API call.
local_inventory = {"storeCode": store_code}
# Optional fields
if availability:
local_inventory["availability"] = availability
if quantity_raw:
local_inventory["quantity"] = int(quantity_raw)
if price_raw:
local_inventory["price"] = parse_money(price_raw)
if sale_price_raw:
local_inventory["salePrice"] = parse_money(sale_price_raw)
if sale_price_effective_date:
local_inventory["salePriceEffectiveDate"] = sale_price_effective_date
if pickup_method:
local_inventory["pickupMethod"] = pickup_method
if pickup_sla:
local_inventory["pickupSla"] = pickup_sla
entries.append(
{
"batchId": batch_id,
"merchantId": str(merchant_id),
"method": "insert",
"productId": product_id,
"localInventory": local_inventory,
}
)
batch_id += 1
return entries
def push_custombatch(access_token: str, entries):
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
payload = {"entries": entries}
resp = requests.post(BATCH_ENDPOINT, headers=headers, data=json.dumps(payload), timeout=60)
resp.raise_for_status()
return resp.json()
def main():
if not MERCHANT_ID:
raise RuntimeError("Set GMC_MERCHANT_ID env var to your Merchant Center merchantId.")
token = get_access_token()
entries = build_batch_entries(CSV_PATH, MERCHANT_ID)
# Tip: Google APIs often have practical batch-size limits; chunk if your file is large.
result = push_custombatch(token, entries)
# Print batch errors (if any)
for entry in result.get("entries", []):
if "errors" in entry:
print("ERROR:", json.dumps(entry["errors"], indent=2))
else:
print("OK batchId:", entry.get("batchId"))
print("Done.")
if __name__ == "__main__":
main()
Why โmethodโ: “insert” for updates?
localinventory.custombatch entries accept method: "insert" and the API updates local inventory for the product/store in that entry.
Final Thoughts
Inventory management in Google Merchant Center should be aligned with your retail model. Online-only merchants should manage inventory directly through their primary product feeds, while omnichannel retailers must implement local inventory feeds to accurately represent in-store availability.
Enterprises with large catalogs or high-frequency inventory changes should rely on the Content API to enable scalable, near-real-time updates.
A correctly implemented inventory setup is critical, as it directly affects product eligibility, ad delivery, local discovery across Google surfaces, and the overall trust and health of your Merchant Center account.
