Skip to content

JsonLd

JsonLd renders a <script type="application/ld+json"> tag in the document head from either a pre-serialized JSON string or a schema object. It is responsible for safely writing the JSON payload inline and does not validate schema structure.

For practical, strongly typed patterns using schema-dts, see JsonLd with schema-dts.

proptypedefaultrequireddescription
jsonLdRecord<string, unknown> | string-YesJSON-LD payload as either a pre-serialized string or a plain object. Object values are serialized internally with JSON.stringify(...) before rendering.

Input:

<JsonLd
jsonLd='{"@context":"https://schema.org","@type":"WebPage","name":"Home"}'
/>

Output:

<script type="application/ld+json">
{ "@context": "https://schema.org", "@type": "WebPage", "name": "Home" }
</script>

Input:

---
const websiteSchema = {
"@context": "https://schema.org",
"@type": "WebSite",
name: "Example Site",
url: "https://example.com",
};
---
<JsonLd jsonLd={websiteSchema} />

Output:

<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "Example Site",
"url": "https://example.com"
}
</script>

JsonLd accepts either a JSON string or a plain object. Object inputs are serialized internally, while string inputs are passed through as-is before escaping.

Escapes HTML-sensitive characters before injection

Section titled “Escapes HTML-sensitive characters before injection”

Before writing the script content, the component escapes <, >, and & into their Unicode escape sequences (\u003c, \u003e, \u0026). This prevents script-breakout when inline JSON contains those characters.

The component always renders one application/ld+json script when a value is provided. If multiple schema entities are needed, prefer a single payload with @graph so your page head can keep one JSON-LD script block.

---
interface Props {
jsonLd: Record<string, unknown> | string;
}
const { jsonLd }: Props = Astro.props;
const ESCAPE_MAP: Record<string, string> = {
"<": "\\u003c",
">": "\\u003e",
"&": "\\u0026",
};
const normalizedJsonLd =
typeof jsonLd === "string" ? jsonLd : JSON.stringify(jsonLd);
const escapedJsonLd = normalizedJsonLd.replace(
/[<>&]/g,
(character) => ESCAPE_MAP[character],
);
---
<script is:inline type="application/ld+json" set:html={escapedJsonLd} />