Publish prices search engines accept, and the ones the page actually shows

Fixkamo-marketing
Shipped
September 10, 2026 at 7:08 PM UTC
Author
Kamo
Commit
7511cb2

Search Console's product snippet report flagged "Invalid price format" on both `price` and `priceSpecification.price`. The cause was Enterprise going out as "price": "-1" — the catalogue's marker for "quoted on application" — because /pricing stringified the raw rate without branching on it. A negative price is not a price. The rest of the product markup was wrong in quieter ways: - /pricing quoted each plan's month-to-month rate ($69 / $119) while its cards open on the three-year rate with the running offer applied ($32.83 / $66.33). Structured data that disagrees with the visible price is grounds for the snippet to be dropped. - The SoftwareApplication block on the homepage, /product, /features, /solutions and /alternatives carried typed-in offers from two price lists ago — Starter $34, Business $72 — and listed Enterprise at "0", telling search engines the dearest plan is free. - Organization carried a hand-typed AggregateOffer topping out at the retired $64. schema.org does not define `offers` on Organization, so it was discarded anyway; it is removed. Both product blocks now take their offers from planOffers (app/lib/product-offers.ts), which reads the catalogue and prices each plan with quotePlan on HOME_TERM — the same call the card makes. A plan quoted on application gets no Offer rather than an invented price. A discounted plan carries its struck-through term rate and a priceValidUntil ending with the offer. Prices are JSON numbers rounded to cents, never strings. ProductJsonLd is now async and locale-aware, sharing the pricing fetch and its 5-minute cache entry. With the catalogue unreachable it renders nothing rather than a guessed price. scripts/check-product-offers.ts (npm run guard:offers, in test and prebuild) asserts every published price is a non-negative number with at most two decimals and matches its card, and fails if a price literal reappears under app/components/seo. It flags every hardcoded price in the previous versions of both components. Verified on a production build against the live catalogue: every page carrying product markup publishes Free 0, Starter 32.83 (was 49), Business 66.33 (was 99), valid until 2026-09-30, with no Enterprise offer and no invalid price anywhere. aggregateRating and review are left absent. They are optional enhancements, and Google permits them only from genuine user reviews shown on the page; the site has none to mark up.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing