How to schedule a sale price on Shopify (and restore it on time)
Scheduling sale prices on Shopify: price vs compare-at, the scheduling options, and a restoration calendar that doesn't depend on anyone remembering.
InventoryX is in development and not available today. ClearStock is the live Shopify app.
A scheduled sale price is two problems wearing one coat. The first is getting the lower price live at a specific moment; the second, much harder one is getting the original price back when the window closes. Shopify handles scheduling through automation and apps; restoration happens only if someone remembers. Every stale sale price still on a storefront in March is evidence that the second problem was treated as an afterthought.
Here's how the two price fields differ, the realistic scheduling options, and a restoration routine that survives a busy week. Field mechanics get their own treatment in sale price vs compare-at price; this article is about timing and getting out again.
Price and compare-at do different jobs
The price field is what the customer is charged. It is the number that reaches checkout, tax calculation, and your revenue reports.
The compare-at price is a display anchor. Put a higher number in it and the storefront shows it struck through beside your price. It does not affect what anyone pays, and it does not create a discount — it is presentation, and in several jurisdictions it is regulated presentation, since a struck-through reference price is often required to have been a genuine recent selling price.
For a scheduled sale, that split gives you two different techniques:
- Discount the price (price down, compare-at at the original). The customer pays less, the strikethrough shows the old price, and restoration means putting the original number back in the price field.
- Leave price alone, add a discount. The price never changes, the discount applies at checkout, and restoration is automatic because nothing was edited. The trade-off: the storefront may show full price in the collection grid, which reduces conversion.
Most merchants choose the first. It converts better and carries the restoration risk below.
How to actually schedule the change
At the time of writing, Shopify's admin has no native "change this price on this date" scheduler for product prices. What exists:
- Scheduled product publishing. A product's publish date controls when it appears. Visibility, not price.
- Shopify Flow. Flow can run on a schedule and take product actions where the action exists for your plan and Flow version. What Flow can write to product pricing has changed over time, so confirm the available action in your own admin rather than trusting a blog post.
- Apps. A price-scheduling app writes the new price on one schedule and writes it back on another. Reliability here is only as good as its ability to write the right original price back.
- The Admin API. A scheduled script is the most controllable option and the most fragile in a different way: it keeps running after the person who wrote it leaves.
Whichever route you take, the schedule isn't the hard part. The hard part is that the restoration value has to come from somewhere trustworthy.
Why manual restoration fails at scale
A 400-SKU sale is a data problem, and it fails in four predictable ways:
The original price only exists in the compare-at field. You set price to the sale value and compare-at to the original, so restoration becomes "move compare-at into price." But compare-at previously held something else — an MSRP, or nothing — and overwriting it destroys that. Six months later the field holds a number that no longer means anything.
Partial restorations. Someone restores the products that got complaints and misses three collections nobody looked at. The catalog now has two pricing regimes, and the next sale's baseline is contaminated.
The sale price becomes the price. This is the quiet one. After eight weeks, the sale price stops reading as a deal and starts reading as the price. Restoring it produces a price increase that customers notice — reviews, support tickets, and in some markets a compliance question about the reference price you were showing.
No record of what changed. If nobody exported prices before the sale started, there is no baseline. The compare-at trick only works if compare-at was managed for exactly this purpose.
The restoration calendar
One table per sale, filled in before the sale goes live, answers what happens and when.
| Field | What it holds | When it's set |
|---|---|---|
| Sale name and ID | "Spring Clearance 2026-11" | Before launch |
| SKU list | Exact variants included, exported | Before launch |
| Pre-sale price (per SKU) | The real price before the sale — exported, not retyped | Before launch |
| Pre-sale compare-at (per SKU) | Whatever was there before, including blanks | Before launch |
| Sale price | The discounted price | Before launch |
| Discount mechanism | Price edit, automatic discount, or code | Before launch |
| Start (date + time, store timezone) | e.g. 2026-11-12 09:00 | Before launch |
| End (date + time, store timezone) | e.g. 2026-11-26 23:59 | Before launch |
| Restore-by date | End date, or the day after | Before launch |
| Owner | One named person | Before launch |
| Verification | Guest test order placed after restore | After end |
| Post-sale action | Restore, re-price, or retire the SKU | After end |
Two entries do the heavy lifting. Pre-sale compare-at prevents the overwrite problem: you know what was there, so you can put it back. Post-sale action forces the decision most sales defer — some SKUs shouldn't return to their old price after a clearance, and writing that down per SKU is the difference between a restoration and a slow-motion discount.
The restoration routine that holds up
- Export prices the day before launch. Products → Export, include price and compare-at columns. File it with the sale name and date. This is the rollback file, and it takes two minutes.
- Never overwrite compare-at without recording it. If compare-at held your MSRP and you're about to use it for the sale anchor, capture the MSRP in the calendar table or a metafield first.
- Set an end date and time, not just a date. Then set a calendar reminder for the following morning with the export attached.
- Restore in one pass, not per product. Bulk editor or CSV import for the whole SKU list at once. A partial restore is worse than a late one because it hides.
- Verify with a guest order. After restoration, place a real checkout as a guest in a private window on the main market, and confirm the displayed price, the compare-at display, and the cart total agree.
- Log the outcome. Realized units, realized margin, and whether velocity changed. That number decides whether the next sale runs at the same depth — most sale operations skip it, which is why the same depth gets repeated whether or not it worked. The measurement side is covered in markdown depth and margin math.
Where scheduled pricing goes wrong in practice
- Timezone drift. Your end date is interpreted in store time. If you're coordinating a campaign with an agency in another timezone, write the store-time value into the calendar table and convert only for communication.
- The sale price and a live automatic discount collide. If you drop the price and leave an automatic discount running, the customer gets both. That's a legitimate stacking surprise, not a bug — the combination was permitted by both. Turn off the automatic discount before you edit prices, or expect the compounded depth.
- The compare-at is left behind after restoration. You restore the price but forget the compare-at still holds the old value, so the storefront shows a permanent discount on a full-price product. Check both fields at verification time, not just price.
- Some markets were never covered. A scheduled price edit that ran through an app scoped to one market leaves other markets at the old price. Verify one product in each market you sell in.
- Draft orders and wholesale price lists keep their own prices. Restoring the storefront doesn't restore a B2B catalog, which may need its own pass.
When the sale is a rolling markdown, not an event
The calendar above assumes a bounded event. That works for a seasonal sale. It does not work for clearing aged inventory, where the SKU list changes weekly, products sit at different depths, and each depth has its own hold window — manual restoration becomes a permanent part-time job.
That's the shape of problem ClearStock addresses: markdown rules driven by product status and runway, with a percentage discount cap, exclusions, and restoration when the rule ends. If your next promotion has a start date and an end date, you don't need it. If your whole spring is a rolling markdown across 300 SKUs, a calendar table is the wrong instrument.
Common questions
Can you schedule a sale price on Shopify? Not with a native price-change scheduler in the admin at the time of writing. What you can schedule is product publishing, Flow automations where the action exists on your plan, app-based price changes, or an API script. Whichever you use, the restoration date is a separate commitment you should calendar before launch.
What's the difference between price and compare-at price? Price is what the customer pays and what feeds checkout, tax, and reporting. Compare-at is a display-only anchor producing the struck-through "was" price — it changes presentation, not revenue.
How do I put a product on sale and then restore the original price? Export prices before the sale, record the original and the pre-sale compare-at in your sale calendar, edit the price for the window, then restore in a single bulk pass and verify with a guest checkout — otherwise restoration leaves a fabricated anchor behind.
Does the compare-at price affect checkout? No — the cart, taxes, shipping thresholds, and reports all use price. That's also why a stale compare-at after a sale is invisible in your numbers and obvious to your customers.
What happens if I forget to restore prices after a sale? The sale price becomes the price. After a few weeks, raising it back reads as a price increase rather than a sale ending, and in some jurisdictions a long-running struck-through anchor raises reference-pricing questions.
Next step: open the sale you're currently running and check three things: does it have an end time in store timezone, does the calendar table have the pre-sale compare-at value recorded, and has anyone placed a guest test order since launch? Fix whichever is missing before you do anything else — then, when the window closes, restoring prices after a sale picks up exactly there.