Next.jsでOGP・metaタグを設定する方法

Next.jsでOGP・metaタグを設定する方法になります。

## OGP・meta用のcomponentsを作る
まずは、OGP・metaタグ用のcomponentsを作成します。

### next/headを利用する
作成したcomponentsに`next/head`を利用して、OGP・metaタグを設定します。

```jsx:Seo.jsx
import Head from 'next/head'

const Seo = ({
  pageTitle,
  pageDescription,
  pagePath,
  pageImg,
  pageImgWidth,
  pageImgHeight
}) => {
  const defaultTitle = 'demo'
  const defaultDescription = 'demo'

  const title = pageTitle ? `${pageTitle} | ${defaultTitle}` : defaultTitle
  const description = pageDescription ? pageDescription : defaultDescription
  const url = pagePath
  const imgUrl = pageImg
  const imgWidth = pageImgWidth ? pageImgWidth : 1280
  const imgHeight = pageImgHeight ? pageImgHeight : 640

  return (
    <Head>
      <title>{title}</title>
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      <meta name="description" content={description} />
      <meta property="og:url" content={url} />
      <meta property="og:title" content={title} />
      <meta property="og:site_name" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:image" content={imgUrl} />
      <meta property="og:image:width" content={String(imgWidth)} />
      <meta property="og:image:height" content={String(imgHeight)} />
      <link rel="preconnect" href="https://fonts.gstatic.com" />
      <link
        href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&amp;display=swap"
        rel="stylesheet"
      />
      <link rel="canonical" href={url} />
    </Head>
  )
}

export default Seo

```
OGP・metaタグはページごとに変わることが想定されます。
propsがある場合は、propsの値を設定するようにしています。

## 作成したcomponentsをpageにて読み込む

```jsx
import Seo from '../../components/layout/Seo'

const Home = () => {
  return (
    <Layout>
      <Seo
        pageTitle={'site title'}
        pageDescription={'site description'}
        pageImg={'https://demo.com'}
        pageImgWidth={1280}
        pageImgHeight={960}
      />
    </Layout>
  )
}

export default Home
```
作成したcomponentsをpageにて読み込みます。
その後、設定したいOGP・metaをpropsで渡します。

## Next.jsで動的にOGP・meta設定する場合

APIのデータなどで動的にOGP・metaを書き換えることも可能です。

`getStaticProps`などで取得したデータをそのままpropsで渡すことで設定できます。

```jsx
import Seo from '../../components/layout/Seo'

const Home = ({ post }) => {
  return (
    <Layout>
      <Seo
        pageTitle={post.title}
        pageDescription={post.subTitle}
        pageImg={post.image.src}
        pageImgWidth={post.image.width}
        pageImgHeight={post.image.height}
      />
    </Layout>
  )
}

export default Home

export const getStaticPaths = async () => {
  const paths = await getAllPostsIds()
  return {
    paths,
    fallback: false
  }
}

export const getStaticProps = async (ctx) => {
  const post = await getPostDetails(ctx.params.id)

  if (!post) {
    return {
      notFound: true
    }
  }
  return {
    props: {
      post
    }
  }
}

```

## TypeScriptで記述する場合の例

```tsx:Seo.tsx
import { VFC } from 'react'
import Head from 'next/head'

interface MetaData {
  pageTitle?: string
  pageDescription?: string
  pagePath?: string
  pageImg?: string
  pageImgWidth?: number
  pageImgHeight?: number
}

const Seo: VFC<MetaData> = ({
  pageTitle,
  pageDescription,
  pagePath,
  pageImg,
  pageImgWidth,
  pageImgHeight
}) => {
  const defaultTitle = 'demo'
  const defaultDescription = 'demo'

  const title = pageTitle ? `${pageTitle} | ${defaultTitle}` : defaultTitle
  const description = pageDescription ? pageDescription : defaultDescription
  const url = pagePath
  const imgUrl = pageImg
  const imgWidth = pageImgWidth ? pageImgWidth : 1280
  const imgHeight = pageImgHeight ? pageImgHeight : 640

  return (
    <Head>
      <title>{title}</title>
      <meta name="viewport" content="width=device-width,initial-scale=1.0" />
      <meta name="description" content={description} />
      <meta property="og:url" content={url} />
      <meta property="og:title" content={title} />
      <meta property="og:site_name" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:type" content="website" />
      <meta property="og:image" content={imgUrl} />
      <meta property="og:image:width" content={String(imgWidth)} />
      <meta property="og:image:height" content={String(imgHeight)} />
      <link rel="preconnect" href="https://fonts.gstatic.com" />
      <link
        href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900&amp;display=swap"
        rel="stylesheet"
      />
      <link rel="canonical" href={url} />
    </Head>
  )
}

export default Seo

```