Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteParse every JSON-LD block, connect each offer to its plan, and retain its price, currency and billing term. Then compare those fields with the pricing page’s visible labels and billing toggle; JSON-LD alone may not reveal whether a “per month” figure is charged monthly or is the monthly equivalent of an annual commitment.
What pricing-page JSON-LD can—and cannot—tell you
JSON-LD can expose plan names and offer details, but it is not a guaranteed inventory of every plan, market or billing choice shown on a SaaS site. Google’s SoftwareApplication structured-data documentation shows an offer with price and priceCurrency. For Google’s software-app rich result, name and offers.price are required, and currency is recommended when the price is greater than zero. Those requirements do not mean that a pricing page will encode all its subscription options as structured offers.
As an Amazon Associate I earn from qualifying purchases.
Schema.org defines PriceSpecification as “A structured value representing a price or price range.” Its UnitPriceSpecification adds fields such as billingDuration (how long the price is billed), billingIncrement, billingStart and priceType. A page may use some of these fields, another structure, or no explicit cadence at all.
Extract offers without losing their context
- Capture the page context. Save the requested URL, final URL after redirects, retrieval time, response status and a copy or hash of the response body. Record the locale or market when known, because prices and currency can vary. Do not treat a block page or access challenge as a valid pricing response.
- Parse every JSON-LD script independently. Find each
<script type="application/ld+json">block and parse it as JSON. Accept top-level objects and arrays, then traverse@graphand nested objects. Retain a parse error with its block index rather than silently dropping malformed data. - Connect an offer to its plan. Find relevant entities—possibly
SoftwareApplication,Product,Serviceor a page-specific type—and follow theiroffersand price-specification relationships. Keep graph links and entity paths. Do not combine every offer into a single page-wide price: the graph may include multiple plans, currencies, markets or price components. - Keep raw values alongside normalized ones. Preserve the original price string and, when parsing is unambiguous, a normalized numeric value. Store the currency code, the exact source path, plan name and any stable identifier or
@id. Record the JSON-LD block index, entity path, page URL and retrieval time so a price can be traced back to the captured response.
A useful record can also retain cadence text or billingDuration, per-seat or per-user basis, minimum quantity, price type, validity window, setup charges and usage-based components when present. This is a practical data-model recommendation, not a schema-mandated record format; mark missing fields as unavailable rather than filling them by inference.
#1 Best Overall
Decide whether an offer is monthly or annual conservatively
A displayed “$X / month” can mean a monthly charge or a monthly equivalent billed as an annual commitment. A toggle can change the rendered page without changing server-delivered JSON-LD, and structured data may expose only one offer. Do not infer cadence from the amount or multiply a monthly-looking price by 12.
Compare each captured offer with the visible plan label, billing-toggle state and, where accessible, checkout terms. Keep each observation with its source. If JSON-LD says one thing while the rendered page says another, retain separate candidates or mark cadence unresolved instead of silently choosing one. Neither Schema.org’s pricing vocabulary nor Google’s documented offer formats establish that SaaS publishers consistently encode every billing state.
Normalize prices without erasing useful distinctions
Use an explicit priceCurrency code rather than guessing from a symbol such as “$”. Schema.org recommends standard currency codes such as USD and a full stop as the decimal separator in structured prices. Preserve the raw value as well: localized commas and periods can be ambiguous without locale context. If there is not enough information to parse a number safely, keep the source string and flag it.
Recommended Free Tools
When comparing offers, keep the basis of each figure visible. A price may be per seat, subject to a minimum quantity, introductory, tied to a validity window or combined with setup or usage fees. Compare the charge cadence and total commitment, currency and market, quantity basis, usage limits and trial or renewal terms only where the page or markup actually supplies those details.
Rank #3
Validate the captured markup and Google’s interpretation separately
- Check your capture: confirm that each script block was parsed, the relevant graph relationships were followed, and each output price still points to its source entity and path.
- Check Google-facing markup: use Google’s Rich Results Test, address critical errors, and inspect deployed pages with URL Inspection. A page must be accessible to Google and not blocked by robots.txt, marked
noindexor gated behind login requirements. - Allow for indexing delay: Google says it may take several days after publishing a page to find and crawl it, so a recent markup change may not appear immediately in inspection or search results. See the SoftwareApplication documentation.
Successful JSON parsing confirms syntax, not that the extracted amount matches the current visible offer. A valid Rich Results Test likewise does not prove that every plan or billing option has been captured.
Quick Recap
Best Value
Common scraping mistakes
- Treating every
offersnode as the main subscription price, or flattening the graph and attaching a price to the wrong plan. - Assuming
offers.priceandpriceSpecification.priceare interchangeable in every context. For Google’s Product snippet processing, Google says it usesoffers.priceand ignoresoffers.priceSpecificationwhen both encode an active price. Preserve both in your own data pipeline; this is Google’s rule for that feature, not a universal conflict rule. See Product snippet structured data. - Inferring a currency from its symbol or parsing localized decimal separators without enough locale context.
- Assuming the initial HTML contains all relevant data. Some sites may populate or change markup after JavaScript execution; determine whether rendering is needed for the particular target site.
- Treating a parsed price or valid structured-data test as proof that it matches the live offer and selected billing option.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




