Part 37: Dynamic Metadata in Next.js for SEO-Friendly Review Pages

[App] Metadata

Dynamic Metadata in Next.js for SEO-Friendly Review Pages

When building a dynamic website, it’s important to ensure that each page has the appropriate metadata for better SEO and user experience. In this post, we’ll discuss how to set dynamic titles for individual review pages in a Next.js application. This ensures that each review has its own SEO-friendly title instead of a generic default.

Setting Up Default Metadata in RootLayout

First, let’s ensure that we have a default title and template set in our RootLayout. This allows us to append the website name to any page-specific title automatically.

// app/layout.jsx
import { exo2, orbitron } from './fonts';
import './globals.css';

export const metadata = {
  title: {
    default: 'Indie Gamer',
    template: '%s | Indie Gamer',
  },
};

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={`${exo2.variable} ${orbitron.variable}`}>
      <body>{children}</body>
    </html>
  );
}

With this setup, any page title will follow the format "Page Title | Indie Gamer".

Dynamic Titles for Review Pages

While the default title is useful, it doesn’t suffice for pages like individual reviews that need unique titles based on their content. For these dynamic pages, we need to generate the metadata after fetching the review data.

Using generateMetadata for Dynamic Titles

Next.js provides a generateMetadata function that allows us to dynamically set metadata based on the data we fetch. This function can run asynchronous code, making it ideal for fetching review data before setting the metadata.

Step-by-Step Implementation

  1. Create the generateMetadata function: This function will receive the props which include parameters like the slug that identifies the review.

  2. Fetch the review data: Use the slug to fetch the specific review data from your data source.

  3. Set the title dynamically: Return a metadata object with the dynamic title based on the fetched review data.

Here’s how you can implement it:

// app/reviews/[slug]/page.jsx
import Heading from '@/components/Heading';
import { getReview } from '@/lib/reviews';

// Generate metadata dynamically based on review data
export async function generateMetadata({ params: { slug } }) {
  const review = await getReview(slug);
  return {
    title: review.title,
  };
}

export default async function ReviewPage({ params: { slug } }) {
  const review = await getReview(slug);
  console.log('[ReviewPage] rendering', slug);
  return (
    <div>
      <Heading />
      <article>
        <h1>{review.title}</h1>
        <p>{review.content}</p>
      </article>
    </div>
  );
}

Explanation

  • Fetching the Review Data: The getReview function fetches review data based on the slug.

  • Setting Metadata: The generateMetadata function uses the fetched review data to set the page title dynamically.

  • Rendering the Review Page: The ReviewPage component fetches the review data and renders it on the page.

Logging Props for Debugging

If you’re curious about what the props contain, you can log them:

export async function generateMetadata({ params }) {
  console.log('generateMetadata params:', params);
  const review = await getReview(params.slug);
  return {
    title: review.title,
  };
}

When you load a review page, the server logs will show the params object, which includes the slug.

Verifying the Dynamic Titles

To verify that the titles are set correctly:

  1. Open a Review Page: Navigate to a review page in your browser.

  2. Check the Browser Tab: The title should now reflect the specific review title followed by the website name, e.g., "Hellblade | Indie Gamer".

  3. Test Different Reviews: Navigate to different reviews and observe the titles updating accordingly.

Example Review Titles

  • Hellblade: "Hellblade | Indie Gamer"

  • Hollow Knight: "Hollow Knight | Indie Gamer"

  • Stardew Valley: "Stardew Valley | Indie Gamer"

Extending Metadata

Beyond setting the title, you can also set other metadata properties dynamically, such as description, keywords, etc. Here’s an example:

export async function generateMetadata({ params: { slug } }) {
  const review = await getReview(slug);
  return {
    title: review.title,
    description: review.description,
    keywords: review.keywords.join(', '),
  };
}

Conclusion

By leveraging Next.js’s generateMetadata function, you can dynamically set metadata for each review page based on the specific content. This approach enhances the SEO of your site and provides a better user experience with meaningful and context-specific titles.

Feel free to share your thoughts or ask questions in the comments section below. We’d love to hear about your experiences and any challenges you faced while setting up dynamic metadata for your Next.js application. Happy coding!

Last updated