( Metadata in NEXTJS ) : Static MetaData, Dynamic MetaData

Here, I am using App Router.

Static Metadata

// layout.js

export const metadata = {
  title: "Static Page Title",
  description: "This is a static page description"
}

export default function Page() {}

Dynamic MetaData using generateMetadata

Dynamic metadata allows you to generate metadata based on dynamic data, such as route parameters or fetched data.

Example:

// [dynamic-route]/page.jsx

export async function generateMetadata({ params }) {
  return {
    title: product.title,
    description: product.description,
    
    openGraph: {
      title: product.title,
      description: product.description,
      url: product.url,
      images: [
        {
          url: product.imageUrl,
          width: 800,
          height: 600,
          alt: product.title,
        }
      ],
      type: 'website'
    },
    
    twitter: {
      card: 'summary_large_image',
      title: product.title,
      description: product.description,
      images: [product.imageUrl]
    }
  };
}
    
  }
}

export default function Page({ params, searchParams }) {}

note: post is an object containing the information of a blog post.

NOTES:

  • Use Static Metadata When Possible: If metadata doesn’t depend on runtime information, prefer static metadata for simplicity.
  • Dynamic Metadata for Dynamic Data: Use generateMetadata for routes where metadata depends on dynamic data or needs to extend parent metadata.

DYNAMIC METADATA using next/head

For example, if you are building a blog and want each post to have its own title — you can do this with dynamic Metadata.

import Head from 'next/head'

export default function BlogPost({ post }) {    // post is an object that contains information about the blog post.
  return (
    <>
      <Head>
        <title>{post.title} | My Blog</title>
        <meta name="description" content={post.description} />
        <meta property="og:title" content={post.title} />
        <meta property="og:description" content={post.description} />
        <meta property="og:image" content={post.image} />
        <meta property="og:type" content="article" />
        <meta property="og:url" content={`https://my-site.com/blog/${post.slug}`} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:title" content={post.title} />
        <meta name="twitter:description" content={post.description} />
        <meta name="twitter:image" content={post.image} />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="UTF-8" />
      </Head>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </>
  )
}

Import the Head component

Next.js provides a Head component that you can use to add elements to the <head> of your HTML document.

import Head from 'next/head'

Use the Head component

You can use the Head component in your component as follows:

<Head>
  ......................
  ....ALl codes here....
  ......................
</Head>

For Meta Title and Meta Description

import Head from 'next/head'

export default function BlogPost({ post }) {    // post is an object that contains information about the blog post.
  return (
    <>
      <Head>
        <title>{post.title} | My Blog</title>
        <meta name="description" content={post.description} />
      </Head>
      
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </>
  )
}

For OpenGraph Title, Description & Image

import Head from 'next/head'

export default function BlogPost({ post }) {    // post is an object that contains information about the blog post.
  return (
    <>
      <Head>
        <title>{post.title} | My Blog</title>
        <meta name="description" content={post.description} />
        <meta property="og:description" content={post.description} />
        <meta property="og:image" content={post.image} />
        <meta property="og:type" content="article" />
        <meta property="og:url" content={`https://my-site.com/blog/${post.slug}`} />
      </Head>
      
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </>
  )
}

For Twitter Title, Description & Image

import Head from 'next/head'

export default function BlogPost({ post }) {    // post is an object that contains information about the blog post.
  return (
    <>
      <Head>
        <title>{post.title} | My Blog</title>
        <meta name="description" content={post.description} />
        <meta property="og:description" content={post.description} />
        <meta property="og:image" content={post.image} />
        <meta property="og:type" content="article" />
        <meta property="og:url" content={`https://my-site.com/blog/${post.slug}`} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:title" content={post.title} />
        <meta name="twitter:description" content={post.description} />
        <meta name="twitter:image" content={post.image} />
      </Head>
      
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </>
  )
}

Last 2 Fields (Meta Viewport & Meta charset) (Note: These are Default Fields by NextJS)

There are two default meta tags given by NEXTJS — that are always added even if a route doesn’t define metadata:

  • The meta charset tag sets the character encoding for the website.
  • The meta viewport tag sets the viewport width and scale for the website to adjust for different devices.
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

Good to know: You can overwrite the default viewport meta tag.

Additional Optimisations:

Previews and Rich Snippets

Consider using structured data (JSON-LD) to improve rich snippets in search results.