83 lines
2.7 KiB
TypeScript
83 lines
2.7 KiB
TypeScript
type MediaLike = { url?: string | null } | null | undefined
|
|
|
|
type ArticleJsonLdArgs = {
|
|
/** Article headline (the title). */
|
|
headline: string
|
|
/** Absolute URL of the article. */
|
|
url: string
|
|
description?: string
|
|
/** Cover/hero image. */
|
|
image?: MediaLike
|
|
/** ISO date the article was first published, e.g. '2026-01-15'. */
|
|
datePublished?: string
|
|
/** ISO date of the last modification. Defaults to datePublished. */
|
|
dateModified?: string
|
|
/** Author name (person or org). */
|
|
author?: string
|
|
/** Publisher (usually the site/organization) name. */
|
|
publisherName?: string
|
|
/** Publisher logo (for the Article rich result). */
|
|
publisherLogo?: MediaLike
|
|
/** 'Article' (default), 'BlogPosting', or 'NewsArticle'. */
|
|
type?: 'Article' | 'BlogPosting' | 'NewsArticle'
|
|
}
|
|
|
|
/**
|
|
* Builds Article / BlogPosting JSON-LD (schema.org) for blog posts and articles.
|
|
* Enables article rich results in Google (headline, date, author, image). Pairs
|
|
* with the plugin's content collections (blog/archives).
|
|
*
|
|
* Per-article (each post emits its own), data from the document + panel:
|
|
*
|
|
* import { buildArticleJsonLd } from '@intecion/ipal-kit'
|
|
* const jsonLd = buildArticleJsonLd({
|
|
* headline: post.title, url: postUrl, description: post.excerpt,
|
|
* image: post.coverImage, datePublished: post.publishedAt,
|
|
* author: post.author, publisherName: settings.siteName,
|
|
* publisherLogo: settings.logo, type: 'BlogPosting',
|
|
* })
|
|
*
|
|
* All data from the document/panel — nothing hardcoded. Google requires headline
|
|
* and dates for the rich result; supply them from the post's real fields.
|
|
*/
|
|
export function buildArticleJsonLd({
|
|
headline,
|
|
url,
|
|
description,
|
|
image,
|
|
datePublished,
|
|
dateModified,
|
|
author,
|
|
publisherName,
|
|
publisherLogo,
|
|
type = 'Article',
|
|
}: ArticleJsonLdArgs) {
|
|
const imageUrl = image?.url
|
|
const logoUrl = publisherLogo?.url
|
|
|
|
const abs = (u: string | null | undefined): string | undefined =>
|
|
u ? (u.startsWith('http') ? u : `${url.split('/').slice(0, 3).join('/')}${u}`) : undefined
|
|
|
|
return {
|
|
'@context': 'https://schema.org',
|
|
'@type': type,
|
|
headline,
|
|
url,
|
|
mainEntityOfPage: { '@type': 'WebPage', '@id': url },
|
|
...(description ? { description } : {}),
|
|
...(imageUrl ? { image: abs(imageUrl) } : {}),
|
|
...(datePublished ? { datePublished } : {}),
|
|
...(dateModified || datePublished ? { dateModified: dateModified ?? datePublished } : {}),
|
|
...(author ? { author: { '@type': 'Person', name: author } } : {}),
|
|
...(publisherName
|
|
? {
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
name: publisherName,
|
|
...(logoUrl ? { logo: { '@type': 'ImageObject', url: abs(logoUrl) } } : {}),
|
|
},
|
|
}
|
|
: {}),
|
|
}
|
|
}
|