Skip to content
Issue docs

Product schema missing a nested Offer

Importantoffer_schema_nestedIssue 106

What is this issue?

This issue reports an Offer or AggregateOffer block your page already declares — nested inside a Product or elsewhere — that is missing price (or lowPrice) or priceCurrency. It is not the same as a Product declaring no offers at all; that is issue #109.

What this issue is not:

  • It does not fire on a Product with no offers property — see #109 for that.
  • It does not check availability, currency validity or numeric price format here; a Product's own offers are checked more thoroughly as part of the Product's own validation, reported under #108.

Why it matters

Offer schema is essential for e-commerce SEO and user experience:

  • Product rich results: Enables price, availability, and review stars in search results
  • Price drop badges: Google shows "Price drop" badges when priceValidUntil is set
  • Availability signals: Helps users see if products are in stock before clicking
  • Conversion optimization: Users are more likely to click when they see current pricing
  • AI search readiness: AI engines use Offer data to answer pricing queries accurately

Resolving this issue improves your e-commerce SEO health score by ensuring product pricing information is properly structured for search engines and AI systems.

How to fix it

If this issue was raised, your page already declares an Offer or AggregateOffer that is missing price/lowPrice or priceCurrency — open the finding for specifics. A Product with no offers property at all is a different issue (#109); the steps below fix an offer that is present but incomplete.

  1. Locate Product schema: Find pages with Product schema (check your product detail pages)

  2. Add or complete the offers property in your Product schema:

    {
      "@context": "https://schema.org",
      "@type": "Product",
      "name": "Product Name",
      "description": "Product description",
      "offers": {
        "@type": "Offer",
        "price": "29.99",
        "priceCurrency": "USD",
        "availability": "https://schema.org/InStock",
        "priceValidUntil": "2024-12-31",
        "url": "https://example.com/product-page",
        "seller": {
          "@type": "Organization",
          "name": "Store Name"
        }
      }
    }
  3. Use correct values for key properties:

    • price: Numeric value as string (e.g., "29.99")
    • priceCurrency: ISO 4217 currency code (e.g., "USD", "EUR", "GBP")
    • availability: Use Schema.org URLs: https://schema.org/InStock, https://schema.org/OutOfStock, https://schema.org/PreOrder, etc.
    • priceValidUntil: ISO 8601 date format (e.g., "2024-12-31")
  4. For multiple offers, use AggregateOffer:

    "offers": {
      "@type": "AggregateOffer",
      "lowPrice": "29.99",
      "highPrice": "49.99",
      "priceCurrency": "USD",
      "offerCount": "5"
    }
  5. Validate with Google's Rich Results Test

Examples

Example 1: A Product With No offers — See Issue #109, Not This One

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Wireless Headphones",
  "description": "High-quality wireless headphones with noise cancellation"
}

A Product declaring no offers property at all is reported under issue #109 ("Offer schema missing or incomplete"), not this one. This issue only fires once an Offer or AggregateOffer is actually present and incomplete.

Example 2: A Well-Formed Offer (passes)

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Wireless Headphones",
  "offers": {
    "@type": "Offer",
    "price": "199.99",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Example 3: A Product's Offer Missing priceCurrency (fails)

Problematic state:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Smartphone",
  "offers": {
    "@type": "Offer",
    "price": "599.99"
  }
}

Reported here: Offer schema nested inside Product is incomplete at index 0: priceCurrency missing. The same page also gets a separate finding under the Product's own issue (#108) for the same and any additional offer faults (such as a missing availability), since the Product's own validation checks the offer more thoroughly.

Corrected state:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Smartphone",
  "offers": {
    "@type": "Offer",
    "price": "599.99",
    "priceCurrency": "USD",
    "availability": "https://schema.org/InStock"
  }
}

Example 4: A Standalone AggregateOffer Missing priceCurrency (fails)

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Running Shoes",
  "offers": {
    "@type": "AggregateOffer",
    "lowPrice": "89.99",
    "highPrice": "129.99",
    "offerCount": "5"
  }
}

Reported: AggregateOffer schema (nested inside Product) is present but failed validation: priceCurrency missing.

How PixyScan detects this

This check is about an Offer that is present but incomplete — not a Product with no offers at all (that is issue #109).

  1. Read the declared structured data: every JSON-LD block is parsed, and @graph wrappers are flattened.

  2. Two routes trigger this issue:

    • A Product's own offers array: for each entry whose @type is Offer, price and priceCurrency are checked.
    • Any nested Offer or AggregateOffer object found elsewhere in a declared schema: price/priceCurrency (Offer) or lowPrice/priceCurrency (AggregateOffer) are checked.

    A page that declares no Offer/AggregateOffer anywhere is not examined.

  3. This is reported when: a Product's own offer entry, or any nested Offer/AggregateOffer block, is missing the properties above. A Product with no offers property at all is reported separately, under #109 — not this issue.

Note: availability, currency validity and numeric-price format are validated more thoroughly as part of a Product's own rich-result rules, and any failure there is reported under the Product's own issue (#108) rather than here.

What we store

Storage Level

Page Level — This issue is evaluated for each individual URL that contains structured data.


Database Table / Prisma Model

PageStructuredData


Stored Fields

Field Type Description
schemaType SchemaType The type of schema (e.g., Organization, Person)
schemaFormat SchemaFormat The format of the schema (JSON-LD, Microdata, RDFa)
schemaIdentifier String? Unique identifier for the schema
rawJson Json? The raw JSON-LD or structured data content
schemaErrors Json? Array of validation errors found in the schema
isValidSchema Boolean? Whether the schema is valid according to validation
missingFields Json? Reserved for future use — the crawler always writes null here today; no check currently populates it

Detection Dependencies

  • The following data sources are required to evaluate this issue:
  • HTML Document — The crawler parses the HTML to find structured data (JSON-LD, Microdata, RDFa)
  • Structured Data Validation — The extracted schema is validated against Schema.org definitions
  • Schema Parser — JSON-LD scripts, Microdata attributes, and RDFa markup are parsed

Further reading