inmake DOCS
Docs / Server / Page head & SEO

Page head & SEO

Generated and custom meta tags, which one wins, and the JSON-LD merge.

Page head — SEO, meta tags and JSON-LD#

Every published page's <head> is built from two SeoEntity values: the document's own seo and the site defaults in setup/web.seo. mergeSeo (compose.ts) combines them; headMetaTags (web_renderer) writes the tags. WebSite and the admin's Studio renderer both go through these two, so a preview's head is the published one.

  • Generated tags — og:title (the SEO title, else the document's title / name — without the site's title pattern, which only the <title> carries), description + og:description, og:image, the canonical link, og:url, og:locale + og:locale:alternate (path mode with a known origin).
  • Custom tags — seo.meta: [{key, value}], a list, so a key may repeat (og:image, article:tag). Keys match SEO_META_KEY_PATTERN (a letter, then letters / digits / _ . : -); seoMetaList drops entries with an invalid key or an empty value at render — nothing refuses them on write. seoMetaAttr picks the attribute: the Open Graph namespaces (og, article, book, profile, music, video, product, fb, business, place) render as property=, every other key (twitter:*, robots, author, theme-color) as name=. Values are HTML-escaped. The custom tags follow the generated ones.
  • Precedence per key (case-insensitive), most specific first: the document's meta > the document's SEO title / description / image > the site's meta > the site's SEO fields. A document key drops every site entry under that key and replaces the generated tag. A site key replaces a generated tag only where that tag comes from the site's own SEO fields, so a site og:image fills a page without an SEO image but never beats one. A site key under og:url / og:locale / og:locale:alternate is dropped — those are the page's own. metaReplaces lists the generated keys the renderer leaves out.
  • JSON-LD — pageJsonld merges the site's setup/web.jsonld records with the document's own jsonld (the Structured Data container); where both declare a @type, the document's record wins. One <script type="application/ld+json"> per record; invalid JSON is skipped.

/gen/seo returns a meta list as well (og:type, social og:title / og:description, twitter:card); the admin's SEO card merges it by key.