[UPDATED SOLUTION]
First of all, I have seen new documentation section about structured data in Next js: Use Schema.org with Next.js - Documentation - Prismic
That's great!
On my hand, I have twisted a bit the documentation to make it work:
- I have created a component named StructuredData:
import Head from 'next/head';
import Script from "next/script";
export default function StructuredData({ data }) {
return (
<Script
id="app-ld-json"
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(data, null, "\t"),
}}
/>
);
}
- Then I import this component in the targeted custom type:
import StructuredData from "../components/seo/StructuredData";
- I create a variable named schema that render the markup:
// Custom version
const schema = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: page.data.questions.map((question) => ({
"@type": "Question",
name: prismicH.asText(question.question),
acceptedAnswer: prismicH.asText(question.answer),
})),
};
- Then in the return section of the custom type, i pass the schema const to the StructuredData Component, here's the full code of the custom type:
import React from "react";
import Head from "next/head";
import Hero from "../components/ui/PillarPages/Hero";
import { SliceZone } from "@prismicio/react";
import * as prismicH from "@prismicio/helpers";
import { createClient } from "../prismicio";
import { components } from "../slices";
import { useRouter } from "next/router";
import StructuredData from "../components/seo/StructuredData";
// FAQ structured data to be done
const Page = ({
metaTitle,
metaDescription,
ogImage,
page,
title,
upperTitle,
description,
}) => {
const router = useRouter();
const currentRoute = router.pathname;
// Custom version
const schema = {
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: page.data.questions.map((question) => ({
"@type": "Question",
name: prismicH.asText(question.question),
acceptedAnswer: prismicH.asText(question.answer),
})),
};
return (
<React.Fragment>
<StructuredData data={schema} />
<Head>
<title>{metaTitle}</title>
<meta name="description" content={metaDescription} />
{/* <!-- Twitter Card data --> */}
<meta name="twitter:card" content="summary" />
{/* <meta name="twitter:site" content="@publisher_handle" /> */}
<meta name="twitter:title" content={metaTitle} />
<meta name="twitter:description" content={metaDescription} />
{/* <meta name="twitter:creator" content="@author_handle" /> */}
{/* <-- Twitter Summary card images must be at least 120x120px --> */}
{ogImage && <meta name="twitter:image" content={ogImage} />}
{/* <!-- Open Graph data --> */}
<meta property="og:title" content={metaTitle} />
<meta property="og:type" content="website" />
<meta property="og:url" content={currentRoute} />
{ogImage && <meta property="og:image" content={ogImage} />}
<meta property="og:description" content={metaDescription} />
<meta property="og:site_name" content="Dataai Jobs" />
</Head>
{page.data.uppertitle && page.data.title && page.data.description && (
<Hero upperTitle={upperTitle} title={title} description={description} />
)}
<SliceZone slices={page.data.slices} components={components} />
</React.Fragment>
);
};
export default Page;
export async function getStaticProps({ params, previewData }) {
const client = createClient({ previewData });
const page = await client.getByUID("pillar_page", params.uid);
return {
props: {
metaTitle: page.data.meta_title,
metaDescription: page.data.meta_description,
ogImage: page.data.og_image.url,
page: page,
title: page.data.title,
upperTitle: page.data.uppertitle,
description: page.data.description,
},
};
}
export async function getStaticPaths() {
const client = createClient();
const pages = await client.getAllByType("pillar_page");
return {
paths: pages.map((page) => prismicH.asLink(page)),
fallback: false,
};
}
As I am a Junior Developer, I am sure that there is a DRY way of doing it.
For this first iteration, I am just wondering if there's a way for me to improve the front display when the "answer" of the FAQ has multiple paragraphs or bullet points.
Thanks for the help!