Merchant promotions in Merchant Center
How Merchant Center promotions work, promotion feeds and annotations, promotion_id linking, eligibility rules, and a clean setup that survives review.
Merchant promotions put a clickable offer badge, '20% off', 'Free shipping', on your free and paid Shopping listings. You submit the promotion once, then link it to products with a shared promotion_id. The mechanics are simple; the failures are almost always eligibility and matching problems, where the promotion is live but attached to nothing, or the on-site price doesn't back up the claim.
What a promotion actually is
A Merchant Center promotion adds a special-offer annotation ("Save 15%", "Free gift", "Free shipping") to your product listings across free and paid Shopping surfaces. Shoppers see a "special offer" link on the listing that expands to the offer detail and points at your site.
Two things have to exist and be connected:
- The promotion itself: the offer definition: what the discount is, which promotion type, and the start and end dates. Submitted through the Promotions section, the Content API, or a promotions feed.
- The link to products: a shared
promotion_idon both the promotion and every product it applies to. This is the join that decides which listings get the badge.
Miss the second and you get the classic dead promotion: approved, live, attached to nothing.
The promotion_id link
promotion_id is the exact-match string that ties products to a promotion:
- The promotion carries a
promotion_id. - Every product that should show the badge carries the same
promotion_idin its product data (a product can list several, separated per the spec). - A product with no matching
promotion_idnever shows the promotion, even if it's obviously in scope.
Because the match is exact, promotion_id is where most setups break: a typo, a case difference, or products that were never tagged at all. You can add promotion_id to a targeted set of products cleanly with a supplemental feed keyed on id, which avoids re-exporting your whole catalog just to tag a weekend sale.
Eligibility, in plain terms
Promotions have their own eligibility bar on top of your products being approved:
- Country and platform must be supported for promotions in your target market.
- The offer must be redeemable exactly as stated: the discount has to apply on-site, at checkout, within the dates you set.
- Promotion type must match the offer: percentage off, amount off, free shipping, free gift, buy-one-get-one; the type and the value have to agree.
- Timing: a promotion won't render before
promotion_effective_datesopen, and stops at their close. - No prohibited categories: the same policy categories that block products block their promotions.
Deep dive A promotion setup that survives review
Most promotion disapprovals aren't the promotion: they're the mismatch between the promotion, the product data, and the live site. A setup that holds up:
- Tag before you launch. Add
promotion_idto the target products and let a feed fetch land before the promotion's start date. If the promotion goes live while products are still untagged, you burn the first hours of the sale showing nothing. - Back the claim on-site. If the promotion says "20% off", the crawler must be able to see 20% actually come off at checkout: via an automatic cart discount or a genuinely reduced price. A promotion the landing page doesn't honour is a misrepresentation flag, and misrepresentation is one of the harder disapprovals to clear. See fixing disapprovals.
- Keep
sale_priceand the promotion coherent.sale_pricesets the advertised price; the promotion is an additional badge and offer. Stacking asale_priceand a percentage-off promotion that together overstate the discount reads as inconsistent: decide which mechanism carries the offer and keep the other consistent with it. - Set honest dates.
promotion_effective_datesshould mirror the real on-site window. A promotion that outlives the on-site discount is the same misrepresentation problem in slow motion. - Scope with
product_applicability. Use it (all products vs specific products) deliberately: an "all products" promotion whose terms only some products meet invites eligibility conflicts. - Match the currency and country of the promotion to the products' target market. A promotion in the wrong currency for the offer's country won't attach.
The recurring root cause across all of these is the join and the site agreeing with the feed: the same discipline that keeps ordinary listings approved. Tag the right products, honour the offer where the crawler can see it, and set dates you'll actually keep.
Common failure modes
| Symptom | Usual cause | Fix |
|---|---|---|
| Promotion approved, shows on nothing | promotion_id on no products, or mismatched |
Tag products with the exact promotion ID |
| Promotion disapproved for misrepresentation | Offer not honoured at checkout | Make the discount genuinely apply on-site |
| Promotion never appears | Outside promotion_effective_dates, or unsupported country |
Check dates and market eligibility |
| Only some products show it | Partial tagging | Add the ID to the full target set |
For the underlying attributes and where promotion fields sit in the spec, see the product data spec overview.
Frequently asked questions
Why is my promotion approved but not showing on any products?
Almost always a promotion_id mismatch. The promotion is eligible, but no product carries a matching promotion_id, so there's nothing for it to attach to. Check that the IDs in your product data exactly match the promotion's ID.
Do I need to lower the price in my feed as well as run a promotion?
The two are different things. A promotion is a badge and a landing-page offer; sale_price is the actual advertised price. If your promotion says a percentage off, the discount must be genuinely applied at checkout, a promotion that isn't honoured on-site gets disapproved for misrepresentation.
How long does a promotion take to go live?
Promotions go through their own review, typically up to a few hours but occasionally longer for new accounts. It won't appear before its start date regardless of when it's approved.