Product Feeds
How to Handle Sale Prices in Your Google Product Feed
A sale changes your price in at least three places: the feed, the product page and the structured data. Here is how to keep them in step so discounts show correctly instead of triggering mismatches.
Sales are one of the most common sources of price mismatches in Merchant Center. The site switches to the discounted price on Friday morning, the feed updates on Friday night, and in between Google sees two different prices.
This guide explains how Google’s sale_price attribute works, how to schedule sales with sale_price_effective_date, how strikethrough prices on your page should line up with the feed, what to do about coupons and member prices, and how to mark up sale prices in structured data.
Short answer: Keep submitting the regular price in [price] and add the discounted price in [sale_price], with sale_price_effective_date (including the correct timezone) to set when the sale runs. Your page must show both prices, checkout must charge the sale price, and the strikethrough price should equal [price]. Use loyalty_program for member prices and promotions for discount codes.
Key Takeaways
- Submit the full price in price and the discount in sale_price; sale_price must be lower than price.
- Without sale_price_effective_date, the sale price applies immediately; include the correct timezone.
- The landing page must show both prices, and checkout only the sale price.
- Discounts that need a promo code are promotions, not sale_price; member prices use loyalty_program.
- In structured data, mark the original price as a strikethrough price and use validFrom and validThrough for sale dates.
How sale_price works
sale_price is an optional attribute described in Google’s sale price documentation. You submit it as a number plus an ISO 4217 currency code, for example 15.00 USD, alongside your regular price. While the sale is active, Google shows the sale price as the current price and may show the original price with a sale annotation. Google doesn’t guarantee the annotation.
The key idea: price stays the regular, non-sale price throughout the sale. You don’t overwrite it with the discount. Google needs both values to understand there is a sale.
| Attribute | What to submit during a sale |
|---|---|
| price | The regular price, e.g. 20.00 USD |
| sale_price | The discounted price, e.g. 15.00 USD |
| sale_price_effective_date | The start and end of the sale, with timezone |
Google’s sale price requirements
- The sale price must be lower than the regular price.
- Use no more than two decimal places; Google rounds anything beyond that.
- The sale price must match your landing page and checkout.
- Show both the non-sale and the sale price on the landing page, and only the sale price at checkout. The sale price doesn’t have to be the most prominent price on the page.
- Keep submitting the full price in
price. - If a product is on sale but you don’t submit
sale_price, submit the sale price aspriceinstead. - Don’t use
sale_pricefor prices only loyalty members get; useloyalty_program. - Don’t use it for subscriptions to physical goods; use
subscription_cost.
The fallback rule matters for platforms that can’t send sale_price: if the feed sends only one price, it must be the price shoppers actually pay right now.
Correct base prices also matter. Google says accurate regular prices are what enable sale annotations, and its free listings documentation notes that price drops compared with a running historical average may be shown. Practitioner view: keep the regular price honest, because an inflated base price undermines both.
Scheduling sales with sale_price_effective_date
If your platform can’t send sale_price at all, an supplemental data source or attribute rules can add it, as long as the result still matches the page. sale_price_effective_date sets the window when the sale price applies. Google recommends using it; if you leave it out, the sale price applies immediately.
The date range includes a time and timezone. Google’s automatic item updates documentation specifically calls out setting the effective date with the correct timezone, because a sale that starts at midnight Eastern but is submitted with the wrong offset will switch at the wrong hour. For the exact format, follow the attribute’s entry in the product data specification.
Why scheduling prevents mismatches
If you load the sale into the feed in advance with an effective date that matches the moment your site switches, both change at the same time. Without it, you depend on the feed update and the site change landing together, which rarely happens to the minute.
- Decide the exact start and end time, and the timezone your store uses for the switch.
- Schedule the site change for that time (most platforms support scheduled discounts or sale dates).
- Submit sale_price and sale_price_effective_date in the feed before the sale starts.
- After the start time, check a sample of products in Merchant Center and on the site.
- After the end time, check again that the site reverted and the feed’s sale window has closed.
Practitioner tip: avoid editing sale end dates by hand mid-sale on the site without updating the feed. Extensions are a common source of a day or two of mismatches.
Strikethrough prices on your site
When a product is on sale, most themes show the original price crossed out next to the sale price. Google’s automatic item updates guidance says the strikethrough price on your site should match the price you submit when sale_price is provided.
Common ways this goes wrong:
- The site shows a “compare at” or “was” price that differs from the regular price in the feed.
- A page shows more than one strikethrough price (for example, a list price and a previous price).
- The strikethrough is added with JavaScript after the page loads, so it isn’t in the HTML Google crawls.
Automatic item updates and strikethroughs
Merchant Center’s automatic item updates use landing page data to update price, sale_price and availability, and price automation can also update strikethrough prices. Google advises not enabling price automation if your pages show multiple strikethrough prices, because it can’t tell which one is the regular price. Automatic updates are designed for sporadic problems on a small share of products, not as a replacement for regular feed updates. If prices change more than once a day, Google recommends the Merchant API.
Coupons, promo codes and loyalty prices
Not every discount belongs in sale_price. Google separates three kinds:
| Discount type | How to submit it | Why |
|---|---|---|
| Sale price everyone sees on the page | sale_price (+ effective date) | It’s the price any shopper pays |
| Discount applied with a promo code | Promotions, not sale_price | Google treats promo-code discounts as promotions |
| Price only for loyalty members | loyalty_program, not sale_price | Google says not to use sale_price for member prices |
| Subscription pricing for physical goods | subscription_cost | sale_price isn’t for subscriptions |
Google’s sale price rules also say that if coupon codes are involved, they must be accessible to all users and both prices must be shown. In practice, a discount that only some shoppers can reach (newsletter subscribers, members, people with a code) shouldn’t be presented to Google as the product’s sale price.
For structured data, Search Central lets you mark a member price with validForMemberTier. A price specification that contains both priceType and validForMemberTier is ignored, so keep member prices and strikethrough prices in separate specifications.
Sale prices in structured data
Google’s merchant listing structured data documentation describes how to mark up active, strikethrough and member prices on product pages:
| What you want to express | How to mark it up |
|---|---|
| Active (sale) price | offers.price, or priceSpecification.price, with priceCurrency |
| Original (strikethrough) price | A price specification with priceType StrikethroughPrice (ListPrice is also allowed during a transition period) |
| Member price | A price specification with validForMemberTier |
| Sale duration | validFrom and validThrough or priceValidUntil, in ISO 8601 with timezone |
- If both
offers.priceand a priceSpecification give an active price,offers.pricewins. - The price must be greater than zero, with an ISO 4217 currency code.
- If
priceValidUntilis in the past, the listing may not display. Remove or update stale dates after a sale ends. - Put Product structured data in the initial HTML; JavaScript-injected markup can make Shopping crawls less frequent and less reliable for fast-changing prices.
The markup should carry the same sale price as the feed and the visible page. See aligning website data and product feeds for a full consistency check.
Avoiding sale price mismatches
Googlebot crawls your landing pages and compares the price in your data with the price on the page or in structured data, according to the mismatched price guide. A mismatch can disapprove the product, and repeated mismatches can lead to account suspension. During a sale, Google’s sale price rules also require the sale price to match the landing page and checkout.
Common causes during sales
- The site and feed switch at different times (no effective date, or the wrong timezone).
- The sale price is applied only in the cart, so the product page still shows the full price.
- The sale price is injected with JavaScript after load, so the server HTML shows the old price.
- Rounding differences, such as a 15% discount calculated to three decimals on one side.
- Prices shown in a different currency from the one submitted, for example through a currency switcher.
Fixing them
Fix the source of the mismatch first, then correct the data: one product at a time through Products > Needs attention > Edit product, or many by correcting the source file and re-uploading. Google re-crawls disapproved products over the next few hours or days and reapproves them if the prices match. You can also request a review. For the full process, see how to fix price mismatches, and use Merchant Center diagnostics to track which products are affected.
Platform notes
On Shopify, a “compare at” price is what usually becomes the strikethrough; check that it equals the regular price your feed sends, or the Google & YouTube app sync and your page may disagree. On WooCommerce, scheduled sale dates are set per product or variation; confirm your feed plugin or Google for WooCommerce sends the sale price and its dates, and check what timezone your WordPress site uses. In both cases, test one product before a large sale goes live.
When to get help
If sale events regularly trigger price mismatches, or your pricing mixes sale prices, member prices and coupons, it’s worth mapping each one properly once. Our product feed optimization service can set up sale price handling across feed and site, and our disapprovals service helps when products are already disapproved.
Frequently asked questions
Should I change the price attribute during a sale?
No. Keep the regular price in price and submit the discount in sale_price. Only if you can’t send sale_price should price carry the current sale price.
What happens if I don’t set sale_price_effective_date?
The sale price applies immediately. Use the effective date to control when the sale starts and ends.
Can I use sale_price for member-only prices?
No. Google says to use the loyalty_program attribute for prices only loyalty members receive.
Is a discount code a sale price?
No. Google treats discounts that require a promo code as promotions, not sale_price.
Will Google always show my original price crossed out?
Not necessarily. Google may show the original price with a sale annotation, but doesn’t guarantee it.
How should I mark up a strikethrough price?
Use a price specification with priceType StrikethroughPrice for the original price, and the active price in offers.price.
Sales causing price mismatches?
We set up sale prices, dates and strikethrough handling so your feed, pages and markup change together.
Sources
- Google Merchant Center Help — Sale price [sale_price]
- Google Merchant Center Help — Product data specification
- Google Merchant Center Help — Automatic item updates
- Google Merchant Center Help — How to fix: Mismatched product price
- Google Merchant Center Help — Free listings for products
- Google Search Central — Merchant listing structured data
- Google Merchant Center Help — Install and link the Google & YouTube app on Shopify
- WooCommerce Docs — Google for WooCommerce: Get started
Last reviewed October 10, 2026 against the official documentation listed above. Google changes Merchant Center features and policies regularly — always confirm details in your own account.
