# Generating JSON-LD dynamically https://www.sanity.io/learn/course/seo-optimization/generating-json-ld-dynamically.md JSON-LD is a powerful way to provide structured data to search engines—fortunately structured data is what Sanity does best. JSON-LD data follows structured conventions for many different types of content. All you'll need to do is take content already authored in your documents, and render it into the DOM in the expected format. We already have FAQs as a document type, so it makes sense to start there. 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. ## Learning objectives By the end of this lesson, you will: * Generate JSON-LD for FAQs programmatically * Implement type-safe JSON-LD using Google's `schema-dts` package * Improve your FAQ block from the page builder course ### Understanding JSON-LD generation JSON-LD generation can be challenging to get right as it follows a strict structure. Fortunately, [Google provides a TypeScript package](https://github.com/google/schema-dts) called `schema-dts` that gives you type safety for your structured content. Let's start by creating a function that transforms your FAQ data into a JSON-LD friendly structure. Back in [Create page builder schema types](https://www.sanity.io/learn/course/page-building/create-page-builder-schema-types) you created a document type schema for FAQs. 1. **Run** the following to install the `schema-dts` package ```sh:Terminal pnpm add schema-dts ``` Currently in the GROQ query for pages the FAQ block is returning the full document for every reference. Let's update this to only extract specific fields from the document, as well as the Portable Text in the `body` field as a string using the GROQ function `pt::text()` 1. **Update** your GROQ query for pages, to return the answer in plain text ```groq:src/sanity/lib/queries.ts // replace this faqs[]-> // with this faqs[]->{ _id, title, body, "text": pt::text(body) } ``` You've updated your queries, so update your types ```sh:Terminal pnpm run typegen ``` ### Implementing FAQ JSON-LD in components The JSON-LD markup can be rendered anywhere in the page—it doesn't need to be stored inside the ``. So you can add it directly into components where you already have access to the correct data. In this instance, you're rendering the FAQ content into an accordion in this block, so you can also have it process that same content into the JSON-LD format and add it to the component output. 1. **Update** your `FAQs` block to render JSON-LD content in a script tag ```tsx:src/components/blocks/faqs.tsx // ...all your imports and types import { FAQPage, WithContext } from "schema-dts"; const generateFaqData = (faqs: FAQsProps["faqs"]): WithContext => ({ "@context": "https://schema.org", "@type": "FAQPage", mainEntity: faqs?.map((faq) => ({ "@type": "Question", name: faq.title!, acceptedAnswer: { "@type": "Answer", text: faq.text!, }, })), }); export function FAQs({ _key, title, faqs }: FAQsProps) { const faqData = generateFaqData(faqs); return (