Lesson
3
Extending the SEO schema types
Now you're setup for success, extend the fields made available to your authors.
Log in to mark your progress for each Lesson and Task
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.
Update your
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.
Update
PAGE_QUERY
and POST_QUERY
to include these new attributes, along with default valuessrc/sanity/lib/queries.ts
export 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[]-> } }}`);
Run the following to regenerate Types now that you've made schema and query changes
npm run typegen
With 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.
src/app/(frontend)/[slug]/page.tsx
// ...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:
Example only
*[_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.
You have 3 uncompleted tasks in this lesson
0 of 3