New: The $100M AI Visibility Roadmap, built from 7,960 live pages and 197 A/B tests. Get it free →

Home / Blog / How to Add FAQ Schema to Shopify Without an App

Technical SEO · 14 min read

How to Add FAQ Schema to Shopify Without an App

Build an FAQ section that prints visible answers and matching FAQPage JSON-LD from the same fields, test the rendered page, and know what Google's May 2026 removal of FAQ rich results changes.

Robert Battle · Updated

Key takeaways
  • Google stopped showing FAQ rich results on May 7, 2026 and removed the documentation on June 15, 2026, so FAQ markup no longer creates Google dropdowns.
  • Generate the visible FAQ and the FAQPage JSON-LD from the same Shopify fields so the markup can never drift from what shoppers read.
  • Use theme section blocks for FAQ and policy pages, and metaobjects on a product list metafield for product-specific questions.
  • Shopify's json filter adds its own quotes, so never wrap a filtered value in extra quotation marks.
  • Check for duplicate FAQPage output from apps before and after you publish; the console count should be exactly 1.

To add FAQ schema to Shopify without an app, create a theme section that outputs your visible questions and a matching FAQPage JSON-LD script from the same fields, add it to an alternate template, then validate the rendered page. Know the 2026 reality before you start: Google stopped showing FAQ rich results in Search on May 7, 2026, so this markup describes your content for machines but will not create dropdowns in Google results.

This guide is for Shopify merchants, developers and SEO leads who want FAQ markup that stays accurate without another app subscription. You'll get the current Google position with dates, a decision table for the four ways to do it, two working Liquid examples (a reusable section and a metaobject version for product FAQs), a testing checklist and the mistakes we see most often in theme code.

Does FAQ schema still matter in 2026?

FAQ schema is FAQPage structured data from schema.org: a JSON-LD block that labels each question and its accepted answer on a page. For years its main appeal was the expandable FAQ rich result in Google. That feature has now been shut down in two steps.

How Google phased out FAQ rich results
LimitedAug 8, 2023Shown only for well-known government and health sites
RemovedMay 7, 2026FAQ rich results stop appearing in Google Search
Docs goneJun 15, 2026Google deletes its FAQ rich result documentation

Source: Google Search Central Blog, Changes to HowTo and FAQ rich results (Aug 8, 2023); Google Search Central documentation updates (May 8 and June 15, 2026)

In August 2023 Google said FAQ rich results would "only be shown for well-known, authoritative government and health websites." On May 8, 2026 Google's documentation changelog added a deprecation notice saying the feature "will no longer appear in Google Search starting May 7, 2026," and on June 15, 2026 Google removed the FAQ rich result documentation entirely. Our guide to why FAQ schema is not showing in Google covers the history in more detail.

So why build it at all?

  • The visible FAQ is the real asset. Clear answers about sizing, shipping, returns and compatibility reduce support tickets and help shoppers decide. In our own testing, an FAQ accordion won every one of 19 A/B tests where we added it to homepages and collections.
  • Markup is cheap when it shares a source. If the section that prints the answers also prints the JSON-LD, there is no second copy to keep in sync.
  • Unused markup is harmless. When Google limited the feature in 2023, it said "there's no need to proactively remove it" and that structured data that's not being used "does not cause problems for Search."

What FAQ markup does not do: it does not guarantee rankings, AI Overview inclusion or ChatGPT citations. Google's structured data guidelines state that it "does not guarantee that your structured data will show up in search results." No primary source we could find says AI answer engines reward FAQPage markup specifically, so treat any vendor claim that it does with caution. Clear, quotable answers in the visible HTML are what help most. Our pillar guide on FAQ schema explains the vocabulary itself.

Choose how to add FAQ schema to Shopify

There are four common ways to get FAQPage JSON-LD onto a Shopify page. The right one depends on whether the questions are the same across many pages or unique to each product.

MethodBest forVisible FAQ and markup in sync?Main risk
Theme section with blocks (Method 1)A dedicated FAQ page, shipping or returns page, a single landing pageYes, both come from the same block fieldsSection settings are shared by every page on the same template
Metaobjects plus a product metafield (Method 2)Product-specific questions across a catalogYes, both come from the same metaobject entriesNeeds a metaobject definition and a little developer time
FAQ or SEO appTeams with no theme accessUsually, if the app renders bothDuplicate FAQPage output if the theme also emits it; monthly fee
Hand-pasted JSON-LD in a Custom Liquid blockOne-off pagesNo, you maintain two copiesAnswers drift from the visible text after edits

For most stores we recommend Method 1 for policy and support pages and Method 2 for product pages. Both keep a single source of truth, which is the only thing that keeps markup accurate a year from now. If you want to see what correct output looks like before touching code, build a sample with our FAQ Schema Generator and keep it as a reference.

Before you start: back up and check for duplicates

Theme edits go live the moment you save in the published theme, so work in a copy. Shopify's help center explains how to duplicate a theme from Online Store > Themes using the actions menu next to the theme. Edit and preview the duplicate, then publish it when everything checks out.

Find any FAQPage markup that already exists

Many themes, review apps and SEO apps already output structured data. Two FAQPage blocks describing the same questions is the most common FAQ schema mistake we find. Open the page you plan to edit, open your browser's developer console, and run:

[...document.querySelectorAll('script[type="application/ld+json"]')]
  .filter(s => s.textContent.includes('FAQPage')).length

A result of 0 means no FAQPage JSON-LD is present in the rendered page. Anything higher means something already outputs it. Also search the page source for FAQPage to catch microdata (an itemtype attribute) and entities nested inside an @graph. Then check these places in the theme code editor and admin:

  • Sections and snippets with names like faq, collapsible-content or accordion
  • Custom Liquid blocks added in the theme editor
  • App embeds under Theme settings > App embeds for SEO, schema and FAQ apps

Pick one owner for FAQ output. If an app already prints accurate FAQPage markup from your visible answers, you may not need any code. If you switch to a theme section, turn off only the app's FAQ feature, not its Product or BreadcrumbList output.

Find duplicate and broken schema on your store

We'll benchmark your store against your top three competitors on Google and AI answers, flag the pages ready to move and prioritize the technical fixes with the revenue math.

Get my technical SEO audit →

Method 1: an FAQ section with built-in JSON-LD

This section prints a visible accordion and the matching FAQPage script from the same question and answer blocks. It skips any block with an empty field and outputs nothing at all when no complete questions exist, so you never ship an empty mainEntity array.

  1. In your duplicate theme, go to Online Store > Themes > ... > Edit code.
  2. In the sections folder, add a new file named faq-with-schema.liquid and paste the code below.
  3. Under templates, create an alternate page template such as page.faq. Online Store 2.0 templates are JSON files that list sections, so you add the section through the theme editor rather than pasting Liquid into the JSON file.
  4. Open the theme editor, switch to the page.faq template, add the FAQ with schema section and fill in your questions and answers.
  5. In the Shopify admin, assign the faq template to the page you want, then preview it in the duplicate theme.

{%- liquid
  assign faq_count = 0
  for block in section.blocks
    assign q = block.settings.question | strip
    assign a = block.settings.answer | strip
    if q != blank and a != blank
      assign faq_count = faq_count | plus: 1
    endif
  endfor
-%}
{%- if faq_count > 0 -%}
<section aria-labelledby="faq-{{ section.id }}">
  <h2 id="faq-{{ section.id }}">{{ section.settings.heading | escape }}</h2>
  {%- for block in section.blocks -%}
    {%- assign q = block.settings.question | strip -%}
    {%- assign a = block.settings.answer | strip -%}
    {%- if q != blank and a != blank -%}
      <details {{ block.shopify_attributes }}>
        <summary>{{ q | escape }}</summary>
        <p>{{ a | escape | newline_to_br }}</p>
      </details>
    {%- endif -%}
  {%- endfor -%}
</section>
{%- assign emitted = 0 -%}
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
  {%- for block in section.blocks -%}
    {%- assign q = block.settings.question | strip -%}
    {%- assign a = block.settings.answer | strip -%}
    {%- if q != blank and a != blank -%}
      {%- if emitted > 0 -%},{%- endif -%}
      {
        "@type": "Question",
        "name": {{ q | json | replace: '<', '\u003c' }},
        "acceptedAnswer": {
          "@type": "Answer",
          "text": {{ a | json | replace: '<', '\u003c' }}
        }
      }
      {%- assign emitted = emitted | plus: 1 -%}
    {%- endif -%}
  {%- endfor -%}
  ]
}
</script>
{%- endif -%}

{% schema %}
{
  "name": "FAQ with schema",
  "settings": [
    { "type": "text", "id": "heading", "label": "Heading", "default": "Frequently asked questions" }
  ],
  "blocks": [
    {
      "type": "faq",
      "name": "Question",
      "settings": [
        { "type": "text", "id": "question", "label": "Question" },
        { "type": "textarea", "id": "answer", "label": "Answer (plain text)" }
      ]
    }
  ],
  "max_blocks": 20,
  "presets": [{ "name": "FAQ with schema", "blocks": [{ "type": "faq" }] }]
}
{% endschema %}

Why the code is written this way

  • The json filter adds the quotes. Shopify's Liquid reference says you don't need to wrap its output in quotes because "the json filter includes them," and it escapes quotes inside the text. Adding your own quotes around {{ q | json }} is the most common way this markup breaks.
  • The replace on the less-than sign turns any < in an answer into the JSON escape \u003c, so a stray </script> typed into an answer cannot close the script tag early. JSON parsers read it back as the original character.
  • Plain-text fields. The answer uses a textarea setting so the visible text and the JSON-LD text match exactly. If you need links in answers, switch to a richtext setting, print it unescaped in the HTML, and run it through strip_html before json in the script.
  • The {% schema %} tag is not structured data. It only configures the theme editor. The schema.org markup is the application/ld+json script.
  • Body placement is fine. Google's structured data introduction says JSON-LD can sit in a script tag in the head or the body of the page.

Because the questions are stored in the template's section settings, every page assigned to page.faq shows the same FAQ. If your shipping page and your wholesale page need different answers, give each its own alternate template, or use Method 2.

What the rendered output should look like

With two questions entered, view the page source of the preview and you should see a script like this, with no trailing comma and no doubled quotes:

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Do you ship to Canada?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Orders to Canada ship in 3 to 5 business days. Duties are shown at checkout."
      }
    },
    {
      "@type": "Question",
      "name": "Can I return a sale item?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Sale items can be returned within 30 days for store credit."
      }
    }
  ]
}

Method 2: product FAQs with metaobjects

Template-level sections fall apart on product pages, because every product on the default product template would share the same answers. Store product questions on the product itself instead. Shopify's Liquid reference says the value property of a list metafield "returns an array" you can loop through, and metaobject fields are read with .value, which is the pattern below.

Set up the data model

  1. In Settings > Custom data > Metaobjects, add a definition named FAQ item with two fields: question (single line text) and answer (multi-line text).
  2. In Settings > Custom data > Products, add a metafield definition with namespace and key custom.faqs, type Metaobject, referencing FAQ item, set to a list of entries.
  3. On each product, create or pick the FAQ entries that apply. A question like "Is this compatible with the 2024 model?" can be reused on every product it applies to.
  4. Add a new section file, for example sections/product-faq.liquid, with the code below plus a {% schema %} tag and preset like Method 1, then add it to your product template in the theme editor.

{%- assign faqs = product.metafields.custom.faqs.value -%}
{%- if faqs != blank -%}
<section aria-label="Product questions">
  <h2>Questions about {{ product.title | escape }}</h2>
  {%- for item in faqs -%}
    <details>
      <summary>{{ item.question.value | escape }}</summary>
      <p>{{ item.answer.value | escape | newline_to_br }}</p>
    </details>
  {%- endfor -%}
</section>
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
  {%- for item in faqs -%}
    {
      "@type": "Question",
      "name": {{ item.question.value | json | replace: '<', '\u003c' }},
      "acceptedAnswer": {
        "@type": "Answer",
        "text": {{ item.answer.value | json | replace: '<', '\u003c' }}
      }
    }{%- unless forloop.last -%},{%- endunless -%}
  {%- endfor -%}
  ]
}
</script>
{%- endif -%}

Products with no FAQ entries print nothing, so the section is safe to add to the default product template. Forum reports suggest Liquid loops over list references stop at 50 entries; keep product FAQs well below that anyway. Five to eight genuine questions is plenty for a product page.

Page typeGood FAQ topicsWhere to store it
Product pageSizing, compatibility, materials, care, what's in the boxMetaobject entries on a product list metafield
Collection pageHow to choose between products in the rangeCollection metafield or a section on an alternate collection template
FAQ or help pageShipping, returns, payment, order changesSection blocks on an alternate page template
HomepageThe three to five questions that block first purchasesSection blocks on the index template

Keep the same question off dozens of unrelated products. Google's guidelines say structured data "must be a true representation of the page content," so a sitewide shipping FAQ belongs on your shipping page, not repeated in every product's markup. If your product pages also carry Product markup, our guide to product schema on Shopify covers that side.

Why the visible FAQ matters more than the markup

With the rich result gone, the business case for FAQs rests on shoppers. That case is strong in our own data. Across 197 A/B tests on 26 e-commerce stores, tests in FAQ sections won every time.

A/B test win rate by page type197 tests across 26 e-commerce stores; FAQ sections won 19 of 19
FAQ sections100%
Homepage94.1%
Product pages87.1%
Sitewide85.2%
Collections81%
View the data
Value
FAQ sections100%
Homepage94.1%
Product pages87.1%
Sitewide85.2%
Collections81%

Source: QCK A/B test results, 197 tests, qck.co/ab-test-results

Those wins came from the content and its placement, not from schema. So write the answers first:

  • Answer in the first sentence. "Yes, it fits the 2024 model" beats a paragraph of context. Short, direct answers are also the easiest for AI answer engines to quote.
  • Use real questions. Pull them from support tickets, chat logs, reviews and the "People also ask" box for your product category.
  • Keep answers in the HTML. An accordion is fine, but load the answer text with the page rather than fetching it when someone clicks.
  • Keep it page specific. Five questions that matter on this page beat twenty generic ones.
Structured data is one piece of AI visibility

Our free $100M AI Visibility Roadmap, built from 7,960 live pages and 197 A/B tests, shows how to get your answers cited by ChatGPT, Google AI Overviews and Perplexity.

Get the free roadmap →

How to test FAQ schema on Shopify

Test the rendered page, not the Liquid file. A validator cannot run Liquid; it only sees the HTML Shopify outputs.

  1. Preview the duplicate theme on the page with the FAQ template assigned and view the page source.
  2. Copy the JSON-LD script and paste it into our Schema Markup Validator or validator.schema.org. Fix any syntax error first; a single extra comma invalidates the whole block.
  3. Compare every question and answer in the markup with the visible text. They should match word for word.
  4. Stress-test the fields. Enter an answer with quotation marks, an apostrophe, a line break and a less-than sign. Confirm the script still parses and the page still displays correctly.
  5. Test the empty states. Clear one answer, then remove all blocks. The incomplete question should disappear from both outputs, and with no blocks the script should not print at all.
  6. Rerun the duplicate check from earlier. The console count should be exactly 1.
  7. Check an unrelated page, such as a blog article, to confirm the FAQ did not leak into the wrong template.
  8. Publish, then recheck the live URL. Template assignments and app settings are not reversed by rolling back a theme, so write down what you changed.

Don't use Google's Rich Results Test as the pass or fail signal for FAQ markup. Google has removed the FAQ feature and its documentation, so a missing FAQ result there says nothing about whether your JSON-LD is valid. A general schema validator is the right check now.

Common FAQ schema mistakes on Shopify

SymptomLikely causeFix
Validator reports invalid JSONExtra quotes around a json filtered value, or a trailing comma after the last questionRemove the manual quotes; use forloop.last or a counter for commas
Two FAQPage blocks on one pageAn app embed and a theme section both output FAQ markupKeep one owner and disable the other's FAQ output only
Same answers on every productFAQ blocks added to the shared product templateMove product questions into metaobjects (Method 2)
Markup lists questions the page doesn't showHand-pasted JSON-LD that was never updatedGenerate markup from the same fields as the visible FAQ
Answer text shows raw HTML tags in the scriptRich text printed into JSON-LD without strip_htmlStrip HTML before the json filter
Translated page has English markupVisible text translated, hardcoded JSON-LD notGenerate both from translatable fields

If you have other structured data on the page, check that you haven't broken it while editing. Our Schema Markup Generator can rebuild Organization, Product or BreadcrumbList blocks for comparison, and our ecommerce schema markup guide explains which types still produce Google features. It is also worth confirming each FAQ page has the right canonical tag, so the version you marked up is the one Google indexes.

Keep your FAQs accurate after launch

FAQ markup is page infrastructure, and it goes stale the same way content does. A short routine keeps it trustworthy:

  • Write down the setup: the section file name, which templates use it, which metafield holds product FAQs and which app (if any) is turned off for FAQs.
  • Recheck after theme updates and app installs. A new review or SEO app is the usual source of a second FAQPage block.
  • Update answers when policies change. A shipping time or return window in an FAQ is a promise to the customer.
  • Review questions quarterly against support tickets and site search, and replace questions nobody asks.

If you'd like a second pair of eyes on your structured data, duplicate markup and the rest of your technical SEO, talk to our team.

Turn your FAQs into rankings and revenue

Book a free 30-minute call. We'll compare you with your top three competitors, show which pages are ready to move and give you a prioritized plan with the revenue math.

Get my custom plan →
FAQ

Questions & answers

Do I need an app to add FAQ schema to Shopify?
No. A theme section can print the visible FAQ and the FAQPage JSON-LD from the same fields. You only need an app if you have no access to theme code.
Will FAQ schema give my Shopify store FAQ rich results?
No. Google stopped showing FAQ rich results in Search on May 7, 2026. Valid markup still describes your content, but it will not create expandable FAQs in Google results.
Should I remove existing FAQ schema from my store?
You don't have to. When Google limited the feature in 2023, it said unused structured data does not cause problems for Search. Remove it if it is duplicated, inaccurate or hard to maintain.
Can FAQ JSON-LD go in the body instead of the head?
Yes. Google says JSON-LD can be placed in a script tag in either the head or the body, so printing it inside the FAQ section is fine.
How do I add different FAQs to each Shopify product?
Create an FAQ item metaobject with question and answer fields, add a product metafield that lists those entries, and loop over it in a product section so each product prints its own questions.
Free custom plan

Find the revenue you're leaving on the table

A free 30-minute call where we build the first version of your plan with you. You leave with a plan either way.

  • Your score across Google, AI citations, branded demand, and reviews
  • The pages on your site that are ready to move right now
  • Your first Flagship page and the first three tests we'd run

Step 1 of 3

Get your free custom plan

Free. Takes about 30 seconds.