Logo

Next.js SEO checklist: Start ranking higher on Google

Written by
Blog by Stephan Moerman
Stephan Moerman
Published on
Views
Reading time
9 min read
Next.js SEO checklist: Start ranking higher on Google

Don't let your content fade into the internet abyss. Dive in and make your website a beacon of visibility with the powerful tools and techniques we're about to explore.

It's time to let your website shine!

Understanding the role of Next.js in SEO

In understanding the role of Next.Js in SEO, you'll learn how this server-side rendering framework can significantly boost your website's search engine rankings.

Unlike traditional React, Next.js is built with SEO in mind, enhancing your site's visibility to search engines, which can lead to an increase in organic traffic.

Next.js's impressive performance, such as faster page load times, contributes to improved SEO, which is vital in today's mobile-first indexing era.

Applying Next.js SEO best practices, like pre-rendering and dynamic meta tags, ensures your site is both user and crawler-friendly.

Improving page loading times with Next.Js

By optimizing your website with Next.Js, you'll cut down on page loading times, which is a crucial factor for boosting your SEO ranking. This framework assists in optimizing performance by improving server response time and minimizing render blocking resources. It's all about delivering your content efficiently and swiftly, to keep your users engaged.

You can employ lazy loading techniques, which allow for delayed loading of non-critical resources. This means only the necessary content is loaded immediately, improving initial load times. In addition, Next.Js supports utilizing browser caching. This enables the browser to remember resources it has already loaded, reducing the need for repeated loading.

Together, these strategies significantly enhance your page load times, thereby improving your SEO.

Enhancing crawlability using Next.Js

You'll enhance your website's crawlability when you use Next.Js, making it easier for search engine bots to understand and index your content. Improving crawlability is essential to SEO best practices, and Next.Js is a tool that can help you do just that. It's all about making your website more accessible and user-friendly, not just for your visitors, but for search engine bots too.

Here's how Next.Js helps in enhancing crawlability:

  • Pre-rendering of pages: This optimizes website performance by ensuring speedy delivery of your content.
  • Dynamic routing: Enhances user experience by making your site's navigation more efficient.
  • Mobile optimization: Next.Js follows mobile SEO strategies, making your website's content easily accessible on all devices.

The power of dynamic meta tags in Next.js

Dynamic meta tags aren't just crucial for SEO, but they also help in accurately describing each page's content on your Next.js website. They're the silent heroes behind your website's SEO benefits, aiding search engines in understanding and optimizing content. By dynamically changing these tags, you're not only improving visibility but also ensuring each page is accurately represented.

Consider meta tag optimization as an essential part of your SEO strategy. Using dynamic meta tags in Next.js, you can customize each page's title, description, and even the images that appear in search results. This specificity boosts your site's relevance, directly influencing your rank on Google.

To define dynamic metadata you can use generateMetadata function to fetch metadata that requires dynamic values.

import { Metadata, ResolvingMetadata } from "next";
 
type Props = {
  params: { id: string },
  searchParams: { [key: string]: string | string[] | undefined },
};
 
export async function generateMetadata(
  { params, searchParams }: Props,
  parent?: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = params.id;
 
  // fetch data
  const product = await fetch(`https://yourwebsite.com/products/${id}`).then(
    (res) => res.json()
  );
 
  // optionally access and extend (rather than replace) parent metadata
  const previousImages = (await parent).openGraph?.images || [];
 
  return {
    title: product.title,
    openGraph: {
      images: ["/your-og-image-url.jpg", ...previousImages],
    },
  };
}
 
export default function Page({ params, searchParams }: Props) {}

Incorporating structured data in Next.js

While working on your Next.js project, you'll want to incorporate structured data, and this can significantly boost your SEO performance. Structured data helps search engines understand the content on your page, enhancing your website's visibility and improving your search rankings.

Here's what you need to do:

  • Use schema.org markup for providing detailed information about your website's content.
  • Leverage Next.js's Head component to easily add this structured data.
  • Utilize JSON-LD for structured data, which is a preferred format of Google.

By using structured data for better SEO performance, you're leveraging Next.js for improved search rankings.

With these Next.js SEO techniques, you're not only optimizing your SEO but also enhancing your website's visibility.

Keep improving search engine visibility with Next.js structured data to gain a competitive edge. Here's an example of how to incorporate structured data using the JSON-LD format which can be used by search engines to understand y our content.

The current recommendation by the NExt.js team for JSON-LD is to render structured data as a <script> tag in your layout.tsx or page.tsx components

app/products/[id]/page.tsx
export default async function Page({ params }) {
  const product = await getProduct(params.id);
 
  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "Product",
    name: product.name,
    image: product.image,
    description: product.description,
  };
 
  return (
    <section>
      {/* Add JSON-LD to your page */}
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      {/* ... */}
    </section>
  );
}

Make sure to validate and test your structured data with the Rich Results test for Google.

Dynamic image generation

If you share my blog posts, you'll notice that all the images are roughly the same except for the title and the blog date. This is because I use a dynamic image generation service with the @vercel/og package to generate images for my blog posts.

Here's an example of how I generate my OG images:

app/api/og/route.tsx
import { ImageResponse } from "next/server";
// App router includes @vercel/og.
// No need to install it.
 
export const runtime = "edge";
 
export const GET = async (req: Request) => {
  try {
    const { searchParams } = new URL(req.url);
    const title = searchParams.get("title");
    const date = searchParams.get("date");
    const url = searchParams.get("url") ?? "moerman.dev";
 
    const getTitleFontSize = () => {
      if (title.length > 50) return "text-4xl";
      if (title.length > 40) return "text-5xl";
      return "text-7xl";
    };
 
    return new ImageResponse(
      (
        <div
          tw="w-full h-full flex flex-col px-20 py-12 text-white justify-between"
          style={{
            backgroundImage:
              "url(https://www.moerman.dev/images/og-background.png)",
          }}
        >
          <div tw="text-3xl font-semibold">{date}</div>
          <div tw={`${getTitleFontSize()} mx-auto`}>{title}</div>
          <div tw="flex justify-between items-center">
            <div tw="text-3xl font-semibold">Stephan Moerman</div>
            <div tw="text-3xl font-semibold">{url}</div>
          </div>
        </div>
      ),
      {
        width: 1200,
        height: 630,
      }
    );
  } catch {
    return NextResponse.json(
      {
        error: "Failed to generate image",
      },
      {
        status: 500,
      }
    );
  }
};

By calling /api/og and dynamically adding the meta data. You can now combine this with your dynamic meta data in order to get a unique image for each blog post.

export const metadata = {
  openGraph: {
    title: "Next.js",
    description: "The React Framework for the Web",
    url: "<https://nextjs.org>",
    siteName: "Next.js",
    images: [
      {
        url: `${site.url}/api/og?title=${post.title}&date=${
          post.createdAt.split("T")[0]
        }&url=moerman.dev/blog`,
        width: 1200,
        height: 600,
      },
    ],
  },
};

Adding a sitemap - the easiest way to communicate with Google

Other then the meta tags and performance optimizations, I highly recommend that you integrate a sitemap. You can either build an API manually to fetch routes from your Headless CMS and return them in the right XML format, or use a package such as next-sitemap. Having a sitemap will help Google understand which pages to crawl.

There are two options to add a sitemap to a Next.js site (without using external packages), and if you'd like to learn more about next-sitemap I'd recommend you read their documentation. Let's explore them!

Manually adding a sitemap in Next.js

If you have a simple and static site, you can manually add a sitemap to your Next.js site. Here's how:

  1. Create a sitemap.xml file in the public directory of your project:
public/sitemap.xml
 <xml version="1.0" encoding="UTF-8">
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <url>
       <loc>http://www.website.com/about</loc>
       <lastmod>2023-10-01</lastmod>
     </url>
   </urlset>
   </xml>

Using getServerSideProps to generate a dynamic sitemap

Most websites are more dynamic and have constantly updating content such as a blog, services pages or product pages. In this case, you can use getServerSideProps to generate a dynamic sitemap on-demand.

Lets start by freating a new page inside the pages directory called sitemap.xml.js. This page will be responsible for generating the sitemap by hitting our API to get the data that will allow us to know which pages we want to include in our sitemap. We will then convert this response to write an XML file for /sitemap.xml.

Here's an example of how you could implement this:

pages/sitemap.xml.js
const EXTERNAL_DATA_URL = "https://jsonplaceholder.typicode.com/posts";
 
function generateSiteMap(posts) {
  return `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <!--We manually set the two URLs we know already-->
     <url>
       <loc>https://jsonplaceholder.typicode.com</loc>
     </url>
     <url>
       <loc>https://jsonplaceholder.typicode.com/guide</loc>
     </url>
     ${posts
       .map(({ id }) => {
         return `
       <url>
           <loc>${`${EXTERNAL_DATA_URL}/${id}`}</loc>
       </url>
     `;
       })
       .join("")}
   </urlset>
 `;
}
 
function SiteMap() {
  // getServerSideProps will do the heavy lifting
}
 
export async function getServerSideProps({ res }) {
  // We make an API call to gather the URLs for our site
  const request = await fetch(EXTERNAL_DATA_URL);
  const posts = await request.json();
 
  // We generate the XML sitemap with the posts data
  const sitemap = generateSiteMap(posts);
 
  res.setHeader("Content-Type", "text/xml");
  // we send the XML to the browser
  res.write(sitemap);
  res.end();
 
  return {
    props: {},
  };
}
 
export default SiteMap;

Conclusion

As we wrap up, imagine your website as a vibrant city. Next.js is the map and SEO techniques are the signboards guiding Google's bots—your visitors—through the city.

From lightning-fast loading times to easily crawlable paths, dynamic meta tags to structured data, you'll ensure every corner is discovered.

As Next.js evolves, so will your SEO strategies. Set off on this thrilling journey and watch your website rise in Google's ranks.

Good luck, and let me know if you need any help!