Why does a JSON-LD date, URL or price need a particular format?

‘<field>’ should be a URL / an ISO 8601 date string / a positive number page

The issue

A JSON-LD value in the wrong format is there in the markup and still can’t be used as what it claims to be. A datePublished of “March 2, 2026” isn’t a date a parser can rely on, a relative image path doesn’t say which site it belongs to, and a price of “$19.99” isn’t a number. The property looks filled, so the gap is easy to miss.

The cause is usually a template that prints the value the way the page displays it: a formatted date, a path relative to the site, a price with its currency symbol.

Scope

Each field with a known format is checked on each object where it appears, including in nested objects of a type probeo knows. For URL fields holding a list, each value is checked; a value that is itself an object, such as an ImageObject, is left to its own checks. Each is a warning, so the block still counts as valid.

How to check you have it

  • In probeo: the page reports one of three warnings, naming the field:
    • 'url' should be a URL, for url, image, logo, thumbnailUrl, contentUrl, embedUrl and screenshot.
    • 'datePublished' should be an ISO 8601 date string (e.g. "2024-01-15"), for datePublished, dateModified, startDate, endDate, uploadDate, datePosted and validThrough.
    • 'price' should be a positive number, for price, ratingValue, reviewCount and ratingCount.
  • By hand: view the page source, find each <script type="application/ld+json"> block, and read those fields’ values against the formats below.
  • With a tool: the Schema Markup Validator shows each value as it was read, which makes a formatted date or a relative path easy to spot.

The fix

Write each value in its machine-readable format, separately from how the page displays it.

The page can still show “March 2, 2026” and “$19.99” to readers. The JSON-LD takes the same facts in the forms below, usually from the raw field the template formats for display.

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Registered agent service",
  "image": "https://example.com/images/registered-agent.png",
  "offers": {
    "@type": "Offer",
    "price": "125.00",
    "priceCurrency": "USD",
    "priceValidUntil": "2026-12-31"
  }
}

Done when: every date, URL and number field is in the format below, and the check above comes back clean.

Do not

  • Do not copy the displayed, formatted value into the markup.
  • Do not put the currency symbol in price; it belongs in priceCurrency.
  • Do not use a relative path for an image or URL field.

The formats probeo accepts

Kind Accepted Reported
URL starts with https://, http:// or // /images/a.jpg, images/a.jpg, example.com/a.jpg
Date 2026-03-02, or with a time: 2026-03-02T09:30:00Z, 2026-03-02T09:30:00-05:00 March 2, 2026, 03/02/2026, 2026-03
Number a number, or a string that reads as one: 125, "125.00" "$125", "free", a negative number

FAQ

Why is a relative URL a problem when the browser understands it?

The browser resolves it against the page’s address. The JSON-LD is read as data, often apart from the page, and a path on its own doesn’t say which site it belongs to.

Does the date need a time?

No. A date alone, such as 2026-03-02, is accepted. A time can follow after a T, with a time zone.

Is a price of zero accepted?

Yes. Probeo reports a value that isn’t a number or is below zero. A free offer can carry a price of 0 with its currency.

Does probeo check duration or totalTime?

No. Probeo checks the date, URL and number fields listed above. Durations such as PT30M aren’t format-checked.

Which product detects this

Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.