Meta tags describe a document; JSON-LD describes the thing the document is about, which is what earns a rich result. There is no metadata field for it, and none is needed: a Server Component renders a <script type="application/ld+json"> into the body and the crawler reads it there.
const jsonLd = {
"@context": "https://schema.org", "@type": "Book",
name: book.title, author: { "@type": "Person", name: book.author },
isbn: book.isbn, datePublished: book.published,
url: `https://example.com/books/${book.slug}`,
aggregateRating: { "@type": "AggregateRating",
ratingValue: book.rating, reviewCount: book.reviews },
};
<script type="application/ld+json" dangerouslySetInnerHTML={{
__html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }} /><script type="application/ld+json">{"@context":"https://schema.org","@type":"Book",
"name":"The Pragmatic Programmer","author":{"@type":"Person","name":"Andrew Hunt"},
"isbn":"9780135957059","datePublished":"2019-09-13",
"url":"https://example.com/books/the-pragmatic-programmer","aggregateRating":
{"@type":"AggregateRating","ratingValue":4.7,"reviewCount":1842}}</script>Three details decide whether this is safe and useful. Use a plain <script>, not next/script: JSON-LD is data, and next/script schedules executable code. Escape the output — JSON.stringify does nothing about a </script> hidden in a title, so replace < with < or reach for serialize-javascript. And keep the markup honest: Google requires the marked-up facts to be visible to the reader too.
Install `schema-dts 1,246 ` (https://www.npmjs.com/package/schema-dts 3,157 K ) with npm 2,036 i -D schema-dts and annotate the object as WithContext<Book>; a misspelled datePublised is then a compile error. Validate with Google's Rich Results Test 1 (https://search.google.com/test/rich-results 1 ) or the Schema Markup Validator 5,868 (https://validator.schema.org/ 5,868 ).