How to Add FAQ Schema to WordPress Without a Plugin
Skip Yoast and RankMath. Drop FAQ JSON-LD straight into your post with a Custom HTML block — the right way, with copy-paste code.
Every major WordPress SEO plugin claims to handle FAQ schema automatically. In practice, they do — but with tradeoffs. Yoast wraps FAQ schema generation behind its FAQ block, which ties your content structure to the plugin. RankMath adds schema through its own panel, but the output differs across versions and occasionally breaks after updates. When you stop paying for the premium tier, some features disappear.
The alternative is simpler than it sounds: a Custom HTML block in Gutenberg with your JSON-LD pasted directly in. No plugin dependency, no proprietary block format, complete control over the output.
Why skip the plugin for FAQ schema
No plugin lock-in. FAQ content stored in a Yoast FAQ block is readable as HTML, but if you ever switch plugins or migrate to a different CMS, the semantic structure is gone. Plain Gutenberg blocks and raw JSON-LD survive any migration.
Exact output control. Plugin-generated schema makes assumptions. Your acceptedAnswer text might get trimmed, your question formatting might not match what the plugin expects, or the plugin might inject extra fields you don't want. Writing the JSON-LD yourself means the output is exactly what you wrote.
No version fragility. Schema plugin bugs ship on plugin update day. If you've ever had a Yoast update break your rich results, you know this is a real concern. Static JSON-LD in a Custom HTML block doesn't change unless you change it.
Lighter page. Every active plugin adds PHP execution time and typically some JavaScript. If FAQ schema is the only thing you're using a plugin for, removing it shrinks your server-side overhead.
The Gutenberg Custom HTML block approach
In the WordPress block editor, add a Custom HTML block anywhere in your post — typically after the FAQ section it describes, or at the bottom of the article. Paste your <script type="application/ld+json"> block inside it.
Here's a complete FAQPage schema example:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is FAQ schema markup?",
"acceptedAnswer": {
"@type": "Answer",
"text": "FAQ schema markup is structured data that tells Google your page contains a list of questions and answers. It can unlock expandable Q&A cards in search results."
}
},
{
"@type": "Question",
"name": "Do I need a plugin to add FAQ schema to WordPress?",
"acceptedAnswer": {
"@type": "Answer",
"text": "No. You can add FAQ schema directly to any WordPress post using a Custom HTML block in Gutenberg. Paste your JSON-LD markup into the block and Google will read it."
}
},
{
"@type": "Question",
"name": "How many FAQ questions can I include in one schema block?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Google doesn't publish a hard limit, but in practice 2–10 questions per page is the common range for FAQ rich results. Focus on questions that are genuinely useful to the reader."
}
}
]
}
</script>
Paste this into a Custom HTML block, swap out the questions and answers for your own content, and save. That's the full implementation.
The visibility requirement — this is the part people miss
Google's FAQ rich results guidelines have one hard requirement that plugins don't always enforce: every question in your schema must appear visibly on the page. The questions and answers in the FAQPage JSON-LD must correspond to visible Q&A content the user can read in the HTML.
This means two things:
- Don't add FAQ schema for questions that only exist in the schema block and nowhere in the article text.
- The text in
name(the question) andtext(the answer) should closely match what's visible. They don't need to be character-for-character identical, but they should cover the same content.
If you have an FAQ section with <h3> headings for questions and paragraph text for answers, your schema's name and text fields should mirror those. A good pattern is to write your visible FAQs first, then paste the questions and answers into the schema template.
Handling multiple FAQ posts — the reusable snippet approach
If you publish FAQ-heavy content regularly, maintaining a custom JSON-LD block in every post is tedious. A few approaches that scale better:
WordPress Reusable Blocks: Create a Reusable Block containing your FAQ HTML block template. When you start a new FAQ post, insert the reusable block and edit the questions. Note that edits to a reusable block affect all instances — convert it to a regular block first before editing individual post FAQs.
Code Snippets plugin (one plugin exception): If you want to add FAQ schema programmatically based on a custom field, the Code Snippets plugin is lightweight and specifically designed for PHP snippets. You can hook into wp_head and output your JSON-LD from custom post meta:
<!-- Custom HTML block example with WordPress post meta -->
<!-- This approach uses a custom field named "faq_schema_json" -->
<!-- Add raw JSON-LD directly in the Custom HTML block per post -->
Post template in your theme: If you're comfortable with PHP, add a conditional to your single.php or content.php that reads a custom field and outputs the schema block. This keeps the schema out of the block editor entirely.
For most bloggers and small sites, the per-post Custom HTML block approach is the right call. It's transparent, portable, and takes two minutes per post.
JSON encoding gotchas
A few things that will break your JSON-LD silently:
Unescaped double quotes in answer text. If your answer contains a quote — "this is a "quoted" phrase" — the JSON parser will choke. Escape internal quotes with \" or rewrite the sentence to avoid them.
Unescaped newlines. Multi-line answer text needs \n for line breaks within the JSON string, or better yet, write the entire answer as a single continuous string with no literal newlines inside the quotes.
Trailing commas. JSON doesn't allow trailing commas. { "name": "Question?", } is invalid. Double-check after your last question object in the mainEntity array.
Use the Google Rich Results Test after saving your post to catch syntax errors before they stay live.
When this beats the plugin approach
The manual JSON-LD approach wins when:
- You're already maintaining your SEO metadata manually and don't want another plugin's fingers in the schema output
- You have specific formatting requirements that plugin-generated schema doesn't match
- You're migrating the site and need schema that survives a CMS change
- You're troubleshooting rich result issues and need to know exactly what's in the schema
The plugin approach wins when you have a large editorial team that can't be trusted to maintain JSON-LD manually, or when you're generating schema for dozens of fields (like Product with complex offers structures). For FAQ schema specifically, the manual approach is almost always simpler.
Related guides
For broader schema context, see the schema markup guide. If you're seeing validation errors after adding your FAQ schema, the validation errors guide covers the most common failures including malformed JSON and visibility issues.
Other platforms with similar manual JSON-LD patterns: Next.js App Router and Shopify blog articles.