Google Shopping Readiness — Automated Product Feeds

Self-hosted product feeds for Merchant Center: keeping thousands of SKUs fresh daily

Google Merchant CenterProduct FeedShopping AdsXMLAutomated Generation
6 min read

Introduction

When you search for a product on Google, you see that "Shopping" panel with photos and prices. To get your own products in there, you have to hand your product data to Google Merchant Center (GMC). That bundle of product data is the product feed.

Most stores hand feed generation off to a dedicated app. But for the apparel-and-gear EC site I worked on, we deliberately skipped the app and generated our own XML feed from the headless EC side instead.

This article explains why we chose self-hosting, and the overall picture of the automation that keeps thousands of SKUs fresh every day.

Why generate the feed ourselves

We wanted to move past the app's limits

Feed generation apps are convenient. But the flip side of that convenience is that you can't step outside the box the app gives you. Requests like "change how the title is built for just these products" or "exclude anything with a certain tag" often can't be done from the app's settings screen.

With self-hosting, we write the conversion logic from product data to feed ourselves. Being able to map things freely to fit the business was the biggest motivation.

Supporting multi-site operations

In this project, we ran several EC sites off the same product foundation. Each site handles slightly different products, languages, and currencies.

With an app, contracts and settings pile up per site. Self-hosting lets us emit per-site feeds from one codebase — just specify the site on the endpoint and its feed is generated. That single point of management made operations far easier.

It works for both ads and free listings

People assume the product feed only exists for Shopping "ads," but the same feed also powers Google's free listings — the slots where products appear in search results without spending a cent.

In other words, a well-maintained feed multiplies your exposure without ad spend. Once you see the feed as the foundation of acquisition rather than an accessory to advertising, the value of building it properly yourself becomes clear.

The overall self-hosted system

A single endpoint returns the feed

The mechanism is simple: hit one endpoint, /api/merchant/feed.xml, and it returns XML that GMC can read. You just register this URL in GMC. From there, GMC periodically fetches the URL and pulls in the latest product data.

Automated product feed generation
Shopify (product master)

Fetch products, inventory, and prices via the Admin GraphQL API

Fetch product data
Feed generation API

/api/merchant/feed.xml converts to the GMC spec

Cache layer

Holds the generated result with a few-hour TTL

Serve the XML feed
Google Merchant Center

Periodically fetches the URL → reflects into Shopping ads and free listings

Pulling product data from Shopify

The source of truth for inventory and price is Shopify. The feed generation API calls Shopify's Admin GraphQL API to fetch the title, description, price, availability, images, GTIN (the product's international identifier), and more.

We use GraphQL because it lets us grab exactly the fields we need in one shot. Information that would take many REST requests comes back in a single query. When you're dealing with a large SKU count, that efficiency gap really adds up.

Converting to GMC-spec XML

The fetched product data can't be handed to GMC as-is. GMC has fixed field names (title, description, link, image_link, price, availability, and so on) and formatting rules.

So we convert each Shopify product, one at a time, into an XML block that follows this spec. Designing these conversion rules is the crux that determines feed quality. We dig into it in the mapping design article.

Three perspectives that matter in operation

Caching to handle large SKU counts lightly

If we fetched thousands of SKUs via GraphQL and rebuilt the XML every time GMC came to fetch the URL, a heavy process would run on every request.

So we cache the generated result with a TTL of a few hours. Feed contents don't change by the minute, so that's plenty. By controlling page size and serving in chunks, we can return large SKU counts without straining memory. We cover this design in caching and health checks.

If it stops, the ads stop — so we monitor

It's easy to overlook, but if the feed stops, the ads stop. If the feed fails to generate or comes back empty, GMC can no longer list the products, and ad delivery cuts out right along with it.

And it happens quietly. There's no error screen — sales just drift down. That's exactly why a health-check API that watches whether the feed is generating properly is indispensable.

Quality control to reduce disapprovals

GMC reviews the products you hand it. If required fields are missing or a product violates policy, that product is "disapproved" and won't be listed.

Reliably excluding draft and unpublished products and validating for missing required attributes — we cover these quality-control details in managing feed quality.

Conclusion

By generating the Google Shopping product feed ourselves instead of relying on an app, we can freely design mapping, exclusion control, and multi-site support.

  • The value of self-hosting: flexible mapping beyond the app's limits, plus central management of multiple sites
  • The mechanism: fetch products via Shopify Admin GraphQL, convert to GMC-spec XML, and serve from a single endpoint
  • The operational crux: lighten the load with caching, monitor with health checks, and cut disapprovals with quality control

The feed isn't an accessory to advertising — it's the foundation of acquisition that also powers free listings. If it stops, the ads stop too, which is exactly why it's worth building carefully and monitoring diligently.

Each theme is explored in the sub-articles below.