Home › Blog › Shopify product FAQ page schema
Shopify product FAQ page schema for AI shopping agents: the pre-purchase query playbook
AI shopping agents answer pre-purchase questions — "is this BPA-free?", "does it fit a king mattress?", "what’s the warranty?" — from structured data on your product pages. Without FAQPage JSON-LD, agents either skip the question or extract an answer unreliably from description text. The difference is whether your store gets cited or your competitor’s does.
In this guide
- Why pre-purchase queries are the silent conversion lever
- How AI agents use FAQPage JSON-LD
- The 5 question categories that cover 80% of pre-purchase queries
- Implementation: the two-block architecture on Shopify
- Metafield architecture for scalable FAQ at catalog level
- Before/after: a water bottle product
- Integrating FAQ into a full @graph with Product
- 5 FAQPage mistakes on Shopify product pages
- FAQ
Why pre-purchase queries are the silent conversion lever
The AI shopping funnel is different from the Google Shopping funnel. In Google Shopping, a customer sees your product image, price, and title in a grid. They click through to verify the details themselves. The product page carries the conversion burden.
In AI shopping — ChatGPT Shopping, Perplexity Shopping, Google AI Mode — the funnel is reversed. The agent answers the question first, then surfaces a product recommendation. The customer’s pre-purchase questions are resolved before they ever see a product page. If the agent can’t answer the question confidently from your structured data, it either skips your product or cites a competitor whose catalog answers the question clearly.
This is the gap that FAQPage JSON-LD fills. A FAQPage block on a product page is a machine-readable answer bank. Each Question/Answer pair is a direct, attributable answer the AI agent can cite with confidence. There’s no parsing ambiguity — the question text and answer text are explicit fields.
How AI agents use FAQPage JSON-LD
FAQPage is a schema.org type that wraps a list of Question and Answer pairs. Each Question has a name (the question text) and an acceptedAnswer property containing an Answer with a text field (the answer text).
When an AI shopping agent crawls a product page, it indexes FAQPage entries separately from the Product entity. The question text becomes a match target for conversational queries. If a user asks "is this water bottle BPA-free?" and the crawled page has a Question with that text and a clear Answer, the agent has a high-confidence source to cite.
The key distinction from product descriptions is attribution confidence. When an agent extracts an answer from paragraph text, it is making an inference — the answer might be there, might be approximate, might conflict with text elsewhere on the page. When the agent reads a Question/Answer pair, the merchant is making an explicit claim. The agent can cite it as a direct merchant statement, not an inferred fact.
Google uses FAQPage to generate rich results in standard search (expanded Q&A beneath the main result). But in AI Mode and Perplexity, the use is different: FAQ pairs are used to populate the conversational answer layer — the part of the response that directly answers the user’s question before links are shown.
See also
The 5 question categories that cover 80% of pre-purchase queries
Pre-purchase queries follow consistent patterns across product categories. Based on AI shopping query patterns, these five categories account for the majority of pre-purchase questions that agents are asked before a recommendation is made:
The most common category for kitchen, baby, pet, and supplement products. Customers ask about specific materials or certifications because they affect health and safety decisions.
Critical for electronics, accessories, and anything that attaches to or works with another product. Compatibility questions have a binary answer — yes or no — making them ideal FAQ candidates.
Apparel, bedding, furniture, and sporting goods all generate high volumes of sizing queries. These questions are particularly high-value: a wrong size means a return, and AI agents know it.
For durables, electronics, and anything with a significant price point, warranty queries are pre-purchase due diligence. Clear FAQ answers on warranty reduce perceived purchase risk and correlate with higher conversion on first-time AI referrals.
These queries are often the final hesitation point before a purchase. AI agents can answer them per-product if you have product-level FAQ schema — though note that store-wide policies should live in MerchantReturnPolicy Organization schema and product-specific conditions in FAQ.
For each product, pick 3–6 questions from the categories most relevant to that product type. A kitchen appliance might need compatibility + materials + warranty. A clothing item needs sizing + returns. More than 8 questions per product creates diminishing returns and risks diluting the most important answers.
Implementation: the two-block architecture on Shopify
Shopify themes output Product JSON-LD in a single <script type="application/ld+json"> block. FAQPage lives in a second, separate block on the same page. Do not merge them unless you are using @graph (covered in the @graph section below).
The basic FAQPage block for a product page looks like this:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Is this water bottle BPA-free?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. The bottle body and lid are made from BPA-free Tritan co-polyester. The silicone gasket is food-grade and phthalate-free. All materials are FDA-compliant."
}
},
{
"@type": "Question",
"name": "Is this dishwasher safe?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The bottle body is top-rack dishwasher safe. The lid should be hand-washed — high dishwasher temperatures can degrade the silicone seal over time."
}
},
{
"@type": "Question",
"name": "What is the warranty?",
"acceptedAnswer": {
"@type": "Answer",
"text": "This bottle carries a lifetime guarantee against manufacturing defects. If the lid or seal fails under normal use, we replace it free of charge. Contact support@example.com with your order number."
}
}
]
}
</script>
Three structural rules to follow:
- Question
namemust be a question. It should end with a question mark and be phrased as a customer would ask it. Not "BPA status" — "Is this BPA-free?" - Answer
textmust be a complete sentence. Fragment answers ("Yes") are valid JSON-LD but are too thin to be cited confidently by AI agents. Full, specific answers win more citations. - No HTML in answer text. The
textfield is a plain string. HTML entities like&will be parsed as literal characters. Keep answers in plain prose.
Metafield architecture for scalable FAQ at catalog level
Hard-coding FAQ questions into a product template only works for one product. For a real catalog, you need the question/answer content stored in Shopify metafields so each product has its own FAQ data, editable from the admin.
The recommended architecture uses a single JSON metafield per product:
| Namespace | Key | Type | Notes |
|---|---|---|---|
product_faq | questions | JSON | Array of {"question": "...", "answer": "..."} objects |
Store the metafield value as a JSON array:
[
{
"question": "Is this BPA-free?",
"answer": "Yes. The body is Tritan co-polyester, the lid and seal are food-grade silicone. All materials are FDA-compliant and phthalate-free."
},
{
"question": "Is this dishwasher safe?",
"answer": "The bottle body is top-rack dishwasher safe. Hand-wash the lid to preserve the silicone seal."
},
{
"question": "What is the capacity?",
"answer": "This bottle holds 32 oz (946 ml). The wide mouth is 2.2 inches in diameter and fits standard ice cubes."
}
]
Then in your product.liquid or sections/main-product.liquid:
{% assign faq_json = product.metafields.product_faq.questions.value %}
{% if faq_json and faq_json.size > 0 %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{% for item in faq_json %}
{
"@type": "Question",
"name": {{ item.question | json }},
"acceptedAnswer": {
"@type": "Answer",
"text": {{ item.answer | json }}
}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
</script>
{% endif %}
Key points about this Liquid pattern:
- The
{% if faq_json and faq_json.size > 0 %}guard ensures the FAQPage block only renders for products with FAQ data — no emptymainEntity: []blocks. - The
| jsonfilter escapes quotes, backslashes, and special characters in question and answer strings, preventing JSON parse errors from apostrophes in answers. product.metafields.product_faq.questions.valuereturns the parsed array (not the raw JSON string) when the metafield type is set to JSON in the admin.
Before/after: a water bottle product
Before: description-only product page
A typical Shopify product page for a water bottle has a Product JSON-LD block generated by Dawn or the active theme. It contains name, description, offers, possibly an aggregateRating. The description field contains prose like:
"Our 32oz BPA-free Tritan water bottle is perfect for the gym, hiking, and everyday hydration. Features a leak-proof lid and wide mouth for easy filling. Dishwasher safe. Backed by our lifetime guarantee."
An AI agent asked "is this water bottle BPA-free?" can attempt to extract this from the description. But the extraction is uncertain: Is "BPA-free" in the title, the description, a metafield, a product tag? The agent makes an inference and may hedge the answer (“the listing says it’s BPA-free”), or flag uncertainty, or skip the product entirely if it finds conflicting information on the page.
After: with FAQPage JSON-LD
The same product page now has a second JSON-LD block:
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Is this water bottle BPA-free?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. The bottle body is made from BPA-free Tritan co-polyester. The lid and silicone seal are food-grade and phthalate-free. All materials are FDA-compliant."
}
},
{
"@type": "Question",
"name": "What is the capacity of this water bottle?",
"acceptedAnswer": {
"@type": "Answer",
"text": "32 oz (946 ml). The wide mouth is 2.2 inches in diameter and fits standard ice cubes."
}
},
{
"@type": "Question",
"name": "Is this water bottle dishwasher safe?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The bottle body is top-rack dishwasher safe. Hand-wash the lid to preserve the silicone seal over time."
}
},
{
"@type": "Question",
"name": "What is the warranty on this bottle?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Lifetime guarantee against manufacturing defects. If the lid or silicone seal fails under normal use, we replace it free of charge."
}
}
]
}
Now when an AI agent is asked "is this water bottle BPA-free?" it has a direct, attributable answer. No inference required. The agent can say: "Yes, according to the product page, it is BPA-free Tritan with a food-grade silicone seal." Confident citation. The store gets surfaced; the competitor with only description-text coverage does not.
Integrating FAQ into a full @graph with Product
If you are building a custom product JSON-LD block from scratch (rather than relying on the theme’s auto-generated block), you can consolidate Product and FAQPage into a single @graph array. This is cleaner than two separate script tags and allows you to establish an @id relationship between the FAQPage and the Product page URL.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Product",
"@id": "https://yourstore.myshopify.com/products/32oz-tritan-water-bottle#product",
"name": "32oz Tritan Water Bottle",
"description": "BPA-free 32oz Tritan water bottle with leak-proof lid. Top-rack dishwasher safe body. Lifetime guarantee.",
"brand": { "@type": "Brand", "name": "YourBrand" },
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"price": "34.99",
"availability": "https://schema.org/InStock",
"url": "https://yourstore.myshopify.com/products/32oz-tritan-water-bottle"
}
},
{
"@type": "FAQPage",
"@id": "https://yourstore.myshopify.com/products/32oz-tritan-water-bottle#faq",
"mainEntity": [
{
"@type": "Question",
"name": "Is this water bottle BPA-free?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. Tritan co-polyester body, food-grade silicone seal. All materials are FDA-compliant and phthalate-free."
}
}
]
}
]
}
</script>
The @id on the FAQPage entity uses the product URL with a #faq fragment, disambiguating it from the Product entity. This is optional but recommended when using @graph — it makes the entity graph unambiguous for validators.
In Liquid, generate the product @id using {{ shop.url }}{{ product.url }} and append the fragment. The rest of the graph follows the same metafield-driven pattern described in the implementation section above.
5 FAQPage mistakes on Shopify product pages
Many Shopify FAQ apps add FAQPage JSON-LD to a designated FAQ page or the homepage. This helps Google FAQ rich results on the homepage, but does nothing for product-level AI query coverage. FAQPage must be on the actual product page to answer queries about that product. The entities must be co-located.
A FAQ that answers "What is your return policy?" and "How do I track my order?" on every product page addresses store policies, not product facts. These questions are worth answering — in MerchantReturnPolicy Organization schema, not in per-product FAQPage. Per-product FAQ should answer questions specific to that product: its materials, its compatibility, its sizing, its warranty. Generic FAQs dilute the signal and waste the 8-question limit.
If the Liquid conditional is missing and the product has no FAQ metafield content, the template renders "mainEntity": [] — a valid but empty FAQPage. Validators will flag this as an error. Parsers may interpret it as the page intentionally declaring no FAQ content. Always gate the entire script block on {% if faq_json and faq_json.size > 0 %}.
The text field of an Answer is a plain string in schema.org. Including HTML like <strong>Yes</strong> or <br> in the answer text makes the JSON-LD technically invalid (schema.org text properties expect plain text, not HTML). Validators accept it, but some parsers strip or escape the HTML, turning your answer into a string containing angle brackets. Write answers in plain prose. If you need emphasis, use capitalization or punctuation — not HTML.
FAQPage is not a property of Product in schema.org. They are sibling types that both describe the same page. A common mistake is nesting the FAQ data as a made-up "faq" property on the Product entity: "@type": "Product", "faq": {...}. This is ignored by validators and parsers alike. Keep them as separate script blocks, or as sibling entries in a page-level @graph.
FAQ
<script type="application/ld+json"> block in the <head> or just before </body> in your sections/main-product.liquid. Keep it separate from the theme’s auto-generated Product block, or consolidate both into an @graph array. Never nest FAQPage inside the Product type as a property.@graph siblings.product_faq, key questions, type JSON. Store an array of {"question": "...", "answer": "..."} objects. In Liquid, iterate over product.metafields.product_faq.questions.value to build the FAQPage mainEntity array. This is editable from the Shopify admin and scalable to any catalog size.Is your FAQ schema actually parsing?
CatalogScan’s structured data scan checks FAQPage coverage across your product catalog — including empty mainEntity blocks, missing Question types, and pages where FAQ data exists but isn’t rendering.
Run a free scan More guides