Extending the SEO schema types
In the first lesson, you learned how to add some basic SEO fields to your schema. Now you're going to kick it up a notch with Open Graph fields and more granular controls over displaying documents in lists.
seoType schema type to include description, image and a noIndex fieldimport { defineField, defineType } from "sanity";
export const seoType = defineType({ name: "seo", title: "SEO", type: "object", fields: [ defineField({ name: "title", description: "If provided, this will override the title field", type: "string", }), defineField({ name: "description", type: "text", }), defineField({ name: "image", type: "image", options: {hotspot: true} }), defineField({ name: "noIndex", type: "boolean", }), ],});You may wish to have separate title and description fields for Open Graph properties. But in this course you'll re-use these values.
PAGE_QUERY and POST_QUERY to include these new attributes, along with default valuesexport const PAGE_QUERY = defineQuery(`*[_type == "page" && slug.current == $slug][0]{ ..., "seo": { "title": coalesce(seo.title, title, ""), "description": coalesce(seo.description, ""), "image": seo.image, "noIndex": seo.noIndex == true }, content[]{ ..., _type == "faqs" => { ..., faqs[]-> } }}`);npm run typegenWith these fields now present in your schema types and queries, you can now render even more metadata in your route.
Note in the code below how the Open Graph image reuses the urlFor helper function to generate an image the correct width and height–and will also respect crop and hotspot data.
The value for noindex we only include in the metadata if it is set to true.
// ...the rest of your route
export async function generateMetadata({ params,}: RouteProps): Promise<Metadata> { const { data: page } = await getPage(params);
if (!page) { return {} }
const metadata: Metadata = { title: page.seo.title, description: page.seo.description, };
if (page.seo.image) { metadata.openGraph = { images: { url: urlFor(page.seo.image).width(1200).height(630).url(), width: 1200, height: 630, }, }; }
if (page.seo.noIndex) { metadata.robots = "noindex"; }
return metadata;}Don't forget to update your individual post route as well.
Having a page set to noIndex typically means that you want the published document to exist as a route in your application—but you don't want it included in search results. Either on search engine results or within your website.
Nothing needs to change now with your page type documents, but if you were to include these fields in your post type documents, you'd likely want to update any query that looks up and renders many posts to exclude results where noIndex is true. For example:
*[_type == "post" && seo.noIndex != true]You'll see an example of this later in the lesson Build a dynamic sitemap.
Now your Sanity Studio and application are capable of authoring, querying and rendering complex metadata for the most common SEO needs. You can continue to extend these fields for any other metadata requirements.
In the following lesson you'll take on another major SEO concern: redirects.