Skip to main content

Google Merchant Center App

Saleor version required: 3.23

The Google Merchant Center App generates a product feed for each of your sales channels and serves it at a stable URL that you register in Google Merchant Center as a scheduled fetch.

The app builds feeds in the background, on a schedule. Opening a feed URL never triggers generation — it always returns the last feed that finished successfully. That is what lets the app support large catalogs.

info

This app replaces the Product Feed App. If you use Product Feed today, see Migrating from Product Feed.

Features​

  • One feed per sales channel, with per-channel storefront URLs, language, and status.
  • Scheduled regeneration — feeds refresh on their own, with a "Regenerate all channels" button when you need them sooner.
  • Large catalog support — a run is split into chunks and streamed to storage, so it can cover catalogs of any size.
  • Translated feeds — pick a language per channel and the app writes titles and descriptions from Saleor translations.
  • Safety guard — a run that produces no rows, or far fewer than the last one, does not replace the feed that Google is currently fetching.
  • Category mapping — map Saleor categories to the Google product taxonomy.
  • Attribute mapping — fill the brand, gtin, color, material, pattern, and size columns from Saleor attributes.
  • Per-channel reporting — how many products were published, how many were left out, and which field each was missing.

How it Works​

  1. When you install the app, it schedules a first run right away.
  2. A run walks your whole catalog once and fans out to every configured channel, writing one products.tsv file per channel.
  3. Long runs are cut into chunks. Each chunk continues where the previous one stopped, so a run can take as long as the catalog needs.
  4. When the walk finishes, each channel's file is checked by the publish guard and then published — or discarded, leaving the previous feed in place.
  5. Google fetches the feed URL on its own schedule and receives the last published file.

Feeds refresh roughly every 12 hours. A failed run is retried sooner, after about 30 minutes. Both are service-side settings, not options in the app UI.

The app uses no webhooks. A product you edit in Saleor reaches the feed on the next run, not immediately. Use Regenerate all channels when you want a change picked up now.

Feed URL​

Every configured channel gets its own URL:

https://<app-host>/api/feed/<installation-hash>/<channel-slug>/products.tsv

Copy it from the channel row on the configuration page. Notes:

  • The URL returns 404 until the channel's first feed has been published. Wait for the first run to finish before registering it in Merchant Center.
  • The URL is stable for the lifetime of the installation. Reinstalling the app changes it, so you have to update the data source in Merchant Center.
  • The URL redirects to short-lived, signed storage links. Feed files are never public.

Publish Guard​

Before a channel's new file replaces the live one, the app compares it to the previous run:

SituationWhat happens
The run produced zero rowsNot published. The previous feed keeps serving. This check cannot be disabled.
The run read less than half of the last run's productsNot published. The channel shows Incomplete data with an explanation.
Products were dropped for missing required fieldsPublished anyway. The channel reports how many rows were left out and why.

A partial API response looks exactly like a shrinking catalog and is far more common, so the app treats a sudden drop as suspect. When a reduction is real, enable Allow smaller feeds on that channel, let one run publish, then turn it off again.

Channel States​

StateMeaning
Not configuredThe channel has no storefront URLs, so no feed is generated for it.
Not generated yetConfigured, but no feed has been published. The feed URL returns 404.
QueuedA run is due and waiting to start.
GeneratingA run is walking the catalog.
PublishedThe channel has a feed. The row shows when it was generated and how many products it contains.
Incomplete dataThe publish guard held the run back. The previous feed keeps serving.
FailedThe run could not finish. It is retried automatically.

Permissions​

The app requests MANAGE_PRODUCTS. It uses it to read the catalog for the feed and to write the Google category mapping onto Saleor categories.

To open and change the app's configuration, a staff user needs both MANAGE_APPS and MANAGE_PRODUCTS.

Configuration​

Open the app from Extensions → Installed → Google Merchant Center. A setup checklist on the configuration page walks you through the same steps.

Channel Configuration​

Expand a channel row to configure its feed. A channel is included in a run only when both URLs are filled — Merchant Center rejects a data source whose link column is blank, so a half-configured channel is skipped entirely.

FieldRequiredDescription
Storefront URLYesThe storefront this channel sells through, for example https://shop.example.com.
Product URL templateYesThe template used for the link column. {productSlug} is the only placeholder, and it is substituted literally — this field is not a Handlebars template. Example: https://shop.example.com/products/{productSlug}.
Feed languageNoThe language the feed is written in. See Languages and translations.
Allow smaller feedsNoLets this channel publish a run the publish guard would otherwise hold back.

Channels you create in Saleor later appear in the app automatically.

Title and Image​

These settings apply store-wide, to every channel's feed.

  • Product title template — a Handlebars template for the title column. The default is {{ product.name }} - {{ variant.name }}.
  • Image size — the pixel width requested from Saleor for feed images. Merchant Center wants at least 250px; the default is 1024.

Title Template Variables​

VariableValue
{{ product.name }}Product name, translated when the channel has a feed language.
{{ product.slug }}Product slug.
{{ product.seoDescription }}Product SEO description, untranslated.
{{ product.categoryName }}Name of the Saleor category the product belongs to.
{{ variant.name }}Variant name, translated when the channel has a feed language.
{{ variant.sku }}Variant SKU.
{{ variant.weight.value }}, {{ variant.weight.unit }}Variant weight, when it is set.

Standard Handlebars block helpers such as {{#if}} work. No extra helper library is registered, so helpers like {{uppercase}} are not available.

Avoid {{ product.description }} — it holds the raw rich-text JSON, not readable text.

Attribute Mapping​

Six Google columns have no Saleor equivalent and can be filled from an attribute:

Google columnLabel in the app
brandBrand
gtinGTIN
colorColor
materialMaterial
patternPattern
sizeSize

Rules:

  • Only product-type attributes are offered, and only those whose values become a plain string: dropdown, multiselect, plain text, swatch, and numeric. File, reference, rich-text, boolean, and date attributes are not offered, because they would put a URL, an object ID, or a JSON blob into the feed.
  • A variant attribute value wins over a product attribute value for the same attribute.
  • An unmapped column is left out of the file entirely rather than shipped empty — Merchant Center reports a declared-but-always-blank column as a problem.
  • Only these six columns can be mapped. A mapping naming a computed column such as price or link is rejected and never overwrites the computed value.
  • Attributes you have not mapped never reach the feed, even when products carry them.

Category Mapping​

Open Category mapping from the page header to map Saleor categories to the Google product taxonomy. The value is written to the Saleor category's public metadata under google_category_id, so it applies to every channel's feed at once, and each row saves on its own.

Mapping is optional, but Merchant Center rejects some product types without it.

Languages and Translations​

Set Feed language on a channel when that channel's catalog is translated. Merchant Center matches a data source to a country and a language, and Google expects your landing pages to be in the feed's language — that is why language sits next to the storefront URL rather than being a store-wide setting.

With a language set:

  • Titles and descriptions come from Saleor translations into that language.
  • Mapped attribute columns are translated too. color, material, pattern, and size are words a shopper reads, and Google matches them against search terms in the language of the landing page.
  • A missing translation falls back per field, not per product: a product with a translated name and an untranslated description publishes with both, rather than being dropped. Attribute values fall back per value, so a half-translated colour palette keeps the translations it has.
  • The channel row reports how many rows were published in their original language. Google may disapprove products when most of a feed does not match its declared language.

Leave the field empty for a single-language store. No translations are then requested at all.

What Ends Up in the Feed​

The file is a TSV export following the Google Merchant Center product data specification. One row is generated per product variant; variants of one product share an item_group_id.

Columns​

ColumnSource
idVariant ID.
item_group_idProduct ID.
titleRendered from the title template, using translations when the channel has a language.
descriptionProduct SEO description, falling back to the rich-text description rendered as plain text.
linkProduct URL template with {productSlug} substituted.
image_linkFirst variant image, falling back to the product's images and then its thumbnail.
additional_image_linkThe remaining images.
availabilityout_of_stock when the channel reports zero available quantity, otherwise in_stock.
priceGross price in the channel's currency. The undiscounted price when the variant is on sale.
sale_priceGross price, only when it is lower than the undiscounted price.
brand, gtinFrom attribute mapping. Omitted from the file when unmapped.
mpnVariant SKU.
conditionAlways new.
google_product_categoryFrom category mapping.
product_typeSaleor category name.
shipping_weightVariant weight, when the product type requires shipping and the weight is above zero.
identifier_existsno when the row has neither a GTIN nor an MPN paired with a brand.
color, material, pattern, sizeFrom attribute mapping, translated when the channel has a feed language. Omitted from the file when unmapped.

Which Products Are Included​

  • A product reaches a channel's feed only when it is published, past its publication date, visible in listings, and available for purchase in that channel. Publication is a per-channel setting, so a product live in one channel and unpublished in another appears in the first channel's feed only.
  • A variant appears only when it has a price in that channel. A variant that is not sold in the channel is left out silently. Saleor has no variant-level publication flag; a priced channel listing is the only variant-level gate.
  • Neither exclusion is reported as a problem — an unpublished or unsold product is not a data error.
  • A row is dropped when it is missing any field Google requires: id, title, description, link, image_link, availability, or price. Merchant Center reports an invalid row against the whole data source, so the app keeps such rows out rather than risk the feed's standing.
  • Because description and image_link come from the product, a product-level gap drops all of that product's variants.
  • Dropped rows do not fail the run. The good rows publish, and the channel row shows a count per missing field, such as missing image_link (24), description (21), so you know which field to fix in the catalog.

Assumptions and Limitations​

  • Feeds are not real time. There are no webhooks and no incremental updates. Catalog changes reach Google on the next scheduled run, or after you press Regenerate all channels.
  • Regeneration is all-or-nothing. A run is one catalog walk that fans out to every configured channel, so there is no cheaper per-channel rebuild to offer. The button is disabled while a run is in flight.
  • Configuration changes apply to the next run. A run in flight keeps the language, URLs, title template, and attribute mapping it started with, because the earlier part of the file is already written. The exception is Allow smaller feeds, which is read when the run decides whether to publish.
  • Only six columns are mappable. brand, gtin, color, material, pattern, and size come from attributes; every other column is computed from catalog data and cannot be overridden.
  • TSV only. The app does not produce the XML feed format.
  • One feed per channel, always the full catalog for that channel. There is no filtering by category, collection, or product type.
  • No infrastructure to provide. Unlike the Product Feed App, this app hosts the generated files for you, so there is no S3 bucket or IAM credentials to configure.

Troubleshooting​

The feed URL returns 404. The channel has not published a feed yet. Check its state on the configuration page — until it reaches Published, there is nothing to serve.

A channel shows "Incomplete data". The publish guard held the run back and the previous feed is still serving. The message on the row explains why. If the reduction is intentional, enable Allow smaller feeds for that channel.

Products are missing from the feed. Either they have no price in that channel, or they are missing a field Google requires. The channel row lists the missing fields with a count for each.

Merchant Center reports products in the wrong language. Those products have no translation into the channel's feed language and were published in their original language. The channel row shows how many.

A channel shows "Failed". The run could not finish — usually a temporary Saleor or storage error. It is retried automatically, and the previous feed keeps serving in the meantime.

Migrating from Product Feed​

The Product Feed App is deprecated in favour of this app, and Saleor 3.23 is the last version it supports — if you are on Saleor 3.24 or newer, this app is the only option. When you move over:

  • Category mapping carries over. Both apps store it in the same google_category_id metadata key on the Saleor category, so mapped categories keep working.
  • Feed URLs change. Register the new per-channel URLs in Merchant Center as scheduled fetches and remove the old data sources once the new feeds publish.
  • The feed format changes from XML to TSV. Merchant Center accepts both; you just create the data source anew.
  • You no longer provide an S3 bucket. Drop the IAM user you created for the Product Feed App once you stop using it.
  • Attribute mappings have to be set up again, but every column the Product Feed App could map — brand, gtin, color, material, pattern, and size — is mappable here too.