astro-structured-datav2.4.1

Graph mode

Merge all schemas of a page into one @graph block.

By default every component writes its own JSON-LD block. With useGraph: true, all schemas of a page are combined into a single block with an @graph array:

structuredData({ useGraph: true })

Place <SchemaGraph /> once in your base layout where the block should appear, for example at the end of <body>:

---
import { SchemaGraph } from '@casoon/astro-structured-data/components';
---
<body>
  <slot />
  <SchemaGraph />
</body>

<SchemaGraph /> only marks the position. The @graph is filled in by the integration’s middleware after the whole page has rendered, so schema components can sit anywhere: before or after it, and in components that await data. Schemas are collected per request and page, so nothing leaks from one page into the next during a static build. After a middleware rewrite (next('/target') or context.rewrite()), the graph holds the schemas of the rewrite target, the page that actually rendered.

Focus
How graph mode builds the @graph block
How graph mode builds the @graph blockWhile the page renders, every schema component validates its props and registers its schema in a store kept per request and page in Astro.locals; <SchemaGraph /> renders only a placeholder. Once the page has fully rendered, the middleware resolves the page identity: the url of WebPageSchema, otherwise the site URL plus the page path. An article's mainEntityOfPage is pointed to that @id. If the page renders <SchemaGraph /> not exactly once, the build fails. Otherwise the placeholder is replaced by one script of type application/ld+json holding all schemas in an @graph array. With generateMeta, the canonical, Open Graph and Twitter tags of the primary schema, such as an article, are inserted into <head> as well, with the page @id as canonical URL.While the page rendersMiddleware, after renderingHTML responseSchema components → Per-page store: registerPer-page store → Page identity: whole body readPage identity → mainEntityOfPagemainEntityOfPage → Exactly once?Exactly once? → Build fails: noExactly once? → One @graph script: yes<SchemaGraph /> → Exactly once?One @graph script → Meta tags: generateMetaregisterwhole body readnoyesgenerateMetaSchema components – validate propsSchema componentsvalidate propsPer-page store – Astro.localsPer-page storeAstro.locals<SchemaGraph /> – placeholder only<SchemaGraph />placeholder onlyPage identity – WebPage url / site + pathPage identityWebPage url / site + pathmainEntityOfPage – → page @idmainEntityOfPage→ page @idExactly once?Exactly once?Build fails – none or severalBuild failsnone or severalOne @graph script – at the placeholderOne @graph scriptat the placeholderMeta tags – of the primary schemaMeta tagsof the primary schema

Source: src/components/Schema.astro, src/components/SchemaGraph.astro, src/middleware.ts, src/utils/graph.ts, src/utils/meta.ts, src/utils/json-ld.ts

Show chart data
Data for How graph mode builds the @graph block
StepKindLaneLeads to
Schema componentsstartWhile the page rendersPer-page store (register)
Per-page storedata storeWhile the page rendersPage identity (whole body read)
Page identitystepMiddleware, after renderingmainEntityOfPage
<SchemaGraph />stepWhile the page rendersExactly once?
mainEntityOfPagestepMiddleware, after renderingExactly once?
Exactly once?decisionMiddleware, after renderingBuild fails (no), One @graph script (yes)
Build failsendHTML response
One @graph scriptinput or outputHTML responseMeta tags (generateMeta)
Meta tagsendHTML response
Focus
How graph mode builds the @graph block
How graph mode builds the @graph blockWhile the page renders, every schema component validates its props and registers its schema in a store kept per request and page in Astro.locals; <SchemaGraph /> renders only a placeholder. Once the page has fully rendered, the middleware resolves the page identity: the url of WebPageSchema, otherwise the site URL plus the page path. An article's mainEntityOfPage is pointed to that @id. If the page renders <SchemaGraph /> not exactly once, the build fails. Otherwise the placeholder is replaced by one script of type application/ld+json holding all schemas in an @graph array. With generateMeta, the canonical, Open Graph and Twitter tags of the primary schema, such as an article, are inserted into <head> as well, with the page @id as canonical URL.While the page rendersMiddleware, after renderingHTML responseSchema components → Per-page store: registerPer-page store → Page identity: whole body readPage identity → mainEntityOfPagemainEntityOfPage → Exactly once?Exactly once? → Build fails: noExactly once? → One @graph script: yes<SchemaGraph /> → Exactly once?One @graph script → Meta tags: generateMetaregisterwhole body readnoyesgenerateMetaSchema components – validate propsSchema componentsvalidate propsPer-page store – Astro.localsPer-page storeAstro.locals<SchemaGraph /> – placeholder only<SchemaGraph />placeholder onlyPage identity – WebPage url / site + pathPage identityWebPage url / site + pathmainEntityOfPage – → page @idmainEntityOfPage→ page @idExactly once?Exactly once?Build fails – none or severalBuild failsnone or severalOne @graph script – at the placeholderOne @graph scriptat the placeholderMeta tags – of the primary schemaMeta tagsof the primary schema

Source: src/components/Schema.astro, src/components/SchemaGraph.astro, src/middleware.ts, src/utils/graph.ts, src/utils/meta.ts, src/utils/json-ld.ts

Show chart data
Data for How graph mode builds the @graph block
StepKindLaneLeads to
Schema componentsstartWhile the page rendersPer-page store (register)
Per-page storedata storeWhile the page rendersPage identity (whole body read)
Page identitystepMiddleware, after renderingmainEntityOfPage
<SchemaGraph />stepWhile the page rendersExactly once?
mainEntityOfPagestepMiddleware, after renderingExactly once?
Exactly once?decisionMiddleware, after renderingBuild fails (no), One @graph script (yes)
Build failsendHTML response
One @graph scriptinput or outputHTML responseMeta tags (generateMeta)
Meta tagsendHTML response
Focus
How graph mode builds the @graph block
How graph mode builds the @graph blockWhile the page renders, every schema component validates its props and registers its schema in a store kept per request and page in Astro.locals; <SchemaGraph /> renders only a placeholder. Once the page has fully rendered, the middleware resolves the page identity: the url of WebPageSchema, otherwise the site URL plus the page path. An article's mainEntityOfPage is pointed to that @id. If the page renders <SchemaGraph /> not exactly once, the build fails. Otherwise the placeholder is replaced by one script of type application/ld+json holding all schemas in an @graph array. With generateMeta, the canonical, Open Graph and Twitter tags of the primary schema, such as an article, are inserted into <head> as well, with the page @id as canonical URL.Schema components → Per-page store: registerPer-page store → Page identity: whole body readPage identity → mainEntityOfPagemainEntityOfPage → Exactly once?Exactly once? → Build fails: noExactly once? → One @graph script: yes<SchemaGraph /> → Exactly once?One @graph script → Meta tags: generateMetaregisterwhole bodyreadnoyesgenerateMetaSchema components – validate propsSchemacomponentsvalidate propsPer-page store – Astro.localsPer-pagestoreAstro.locals<SchemaGraph /> – placeholder only<SchemaGraph/>placeholder onlyPage identity – WebPage url / site + pathPage identityWebPage url /site + pathmainEntityOfPage – → page @idmainEntityOfPage→ page @idExactly once?Exactly once?Build fails – none or severalBuild failsnone or severalOne @graph script – at the placeholderOne @graphscriptat theplaceholderMeta tags – of the primary schemaMeta tagsof the primaryschema

Source: src/components/Schema.astro, src/components/SchemaGraph.astro, src/middleware.ts, src/utils/graph.ts, src/utils/meta.ts, src/utils/json-ld.ts

Show chart data
Data for How graph mode builds the @graph block
StepKindLeads to
Schema componentsstartPer-page store (register)
Per-page storedata storePage identity (whole body read)
Page identitystepmainEntityOfPage
<SchemaGraph />stepExactly once?
mainEntityOfPagestepExactly once?
Exactly once?decisionBuild fails (no), One @graph script (yes)
Build failsend
One @graph scriptinput or outputMeta tags (generateMeta)
Meta tagsend
Focus
How graph mode builds the @graph block
How graph mode builds the @graph blockWhile the page renders, every schema component validates its props and registers its schema in a store kept per request and page in Astro.locals; <SchemaGraph /> renders only a placeholder. Once the page has fully rendered, the middleware resolves the page identity: the url of WebPageSchema, otherwise the site URL plus the page path. An article's mainEntityOfPage is pointed to that @id. If the page renders <SchemaGraph /> not exactly once, the build fails. Otherwise the placeholder is replaced by one script of type application/ld+json holding all schemas in an @graph array. With generateMeta, the canonical, Open Graph and Twitter tags of the primary schema, such as an article, are inserted into <head> as well, with the page @id as canonical URL.Schema components → Per-page store: registerPer-page store → Page identity: whole body readPage identity → mainEntityOfPagemainEntityOfPage → Exactly once?Exactly once? → Build fails: noExactly once? → One @graph script: yes<SchemaGraph /> → Exactly once?One @graph script → Meta tags: generateMetaregisterwhole bodyreadnoyesgenerateMetaSchema components – validate propsSchemacomponentsvalidate propsPer-page store – Astro.localsPer-pagestoreAstro.locals<SchemaGraph /> – placeholder only<SchemaGraph/>placeholder onlyPage identity – WebPage url / site + pathPage identityWebPage url /site + pathmainEntityOfPage – → page @idmainEntityOfPage→ page @idExactly once?Exactly once?Build fails – none or severalBuild failsnone or severalOne @graph script – at the placeholderOne @graphscriptat theplaceholderMeta tags – of the primary schemaMeta tagsof the primaryschema

Source: src/components/Schema.astro, src/components/SchemaGraph.astro, src/middleware.ts, src/utils/graph.ts, src/utils/meta.ts, src/utils/json-ld.ts

Show chart data
Data for How graph mode builds the @graph block
StepKindLeads to
Schema componentsstartPer-page store (register)
Per-page storedata storePage identity (whole body read)
Page identitystepmainEntityOfPage
<SchemaGraph />stepExactly once?
mainEntityOfPagestepExactly once?
Exactly once?decisionBuild fails (no), One @graph script (yes)
Build failsend
One @graph scriptinput or outputMeta tags (generateMeta)
Meta tagsend

A page with schemas but without <SchemaGraph />, or with more than one, fails the build so no schema goes missing. Without useGraph, <SchemaGraph /> renders nothing.

The block carries the schema.org @context. A different @context set via <Schema>, for example own term mappings, stays on its node as an embedded context, so the data means the same with and without graph mode.

Linking nodes

Nodes in the graph refer to each other by @id. Give the entities others point to an id (WebSiteSchema, OrganizationSchema, LocalBusinessSchema, …) and the main entity of a page one too (ArticleSchema, ProductSchema, EventSchema, RecipeSchema, VideoSchema, SoftwareAppSchema, JobPostingSchema, CollectionPageSchema, FAQSchema, BreadcrumbSchema). The relations take a reference with id or url and a free type:

Component Props
ArticleSchema, RecipeSchema, VideoSchema, SoftwareAppSchema, CollectionPageSchema, WebPageSchema isPartOf, hasPart
ProductSchema isVariantOf, hasVariant, isRelatedTo, isSimilarTo, isAccessoryOrSparePartFor, isConsumableFor
OrganizationSchema, LocalBusinessSchema parentOrganization, subOrganization
EventSchema superEvent, subEvent

ID conventions

  • Page: the page node’s @id is the page URL: the url passed to WebPageSchema, otherwise siteUrl plus the page path. An article’s mainEntityOfPage refers to the same @id, also when WebPageSchema sets url and whichever component renders first, and the canonical link with generateMeta uses it too.
  • Website: give WebSiteSchema an id such as https://example.com/#website and refer to it from WebPageSchema with isPartOf.
  • Organization: set defaultArticlePublisher.id, for example https://example.com/#organization. OrganizationSchema and the publisher of ArticleSchema and WebPageSchema (and the hiring organization of JobPostingSchema) then share that @id. A publisher or organization named via props does not get this @id; pass its own id.

Edit this page on GitHub · Docs for v2.4.1