Generating FAQ JSON-LD dynamically
JSON-LD is a powerful way to provide structured data to search engines. When it comes to FAQs, proper JSON-LD implementation can help your content appear in rich snippets and potentially even surface you near the top of search results just by providing useful information.
This lesson focuses on creating a dynamic FAQ JSON-LD generator that scales alongside your FAQ documents. You will build a type-safe solution that's reusable across your site and follows Google's structured data guidelines.
Learning objectives
By the end of this lesson, you'll be able to:
- Generate JSON-LD for FAQs programmatically
- Implement type-safe JSON-LD using Google's schema-dts
- Improve your FAQ block from the page builder lessons
Understanding JSON-LD generation
JSON-LD generation can be challenging, especially when dealing with TypeScript. Fortunately, Google provides a TypeScript package (opens in a new tab) called schema-dts
that gives you type safety for your structured data.
Let's start by creating a function that transforms your FAQ data into a JSON-LD friendly structure. Luckily, all the way back in the page builder lessons you created a FAQ document schema. This will come in handy to reuse the FAQ data and eventually become a repository of FAQ data you can reuse across your site.
Here's how you should structure your FAQ data:
import { FAQPage, WithContext } from "schema-dts";
import { Faqs } from "~/types";
const getJsonFaqs = (faqs: Faqs) => {
const faqJson: WithContext<FAQPage> = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: faqs?.map((faq) => ({
"@type": "Question",
name: faq.question,
acceptedAnswer: {
"@type": "Answer",
text: portableRichTextToHtml(faq.answer),
},
})),
};
return faqJson;
};
Notice how you can use the FAQs types generated from Sanity to adhere to your JSON-LD TypeSafe schema.
Implementing FAQ JSON-LD in components
Now that you have your JSON-LD generator, let's see how to use it within a page builder block. Here's an example implementation in a FAQs block component:
export const FaqAccordion: FC<FaqAccordionProps> = ({
faqs,
title,
richText,
}) => {
const jsonFaqs = getJsonFaqs(faqs);
return (
<div>
{/* The frontend for your block */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonFaqs) }}
/>
</div>
);
};
Notice how the most important part of this block, is the script
tag. This is where you're adding the JSON-LD to the page. This should get you thinking about how you can reuse this pattern across your site.
The FAQ schema covered here is just the tip of the JSON-LD iceberg. The beauty of structured data is that once implemented, it works silently in the background to enhance your search presence.
Some other examples you may want to implement:
- Product information (opens in a new tab)
- Event information (opens in a new tab)
- Blog post information (opens in a new tab)
- Video information (opens in a new tab)
- Recipe information (opens in a new tab)
- Course information (opens in a new tab)
- Job post information (opens in a new tab)
- Person information (opens in a new tab)
- Organization information (opens in a new tab)
Conclusion
The more you lean into structured data, the more benefits you'll experience.
If there's one thing to take away from this whole course, it's that SEO doesn't need to be a mentally taxing process. It's about taking your existing data and repurposing it to make it more digestible for your audience and, by extension, for search crawlers.
The future of the web won't be about configuring hundreds of different fields to get the perfect SEO score. Instead, it will focus on finding ways to accelerate content creation and automating the tasks you don't want to do.
Good luck, and I hope you enjoyed the course! Please get in touch if you have any questions or feedback.