Adding Schema Data to Next.js Sites
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Head from "next/head"; | |
import { site, siteTitle } from "../../config"; | |
function strip(html) { | |
var one = html.replace(/<\/?[^>]+(>|$)/gm, ""); | |
var two = one.replace(/[\r\n]\s*[\r\n]/gm, ""); | |
return two; | |
} | |
const Schema = ({ post }) => { | |
const { | |
title, | |
blurb, | |
featuredImage, | |
date, | |
modified, | |
slug, | |
commentCount, | |
author, | |
ratingCount, | |
ratingAverage, | |
citations | |
} = post; | |
const published = new Date(date); | |
const copyrightYear = published.getFullYear(); | |
let mediaDetails, sourceUrl; | |
if (featuredImage) { | |
sourceUrl = featuredImage.sourceUrl; | |
} | |
const citationsList = citations.map((citation, i) => { | |
return `{ "@type": "CreativeWork", "citation": ${JSON.stringify( | |
citation | |
)} }${i === citations.length - 1 ? "" : ","}\n`; | |
}); | |
const citationsText = citationsList.join(""); | |
const org = `{ "@id": "${site}#organization", "type": "Organization", "name":"${siteTitle}", "logo": { | |
"@type": "ImageObject", | |
"name": "${siteTitle} Logo", | |
"width": "230", | |
"height": "67", | |
"url": "${site}images/logo.png" | |
} }`; | |
return ( | |
<Head> | |
<script type="application/ld+json">{` | |
{ | |
"@context":"https://schema.org/", | |
"@type":"Article", | |
"name":"${title}", | |
${ | |
ratingAverage > 4 | |
? `"aggregateRating": { | |
"@type":"AggregateRating", | |
"ratingValue":${ratingAverage}, | |
"reviewCount":${ratingCount} | |
},` | |
: "" | |
} | |
"about": "${blurb}", | |
"author": { "@type": "Person", "@id": "${site}author/${ | |
author.slug | |
}", "name": "${author.name}" }, | |
${ | |
citationsText.length | |
? `"citation": [ | |
${citationsText} | |
],` | |
: "" | |
} | |
"commentCount": ${commentCount}, | |
"copyrightHolder": { "@id": "${site}#organization" }, | |
"copyrightYear": ${copyrightYear}, | |
"datePublished": "${date}", | |
"dateModified": "${modified}", | |
"description": "${blurb}", | |
"discussionUrl": "${site}articles/${slug}#comments", | |
"editor": { "@id": "${site}author/${author.slug}#author" }, | |
"headline": "${title}", | |
${sourceUrl ? `"image": "${sourceUrl}",` : ""} | |
"inLanguage": "English", | |
"mainEntityOfPage": "${site}articles/${slug}", | |
"publisher": { "@id": "${site}#organization" }, | |
"sourceOrganization": ${org}, | |
"url": "${site}articles/${slug}" | |
} | |
`}</script> | |
</Head> | |
); | |
}; | |
export default Schema; |
This worked great for me, with one change: I had to use dangerouslySetInnerHTML on the script tag to avoid NextJS escaping the text inside, which threw this error in Google's Structured Data Testing Tool: Missing '}' or object member name.
function strip(html) { var one = html.replace(/<\/?[^>]+(>|$)/gm, ""); var two = one.replace(/[\r\n]\s*[\r\n]/gm, ""); return two; }
what's is the use of this function?
function strip is used to replace tags to only put plain text in the schema attribute for example desc:{strip(data)}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Assumes you have call the component with standard WP post data (plus I added some custom fields, like
blurb
), and have called the component via:For more information: https://www.loudnoises.us/adding-schema-data-to-next-js-sites/