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.
| prop | type | default | required | description |
|---|---|---|---|---|
jsonLd | Record<string, unknown> | string | - | Yes | JSON-LD payload as either a pre-serialized string or a plain object. Object values are serialized internally with JSON.stringify(...) before rendering. |
Examples
Section titled “Examples”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>Complete
Section titled “Complete”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>Decisions Made
Section titled “Decisions Made”Accepts both object and string input
Section titled “Accepts both object and string input”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.
Emits a single inline script tag
Section titled “Emits a single inline script tag”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.
Source code
Section titled “Source code”---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} />