A sale is not only a set of prices. It is usually also a badge on the product card, a countdown in the header, maybe a banner. Those are theme changes, and theme changes do not expire on a schedule the way a price does.
Where leftovers hide
- Theme code, as a snippet injected into theme.liquid or a section file. This is the one that survives everything, including uninstalling the app.
- Product tags, added to mark what was in the sale and never removed.
- Metafields holding the original price or a sale flag, still read by the theme.
- Script tags, which the platform does remove on uninstall, though not always immediately.
How to check
In the admin, open Online Store, Themes, Edit code, and search theme.liquid for the app's name. Anything found there was added by the app and will not remove itself. Then look at a product that was in the sale and check its tags and metafields.
Before you delete anything
Duplicate the theme first. A snippet that looks like a leftover may be load-bearing for something else you installed, and a duplicated theme costs nothing to keep for a week.
Why this happens at all
Injecting code into the theme is the simplest way for an app to display a badge, and it works immediately on any theme. The cost is that the app now owns a piece of your theme and has to clean it up correctly on every ending, every cancellation and every uninstall. Many do not.
The alternative is theme app blocks, which the merchant adds and removes in the theme editor themselves. Nothing is injected, so nothing can be left behind. SaleGuard uses blocks for its countdown, shipping bar and sale badge, and writes no code into the theme.