go back

Opinionated method for adding SEO to your Nextjs application

Sourav Raveendran

7 min read

2021-10-19

This blog talks about a method for adding proper SEO & Open Graph support for all the pages in your application by wrapping them inside a container.

NextjsSEOmeta tagsOpen Graph

Share this article

FacebookX
Opinionated method for adding SEO to your Nextjs application

What is SEO ?

Search Engine Optimization (SEO) is the process of improving the quality and quantity of website traffic to a website or a webpage from search engines. SEO targets unpaid traffic (natural/organic results) rather than direct traffic or paid traffic. The goal of SEO is to create a strategy that will increase your rankings position in search engine results. The higher the ranking, the more traffic to your site.

Why should i care about SEO ?

SEO is essential for you to get your business in front of your potential customers and clients. This means that when the user have a need and perform a search online, you should make sure that your website get's place on top of the search result so that you can drive more traffic to your website and inturn build your Business/Agency.

What is Open Graph ?

Open Graph is an internet protocol that was originally created by Facebook to standardize the use of metadata within a webpage to represent the content of a pages.

To turn your web pages into graph objects, you need to add basic metadata to your page. You will need to place meta tags in the head of your page we will be using a custom Container component to have a head tag inside it where we will be placing all our meta tags.

Note: Next.js Head component requires the meta tags to have a name attribute.

Some of the most commonly used metatag properties are:

  • title : used to set the title of our page.
  • og:url : complete url for your current page.
  • og:type : type of your object like 'website'.
  • og:image : an image url for your page.
  • description : used to set a description for the page.
  • og:twitter:site : @username for the website used in the card footer.
  • og:twitter:card : the card type, usually 'summary', 'summary_large_image', 'app' or 'player'.
  • og:twitter:title : the title for the page which will be shown on the card.
  • og:twitter:image : cover image for the twitter card.
  • og:twitter:description : the description of the page which will be shown on the card.

If you would like to know more about the different metatags that are supported by Open Graph protocol you can refer Open Graph's website

Getting Started

Let's get started by creating a new Next js project from scratch.

Terminal
npx create-next-app nextjs-seo

Now let's create a Container component which we can use to wrap all our pages with.

Container.jsx
import Head from 'next/head';

function Container(props) {
  const { children, ...customMeta } = props;

  return (
    <>
      <Head>
        {/* we will be placing our meta tags right here */}
      </Head>
      <main>{children}</main>
    </>
  );
}

export default Container;

If you want you can even place your Navbar or Footer components inside the _Container.jsx_file as well so that it acts as a shared layout between pages.

Here customMeta is also getting passed in so that we can change the meta tags for each page individually.

Now let's provide some default info which will used if not custom tags are being provided.

Container.jsx
import Head from 'next/head';

import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';

function Container(props) {
  const { children, ...customMeta } = props;

  const meta = {
    title: 'Page title',
    description: "Page description",
    image: 'url for page image' // eg: https://www.learnnext.blog/img/banner-800x514.png
    type: 'website',
    ...customMeta
  };

  return (
    <>
      <Head>
        <title>{meta.title}</title>
        <meta name="robots" content="follow, index" />
        <meta content={meta.description} name="description" />

        <meta property="og:type" content={meta.type} />
        <meta property="og:site_name" content="Your site name" />
        <meta property="og:description" content={meta.description} />
        <meta property="og:title" content={meta.title} />
        <meta property="og:image" content={meta.image} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:site" content="@yourbusiness" />
        <meta name="twitter:title" content={meta.title} />
        <meta name="twitter.description" content={meta.description} />
        <meta name="twitter:image" content={meta.image} />
        {meta.data && (
          <meta property="article:published_time" content={meta.date} />
        )}      
      </Head>
      <Navbar />
      <main>{children}</main>
      <Footer />
    </>
  );
}

export default Container;

We can use the same data for recurring tags like descripiton tag and twitter:description tag, also we will add the article:published_time tag useful for blogs and article related websites. We've also added the robots tag which allows the search engine crawlers to follow and index our site.

But wait we have not added the og:url tag and the link tag for canonical url, that's because these vary from page to page so we cannot add a hardcoded value to it so instead we will use the next/router to get the path so that we can dynamically set the url's for each page.

Container.jsx
import Head from 'next/head';
import { useRouter } from 'next/router';

import Navbar from '@/components/Navbar';
import Footer from '@/components/Footer';

function Container(props) {
  const { children, ...customMeta } = props;
  const router = useRouter();

  const meta = {
    title: 'Page title',
    description: "Page description",
    image: 'url for page image', // eg: https://www.learnnext.blog/img/banner-800x514.png
    type: 'website',
    ...customMeta
  };

  return (
    <>
      <Head>
        <title>{meta.title}</title>
        <meta name="robots" content="follow, index" />
        <meta content={meta.description} name="description" />

        <meta
          property="og:url"
          content={`https://next-seo.vercel.app${router.asPath}`}
        />
        <link
          rel="canonical"
          href={`https://next-seo.vercel.app${router.asPath}`}
        />

        <meta property="og:type" content={meta.type} />
        <meta property="og:site_name" content="Your site name" />
        <meta property="og:description" content={meta.description} />
        <meta property="og:title" content={meta.title} />
        <meta property="og:image" content={meta.image} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:site" content="@yourbusiness" />
        <meta name="twitter:title" content={meta.title} />
        <meta name="twitter.description" content={meta.description} />
        <meta name="twitter:image" content={meta.image} />
        {meta.data && (
          <meta property="article:published_time" content={meta.date} />
        )}      
      </Head>
      <Navbar />
      <main>{children}</main>
      <Footer />
    </>
  );
}

export default Container;

Now we have a Container with meta tags added in so let's just see how we can use these wrapper for different pages. Let's take the index page for example

Since our index.jsx file is going to be a static file we can use the Container normally by wrapping the items with it _index.jsx_file will use the default value that we've provided.

index.jsx
import Container from '@/components/Container';

function Home() {
  return (
    <Container>
      <div className="mx-auto flex max-w-6xl flex-col h-screen justify-center">
        <div className="p-5 shadow-lg rounded-lg">
          <h2 className="text-white text-4xl font-sans">
            Next SEO
          </h2>
        </div>
      </div>
    </Container>
  )
}

export default Home;

Now let's take the case in which we have a Dynamic route like a blog we would need the meta tags to have the title, image and description of our blog instead of the default value provided, we will pass in the title, description, image etc.. as props to the Container these values can be either fetched from the local MDX files or may be from a CMS where you have uploaded your blogs.

[blog].jsx
import Container from '@/components/Container';


export default function Blog(props) {

  return (
    <Container
      title={`${props.post.title}`}
      description={props.post.summary}
      image={`https://next-seo.vercel.app${props.post.image}`}
      date={new Date(props.post.publishedAt).toISOString()}
      type="article"
    >
      // Rest of your content
      // ... 

    </Container>
  );
}

export async function getStaticPaths() {
  
  // some logic to get all post paths
  return {
    paths: posts.map((p) => ({
      params: {
        blog: path)
      }
    })),
  };
}

export async function getStaticProps({ params }) {
  
  // some logic to get all your posts
  return { props: { ...post } };
}

export default Blog;

And there you go we have successfully set the metatags for a dynamic blog post. If you'd like to see the changes and the tag's that are being appllied during devlopment you can use extensions like SEO minion available for both firefox and chrome, you can inspect your page using this extension to verify the tag's are working correctly.

popular post

Adding Embla Carousel to your NextJS application

8516 views

A detailed walkthrough for setting up and using Embla Carousel in your NextJS application.

Read Article

Using ChartJS a charting library in your NextJS application

4718 views

A detailed walkthrough for setting up and using ChartJS a simple yet flexible charting library in your NextJS application.

Read Article

Auto advancing Carousel component in Next JS.

2178 views

A detailed walkthrough for implementing auto advancing feature for your Embla Carousel.

Read Article

Using Preact with your NextJS application

546 views

A detailed walkthrough for setting up and using Preact a lightweight altrenative to React in your NextJS application.

Read Article