Adding SEO fields to your project
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.
Here's how you can organize your SEO fields:
import { defineField, defineType } from "sanity";
export const post = defineType({
name: "post",
type: "document",
fields: [
// ... Previous fields
defineField({
name: "seoHideFromLists",
type: "boolean",
initialValue: false,
}),
defineField({
name: "seoNoIndex",
type: "boolean",
initialValue: false,
}),
],
});
Let's start with the seoHideFromLists
field. This is a boolean field that allows you to hide pages from lists such as post
or projects
pages through querying the seoHideFromLists
field.
const posts = await sanityClient.fetch(
`*[_type == "post" && !seoHideFromLists]`
);
This is how you would query the post
document type, and check if the seoHideFromLists
field is false
.
For example you may want to show a member of the marketing team the new post, without it being visible to the public. It can also work well with documents like webinars, if you want to form-gate them from a public-facing list.
Now let's move onto the seoNoIndex
field. This is a boolean field that allows you to hide pages from search engines by adding a noindex
tag. There are occasions where you may want to hide a page from search engines, for example a dynamic thankyou
page you've created with a page builder shouldn't turn up in a Google search or it may skew your analytics.
Adding Open Graph fields
While metadata
is used to set the title, description, and image for the page when it's displayed via a search engine, open graph
fields are used to set the title, description, and image for the page when it's shared on social media.
// ...previous schema
defineField({
name: 'ogTitle',
type: 'string',
}),
defineField({
name: 'ogDescription',
type: 'text',
rows: 2,
}),
defineField({
name: 'ogImage',
type: 'image',
}),
From experience, the open graph fields are most useful when you're sharing content as part of a marketing campaign via social media platforms. Usually you want to tailor the message for a specific audience. However, following the pattern of overrides and fallbacks, if you don't use them, they will fall back to the title
, description
, and image
fields.
Here's the example of all the different fields in action.
Note: it's possible to fallback through several fields at once, e.g see the open graph fields fallback for:
ogTitle
-> seoTitle
-> title
.
import { Metadata } from "next";
import { client } from "@/lib/sanity/client";
// Fetch post data
async function getPostData(slug: string) {
const post = await client.fetch(
`
*[_type == "post" && slug.current == $slug][0]{
title,
description,
image,
seoTitle,
seoDescription,
seoImage,
seoNoIndex,
seoHideFromLists,
ogTitle,
ogDescription,
ogImage
}
`,
{ slug }
);
return post;
}
// Generate metadata
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPostData(params.slug);
return {
title: post.seoTitle ?? post.title,
description: post.seoDescription ?? post.description,
robots: post.seoNoIndex ? "noindex" : "index",
openGraph: {
title: post.ogTitle ?? post.seoTitle ?? post.title,
description:
post.ogDescription ?? post.seoDescription ?? post.description,
images: post.ogImage ?? post.seoImage ?? post.image,
},
};
}
// post page component
export default async function postPage({ params }) {
const post = await getPostData(params.slug);
if (!post) return null;
return (
<main>
<h1>{post.title}</h1>
{/* ...post content */}
</main>
);
}
The real benefit of this is that any member of the team can now add these fields to their schema, it's a one-size-fits-all solution that can be reused throughout all your document types, and it can be as hands-on or hands-off as you want.
In the next lesson, you will learn how to implement redirects using Next.js and Sanity. The lesson covers creating a redirect system, managing it through your Sanity Studio, and ensuring updates without site rebuilds.