Edupala

Comprehensive Full Stack Development Tutorial: Learn Ionic, Angular, React, React Native, and Node.js with JavaScript

Nextjs generateMetadata: A Comprehensive Guide

Next.js, a powerful React framework for building web applications, offers several features to improve SEO and optimise the user experience. One such feature is the Nextjs generateMetadata function, which is used to dynamically generate metadata for your web pages. Metadata includes elements such as the page title, description, and other meta tags that are critical for search engine optimisation (SEO) and social media sharing.

In this tutorial, we will explore how to use generateMetadata in Next.js, when to use it, and its benefits.

What is NextjsgenerateMetadata?

The generateMetadata function in Next.js allows you to fetch and generate metadata dynamically for your pages. This function is particularly useful for pages that need to display unique metadata based on route parameters or fetched data.

The generateMetadata function in Next.js is particularly useful for dynamically generating metadata for pages that depend on route parameters or fetched data, such as blog posts or product pages with unique IDs. This dynamic generation ensures that each page has specific and relevant metadata, which is beneficial for SEO (Search Engine Optimization).

Tutorial on generateMetadatain Next.js

Next.js, a popular React framework, provides robust features for server-side rendering, static site generation, and client-side rendering. One of the notable features in Next.js is the generateMetadata function, which allows you to define metadata for your pages. This tutorial will cover the usage, implementation, and advantages of generateMetadata in the latest version of Next.js as of July 2024.

What is NextjsgenerateMetadata?

generateMetadata is a function in Next.js used to dynamically generate metadata for your pages. This includes information like the page title, description, open graph tags, and other HTML meta tags. Metadata is crucial for SEO (Search Engine Optimization), social media sharing, and enhancing the user experience.

Why use generateMetadata?

  1. SEO Benefits: Properly defined metadata improves the visibility of your website in search engine results.
  2. Dynamic Content: Generate metadata based on dynamic content, making your site more relevant to users.
  3. Social Media Optimization: Ensures that your pages are properly represented when shared on social media platforms.
  4. Improved User Experience: Providing accurate titles and descriptions helps users understand the content of your pages.

When to use generateMetadata?

  • Dynamic Pages: Use generateMetadata for pages that display dynamic content such as blog posts, products, or user profiles.
  • SEO Optimization: When you want to improve SEO by providing unique metadata for each page.
  • Social Sharing: To enhance the appearance of your pages when shared on social media platforms.

Static vs. Dynamic Metadata in Next.js

Metadata in Next.js helps search engines and social media platforms understand your content. It can be either static or dynamic, each serving different purposes:

Static Metadata

  • Fixed Information: Static metadata remains the same across the entire page or content.
  • One-time Definition: Defined once and does not change based on conditions or parameters.
  • Common Use: Often used for general page information like site-wide SEO settings or default metadata for pages that don’t change often.

Using Head Component Directly in Page Components

Example of page with Static metadata, Defined in a static site or page that doesn’t require frequent updates. To provide specific metadata for each page, we should place the Head component directly within each page component like below, even we have shared layout component with header.

export default function AboutPage() {
  return (
    <Head>
      <title>About Us</title>
      <meta name="description" content="Learn more about our company." />
    </Head>
   {/* Page content */}
  );
}
Understanding the Problem

In Next.js, it’s common to share components like headers and footers across multiple pages. The challenge lies in managing metadata within these shared components of the Layout.tsx

Nextjs generateMetadata
Solution: Using Head Component in Layout

Next.js provides a Layout component structure to encapsulate shared elements. We can place the Head component within the layout to manage metadata for all pages that use that layout. If some of your page need some different metadata then you can take our first static solution by importing Head directly to that page.

Or we have better option below, by using combining both static and dynamic.

// pages/about.js
import Layout from '../components/Layout';
import Head from 'next/head';

export default function AboutPage() {
  return (
    <Layout>
      <Head>
        <title>About Us</title>
        <meta name="description" content="Learn more about our company." />
      </Head>
      {/* Page content */}
    </Layout>
  );
}

Dynamic Metadata

  • Variable Information: Dynamic metadata can change based on specific conditions, parameters, or fetched data.
  • Contextual Adjustments: Allows metadata to be customized for different scenes, products, or blog posts.
  • Enhanced SEO: Provides more relevant and precise metadata for each page, improving search engine indexing and social media shareability.

Dynamic Metadata Example for all blogpost or all products using its id

Let generate blog post dynamic Metadata for each blog post using ID, or we can used in a products page/[slug] where metadata changes based on the product ID:

Here’s a step-by-step guide to implementing generateMetadata in your Next.js application. In this case we are putting generateMetadata directly on the page it self instead of layout that can shared with all page within that folder.

Step 1: Create a Next.js Project

If you haven’t already, create a new Next.js project using the following command:

codenpx create-next-app@latest my-nextjs-app
cd my-nextjs-app
Step 2: Setup a Page Component

Let’s assume we have a page at app/blogs/[slug]/page.tsx or app/products/[slug]/page.tsx that displays individual blog posts or product detail. We want to generate metadata for each blog post based on its content.

export async function generateMetadata({ params }) {
  const { id } = params;
  const blog = await fetch(`https://api.example.com/blogs/${id}`).then(res => res.json());

  return {
    title: blog.name,
    description: blog.description,
    openGraph: {
      title: blog.name,
      description: blog.description,
      images: [{ url: blog.image }],
    },
    alternates: {      
      canonical: `${getCanonicalUrl()}/products/${params.slug}`,    
    },  
OR
    alternates: {            
      canonical: `https://somedomain.com/products/${params.slug}`,             
     }, 
   };
}

export default function BlogPage({ Blog }) {
  // Page component code here
}

Or with supabase, we can have full code as below here

Instead of adding the base URL directly in the generateMetadata or by calling getCanonicalUrl() from the utils/index.ts file, we can use metadataBase. This is a convenience option to set a base URL prefix for metadata fields that require a fully qualified URL.

export const getCanonicalUrl = () => {
  return process.env.NODE_ENV !== "production"
    ? "http://localhost:3000"
    : "https://nextjs-crash-course-theta.vercel.app";
};

export const getImageUrl = (imageUrl: string) => {
  return `${process.env.NEXT_PUBLIC_SUPABASE_URL}/storage/v1/object/public/storage/${imageUrl}`;
};

No in canonical we don’t need to add baseURL on canonical property, as shown by selecting color red on the where we edit the code.

import { createClient } from "@/supabase/client";
import { getCanonicalUrl, getImageUrl } from "@/utils";
import { Metadata, ResolvingMetadata } from "next";
import Image from "next/image";
import { notFound } from "next/navigation";

export const revalidate = 0;

type Props = {
  params: { slug: string };
  searchParams: { [key: string]: string | string[] | undefined };
};

// For dynamic meta data for SEO
export async function generateMetadata(
  { params }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  const slug = params.slug;

  const supabase = createClient();
  const { data: post } = await supabase
    .from("blog-posts")
    .select()
    .eq("id", slug)
    .single();

  if (!post) {
    return { title: "", description: "" };
  }

  return {
    metadataBase: new URL(getCanonicalUrl()),    
    title: post.title || "", // Optional chaining for safety
    description: post.content.slice(0, 160) || "", // Summary for description
    openGraph: {
      images: [getImageUrl(post.imageUrl)],
    },
    alternates: {
      canonical: `/blog/${params.slug}`,
    },
  };
}

export async function generateStaticParams() {
  const supabase = createClient();
  const { data: posts } = await supabase.from("blog-posts").select("id");

  if (!posts) { return [];}

  return posts.map((post) => ({
    params: { slug: post.id },
  }));
}

export default async function Page({ params }: Props) {
  const supabase = createClient();
  const { data } = await supabase.from("blog-posts").select().eq("id", params.slug).single();

  if (!data) {
    notFound();
  }

  return (
    <div className="px-12 py-12 max-w-7xl mx-auto min-h-screen">
 ....
    </div>
  );
}

Dynamic Metadata using generateMetadata on shared layout file

To generate dynamic metadata for all the new upload blog or product, let create folder upload inside the blogs inside we have folder /[slug] and upload . We have already discuss about the generating dynamic metadata on single page in previous section. Now lets create dynamic metadata in blogs/upload having two files layout.tsx and page.tsx. We only need to used layout.tsx file to add dynamic metadata.

import { getCanonicalUrl } from "@/utils";
import { Metadata } from "next";

export const metadata: Metadata = {
  metadataBase: new URL(getCanonicalUrl()),
  title: "Easy Sell - Upload",
  description: "Upload your files easily using Easy Sell",
  alternates: {
    canonical: "/",
  },
  openGraph: {
    images: ["/assets/og-image.png"],
  },
};

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    // Do what you need to do
    <>{children}</>
  );
}

In conclusion, generateMetadata in Next.js is a powerful tool for dynamically creating metadata, optimizing SEO, and improving social sharing. By using it correctly, you can ensure that your web application provides a better user experience and ranks higher in search engine results. Check offical Next.js documentation on generateMetadata.

Related blog post on nextjs

  1. Mastering generateStaticParams() in Next.js 14: Boost Performance and SEO
  2. Understanding Nextjs Server Actions and Mutations 2024
  3. Understanding Routing in Next.js
  4. Understanding Prefetching in Next.js
  5. Data Fetching and Caching in Next.js 
Nextjs generateMetadata: A Comprehensive Guide

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top