Skip to the solution
MediumFrontend4 min read

What is JSON-LD structured data and how do you add it in Next.js?

549 views

The problem

Question presented to candidate: "How would you add Product structured data to a product page in Next.js, and what security issue must you handle when the data comes from users?"

What a strong answer should cover:

  • JSON-LD is schema.org data in a script type="application/ld+json" tag that search engines read for rich results.
  • In Next.js render it from the page or layout as a script element with dangerouslySetInnerHTML and JSON.stringify(data).
  • Escape < (for example replace it with the unicode escape \u003c), otherwise a value containing a closing script tag ends the tag early and the rest becomes HTML.
  • It is not part of the Metadata API; it is rendered in the component tree, and the page renders on the server so crawlers see it.
  • Validate the output with Google Rich Results Test and keep it consistent with visible content.

Clarifying questions expected:

  • "Which schema types matter (Product, Article, FAQ, Breadcrumb)?" β€” decides the fields.
  • "Is any field user-generated?" β€” then escaping is mandatory.

Code / implementation expected: Yes β€” a safe JSON-LD script in a page.

  • nextjs
  • json-ld
  • structured-data
  • seo

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

4 min read Β· 8 sections

Read the code

A product page with safe JSON-LD
// app/products/[slug]/page.tsx
function jsonLd(data: unknown) {
  return JSON.stringify(data).replace(/</g, "\\u003c");
}

export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {
  const product = await getProduct((await params).slug);
  const data = {
    "@context": "https://schema.org",
    "@type": "Product",
    name: product.name,
    image: product.imageUrl,
    offers: { "@type": "Offer", price: product.price, priceCurrency: "EUR", availability: "https://schema.org/InStock" },
  };
  return (
    <main>
      <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: jsonLd(data) }} />
      <h1>{product.name}</h1>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 70 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

How do Next.js Devtools MCP and AGENTS.md change AI-assisted debugging?

Continue