Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mckhames/b4f3ef74571f64e62bb0c3a980054ad0 to your computer and use it in GitHub Desktop.
Save mckhames/b4f3ef74571f64e62bb0c3a980054ad0 to your computer and use it in GitHub Desktop.
How To Generate Schema-Org JSON-LD + OpenGraph Metadata with NextJS and Wordpress
//This assumes NextJS with wordpress backend that has wpGraphql plugin installed.
//We're filling in all required metadata with standard wordpress fields. Recommend using ACF or equivalent to finetune the different
//fields, as ours will contain a few duplicates (i.e. category, subject, etc)
import Head from "next/head";
import { format } from "date-fns";
export default function MetadataComponent({ post }) {
//create function to strip html from content so that article body can be added to schema
function strip(html) {
var one = html.replace(/<\/?[^>]+(>|$)/gm, "");
var two = one.replace(/[\r\n]\s*[\r\n]/gm, "");
return two;
}
//create function to grab your tags from the post object and return them as a comma-separated string: keywords!
const getKeywords = () => {
if (post.tags) {
let myTags = [];
post.tags.edges.forEach((element) => myTags.push(element.node.name));
let keywords = myTags.join();
return keywords;
} else return "";
};
//get the word count for the article
const getWordCount = (body) => {
if (body) {
// strip html
let strippedHTML = strip(body);
//return the number of words, determined by counting the total spaces in the body
return strippedHTML.split(" ").length;
} else return "";
};
const articleBody = strip(post.content);
// setting some constants...you could & should use environment variables and/or ACF for this...
// if your org and site name are not the same, use schema.org/organization to understand what will work best in your situation.
const organizationName = "Example Site / Organization Name";
const baseUrl = "https://example.com/blog/posts/";
const baseAuthorUrl = "https://example.com/blog/authors/";
//generate author info
//note that metadataAuthor includes email, which you may want to leave off.
const metadataAuthor = `${post.author.node.firstName} ${post.author.node.lastName}, ${post.author.node.email}`;
// adjust accordingly
// ...the author routes in this example are as such: https://example.com/blog/authors/[authorFirstName-authorLastName]
const authorUrl = `${baseAuthorUrl}${post.author.node.firstName.toLowerCase()}-${post.author.node.lastName.toLowerCase()}`;
const schemaOrgAuthor = `${post.author.node.firstName} ${post.author.node.lastName}`;
// generate current url
// ...this example generates something like: https://example.com/blog/posts/[slug]
// ...the slug is set in wordpress.
const currentUrl = `${baseUrl}${post.slug}`;
//general metadata setup with props
const title = `${post.title}`;
// we're assuming here that the first catgory listed is the "primary" category
// ... we're listing that category as the "subject" & "topic"
// ... good example of when creating & fetching custom fields could come in handy.
const subject = `${post.categories.edges[0].node.name}`;
const topic = `${subject}`;
const category = `${topic}`;
const description = `${post.excerpt}`;
const summary = `${description}`;
const publishedDate = `${format(new Date(post.date), "PPPppp")}`; // April 29th, 1453 at 9:30am GMT-4
const revisedDate = `${format(new Date(post.modified), "PPPppp")}`;
const keywords = `${getKeywords()}`;
const wordCount = `${getWordCount(post.content)}`;
const featuredImageUrl = `${post.featuredImage.node.sourceUrl}`;
const lang = "EN";
const locale = "en_US";
const fbPageId = "YourFbPageId";
return (
<Head>
{/** HTML META + OPENGRAPH TAGS **/}
<link rel="canonical" href={currentUrl} />
<meta name="title" property="og:title" content={title} />
<meta property="og:type" content="article" />
<meta
name="description"
property="og:description"
content={description}
/>
<meta name="author" content={metadataAuthor} />
<meta property="og:author" content={authorUrl} />
<meta name="keywords" content={keywords} />
<meta name="image" property="og:image" content={featuredImageUrl} />
<meta name="url" property="og:url" content={currentUrl} />
<meta name="subject" content={subject} />
<meta name="copyright" content={organizationName} />
<meta name="language" content={lang} />
<meta property="og:locale" content={locale} />
<meta name="robots" content="index,follow" />
<meta name="revised" content={revisedDate} />
<meta name="topic" content={topic} />
<meta name="summary" content={summary} />
<meta name="category" content={category} />
<meta name="fb:page-id" content={fbPageId} />
{/** Now for the fun stuff...SCHEMA-ORG/JSON-LD Implementation **/}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: `
{
"@context" : "http://schema.org",
"@type" : "Article",
"name" : "${title}",
"headline": "${title}",
"wordCount": "${wordCount}",
"author" : {
"@type" : "Person",
"name" : "${schemaOrgAuthor}",
"url": "${authorUrl}"
},
"keywords" : "${keywords}",
"datePublished" : "${publishedDate}",
"dateCreated" : "${publishedDate}",
"dateModified": "${revisedDate}",
"image" : "${featuredImageUrl}",
"articleSection" : "${subject}",
"articleBody" : "${articleBody}",
"url" : "${currentUrl}",
"publisher" : {
"@type" : "Organization",
"name" : "${organizationName}"
}
}
`,
}}
/>
</Head>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment