ServicesAI Audit
← Back to Blog

How to Use Offer Schema to Win AI Shopping Recommendations

Schema MarkupOffer SchemaAI ShoppingJSON-LDE-commerce SEOAI VisibilityShopify SEOLLM SEO
A black gift box with a red ribbon surrounded by sale tags on a vivid red background, showcasing a discount theme.

Why AI Shopping Engines Need Structured Pricing Data

When someone asks ChatGPT or Perplexity "where can I buy a waterproof hiking jacket under £150?", those engines don't browse product pages the way a human would. They rely on structured signals baked into your HTML to understand what you sell, at what price, and whether it's actually available right now. Without that structured data, your product is essentially invisible to AI-driven shopping queries, even if it ranks perfectly well on Google.

Offer schema, formally schema.org/Offer, is the piece of structured data that tells AI engines and search platforms everything they need to know about a purchasing opportunity on your site. Price, currency, availability, condition, delivery costs, and return policies can all live inside a single, machine-readable block of JSON-LD. Get it right and you give AI systems a clean, confident signal to cite your product. Get it wrong, or skip it entirely, and you hand that citation opportunity to a competitor who bothered.

This guide walks through exactly how to implement Offer schema, which properties matter most for AI visibility, and the common mistakes that silently kill your chances of being recommended.

The Core Properties That Actually Drive AI Citations

Not all Offer schema properties carry equal weight when it comes to AI shopping recommendations. Some are table stakes. Some are differentiators. Here is how to think about them.

Price and priceCurrency

These two are non-negotiable. If an AI engine cannot confirm your price and the currency it's expressed in, it will not confidently recommend your product in a price-sensitive query. Always use price as a numeric value (not "£49.99" - just "49.99") and pair it with priceCurrency using the ISO 4217 code, so "GBP" for pounds, "USD" for dollars, "EUR" for euros.

One mistake people make constantly: setting the price to zero during a development phase and forgetting to update it. AI crawlers cache structured data, and a £0.00 product looks broken or fraudulent. Check your live pages regularly.

availability

Use one of the schema.org availability values: InStock, OutOfStock, PreOrder, Discontinued, or LimitedAvailability. AI engines will actively avoid recommending out-of-stock products in a shopping context because it creates a bad experience for their users. Keep this accurate and update it dynamically if your platform allows it. On Shopify, this is usually achievable through a theme snippet or an app that writes JSON-LD based on inventory levels.

priceValidUntil

This is a date property that tells AI systems your price is valid up to a specific point. Many sites skip it entirely, which is a missed opportunity. Including priceValidUntil signals to AI engines that the data is current and intentional, not stale. Use ISO 8601 format: "2025-12-31". If you run rolling promotions, update this programmatically rather than leaving it perpetually set to a date two years in the future, which can look like a placeholder.

url

Always include the canonical URL of the product page inside the Offer object. It seems obvious, but a surprising number of implementations omit it or point to a category page. AI engines use this to attribute the offer to a specific, reachable page. Without it, citations may be incomplete or omitted entirely.

seller

Nest an Organization or Person entity inside the seller property to tell AI systems who is making the offer. This is especially important for marketplaces or brands that sell through multiple channels. A clear seller entity links your offer back to a known brand identity, which improves trustworthiness signals. Pair this with a proper Brand schema strategy to reinforce who you are across the knowledge graph.

A Working JSON-LD Example for an E-commerce Product

Here is a realistic Offer schema implementation for a product page, nested inside a Product type as it should be:

{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "Waterproof Hiking Jacket",
  "description": "Lightweight, fully waterproof hiking jacket with taped seams and a packable hood. Suitable for three-season use.",
  "image": "https://example.com/images/hiking-jacket.jpg",
  "brand": {
    "@type": "Brand",
    "name": "TrailKit"
  },
  "offers": {
    "@type": "Offer",
    "url": "https://example.com/products/waterproof-hiking-jacket",
    "priceCurrency": "GBP",
    "price": "129.00",
    "priceValidUntil": "2025-12-31",
    "itemCondition": "https://schema.org/NewCondition",
    "availability": "https://schema.org/InStock",
    "seller": {
      "@type": "Organization",
      "name": "TrailKit Ltd"
    },
    "hasMerchantReturnPolicy": {
      "@type": "MerchantReturnPolicy",
      "applicableCountry": "GB",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": 30,
      "returnMethod": "https://schema.org/ReturnByMail"
    },
    "shippingDetails": {
      "@type": "OfferShippingDetails",
      "shippingRate": {
        "@type": "MonetaryAmount",
        "value": "0",
        "currency": "GBP"
      },
      "deliveryTime": {
        "@type": "ShippingDeliveryTime",
        "handlingTime": {
          "@type": "QuantitativeValue",
          "minValue": 0,
          "maxValue": 1,
          "unitCode": "DAY"
        },
        "transitTime": {
          "@type": "QuantitativeValue",
          "minValue": 2,
          "maxValue": 4,
          "unitCode": "DAY"
        }
      }
    }
  }
}

Notice a few things here. The itemCondition is explicitly set to NewCondition. The return policy is nested directly inside the Offer using hasMerchantReturnPolicy. Shipping details are included. These additions are what separate a bare-minimum implementation from one that genuinely feeds AI shopping engines the full picture they want.

Offer Schema for Variable Products and Multiple Variants

If your product comes in multiple variants, such as different sizes, colours, or configurations, you have two main options. You can use an array of Offer objects inside the offers property, each representing a distinct variant. Or you can use AggregateOffer to express a price range across all variants.

Using AggregateOffer

AggregateOffer is ideal when you have many variants and want to surface a price range. Use lowPrice, highPrice, and offerCount to communicate the spread. For example:

{
  "@type": "AggregateOffer",
  "lowPrice": "49.99",
  "highPrice": "129.99",
  "priceCurrency": "GBP",
  "offerCount": 6
}

AI engines handle this well for category-level queries. For product-specific queries, individual Offer objects with precise pricing tend to perform better because the AI can give a definitive answer rather than a range.

Offer Arrays for Specific Variants

If you have a manageable number of variants (say, fewer than ten), listing individual Offer objects is the stronger approach. Each one can carry its own price, availability, and name for the variant. This gives AI systems precise data to match against user queries like "blue, size medium, under £60".

Shipping and Returns: The Properties Most Sites Ignore

Shipping details and return policies are two of the most frequently missing pieces in Offer schema, and they matter a great deal for AI shopping recommendations. When someone asks an AI assistant "which online shops offer free next-day delivery on running shoes?", the engine needs structured shipping data to answer accurately. If your site doesn't have OfferShippingDetails in place, you simply won't feature in that answer.

The same logic applies to return policies. Shoppers increasingly query AI engines about returns before buying. A well-structured MerchantReturnPolicy nested inside your Offer tells AI systems your returns window, your method (by post, in store), and whether return shipping is free. You can read more about this in our dedicated guide on MerchantReturnPolicy schema for AI shopping trust.

Setting up shipping details requires you to know your shipping zones, rates, and handling times. Yes, it's more work than dropping in a price and calling it a day. But it's exactly this kind of detail that AI engines look for when they're trying to give a shopper a confident, specific recommendation rather than a vague "check the website".

Common Implementation Mistakes That Block AI Citations

Even well-intentioned implementations often contain errors that silently prevent AI engines from using the data. Here are the most common ones seen in practice.

Mismatched prices

The price in your schema must match the visible price on your page. AI engines and Google's crawlers both validate this, and a mismatch is treated as a red flag. If you have a sale price showing on the page but your schema still has the original price, your structured data will be ignored or flagged. Dynamic JSON-LD generation tied to your CMS or Shopify metafields is the cleanest fix.

Hardcoded availability

A huge number of Shopify themes have Offer schema built in but with availability hardcoded to InStock regardless of actual inventory. This is worse than no schema at all because it sends people to your site expecting to buy something that isn't available. Check your theme's JSON-LD output against a product that you know is out of stock.

Missing currency codes

Omitting priceCurrency entirely, or using a symbol like "£" instead of the ISO code "GBP", causes parsing failures. The price data becomes unusable. This is one of the most common errors flagged in AI visibility audits.

Schema on the wrong page

Offer schema belongs on individual product pages, not on your homepage or collection pages. Some platforms accidentally inject product schema site-wide. Structured data validators will pass it, but the contextual mismatch confuses AI crawlers. If you're unsure what your pages are currently outputting, a free AI visibility audit will surface these issues quickly.

How Offer Schema Fits Into a Wider AI Visibility Strategy

Offer schema on its own will improve your chances of being cited in AI shopping queries, but it works best as part of a joined-up approach. Your product data should sit alongside well-structured AggregateRating schema so AI engines can report on both price and customer sentiment in the same recommendation. Ratings are a significant factor in whether an AI presents your product as a confident suggestion or hedges with "you might want to check reviews". See how AggregateRating schema influences AI recommendations for more on that side of the equation.

Brand clarity matters too. If your Offer schema names a seller but that seller isn't clearly defined elsewhere in your knowledge graph, AI engines may struggle to resolve the entity. Consistent brand markup across your site gives AI systems the confidence to attribute offers to a known, trusted source.

At FlinnSchema, this is exactly the kind of holistic implementation work we do for e-commerce brands. Not just dropping a schema block in and hoping for the best, but building a coherent structured data architecture that AI engines can actually use. If you want to see what that looks like in practice, the client results page has specific examples.

Frequently Asked Questions

Does Offer schema help with Google Shopping as well as AI search?

Yes. Well-implemented Offer schema supports both Google's rich results for products and AI engine citations. The properties that matter for AI visibility, such as accurate pricing, availability, and shipping details, are largely the same ones Google uses to populate Shopping listings. You're not building two separate things. One strong implementation serves both purposes.

How often should I update my Offer schema?

Your schema should reflect your live product data at all times. For price and availability, this means dynamic generation tied to your inventory system rather than static, manually edited code. For priceValidUntil, update it whenever you run a promotion or at least quarterly to signal freshness to crawlers. Stale schema is actively harmful because it creates mismatches between what AI engines report and what shoppers find on your page.

Can I use Offer schema on a collection or category page?

Not in the same way. Individual Offer objects belong on product pages. For category pages, you'd use CollectionPage schema to describe the page type, potentially referencing products within it. Using Offer schema on a category page without proper context creates ambiguity that AI engines handle poorly. Keep product-level schema on product-level pages.

What's the difference between Offer and AggregateOffer?

Offer represents a single, specific purchasing opportunity at a defined price. AggregateOffer represents a collection of offers, typically used for products with multiple variants, and expresses a price range using lowPrice and highPrice. Use AggregateOffer when you want to communicate a range across variants; use individual Offer objects when you want to be precise about each variant's price and availability. For AI shopping queries that are highly specific, individual offers perform better.

Want to check your AI visibility?

Run a free audit on your website and see how visible you are to ChatGPT, Perplexity, and other AI search engines.

Run Free Audit