<JsonLd>
Render schema.org structured data as a JSON-LD script block, escaped so that no value can break out of it.
import { JsonLd } from '@gio.js/react';
<JsonLd data={{ '@context': 'https://schema.org', '@type': 'Organization', name: 'Acme', url: 'https://acme.example' }} />Reference
| Prop | Type | Default | Description |
|---|---|---|---|
data (required) | JsonLdData | - | One schema.org object, or an array of them: Record<string, unknown> | ReadonlyArray<Record<string, unknown>>. |
id | string | - | An id for the <script> element, for example to find it in tests. |
The props and data types are exported as JsonLdProps and JsonLdData.
Returns
A <script type="application/ld+json"> element holding JSON.stringify(data), rendered where you place the component. Inside it, <, > and & are written as \u003c, \u003e and \u0026, and the line separators U+2028 and U+2029 as \u2028 and \u2029. Every JSON parser reads the same data, but a string such as a post title containing </script> can no longer end the element and inject markup.
<script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","headline":"Hello \u003c/script\u003e\u003cb\u003ex\u003c/b\u003e \u0026 more"}</script>When JSON.stringify gives nothing (data is undefined at run time), nothing is rendered.
Examples
An article
import type { GetServerSideProps } from '@gio.js/core';
import { JsonLd } from '@gio.js/react';
interface Post {
slug: string;
title: string;
author: string;
publishedAt: string;
}
export const getServerSideProps: GetServerSideProps<{ post: Post }, '/blog/:slug'> = async (ctx) => {
return { props: { post: await posts.get(ctx.params.slug) } };
};
export default function PostPage({ post }: { post: Post }) {
return (
<article>
<JsonLd
data={{
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.title,
author: { '@type': 'Person', name: post.author },
datePublished: post.publishedAt,
url: `https://acme.example/blog/${post.slug}`,
}}
/>
<h1>{post.title}</h1>
</article>
);
}Several items in one block
Pass an array, or one object with an @graph:
<JsonLd
data={{
'@context': 'https://schema.org',
'@graph': [
{ '@type': 'WebSite', name: 'Acme', url: 'https://acme.example' },
{
'@type': 'BreadcrumbList',
itemListElement: [
{ '@type': 'ListItem', position: 1, name: 'Blog', item: 'https://acme.example/blog' },
{ '@type': 'ListItem', position: 2, name: 'Launch notes' },
],
},
],
}}
/>Site-wide data in the root layout
The block is plain HTML, so it works in the server-only root layout too, where it appears on every page.
import type { LayoutProps } from '@gio.js/core';
import { JsonLd } from '@gio.js/react';
export default function RootLayout({ children }: LayoutProps) {
return (
<html lang="en">
<body>
<JsonLd data={{ '@context': 'https://schema.org', '@type': 'Organization', name: 'Acme', logo: 'https://acme.example/logo.png' }} />
{children}
</body>
</html>
);
}Good to know
- The type
application/ld+jsonmakes it a data block the browser never runs, so it needs no CSP nonce, also under a strict Content Security Policy. - The escaping is fixed: it is what makes rendering user content into the block safe.
JSON.stringifyrules apply:Dates become ISO strings,undefinedvalues and functions are dropped, and aBigIntor a circular object throws during the render.- GioJS does not check the vocabulary. Validate the output with a structured-data testing tool.
Related
- Metadata & SEO - titles, Open Graph and structured data.
metadataandgenerateMetadata- the head tags.sitemapandrobots- the other SEO files.
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced. |