検索エンジン最適化(SEO)のためのCSR/SSRにおけるメタ情報の導入

どうも、ピルクルは体に良さそうなのでジュースにはカウントしない方向でやらせてもらってる者です。

最近、参画中のスタートアップで、WebサイトのSEO対策としてメタ情報を導入するチケットを対応したので、Next.jsでCSR/SSRなページへのSEOタグの設定方法について紹介します。

## 目次
1. SEOタグとは
1. SSRを用いて動的にSEOタグを設定する
1. 補足：SSRとCSRの役割の違い
1. おわりに

## SEOタグとは
### What is SEOタグ
SEOタグとは、検索エンジン最適化（SEO: Search Engine Optimization）のためにHTMLのheadタグ内に記述するメタ情報です。これらのタグは、検索エンジンがページの内容や目的を理解しやすくするために利用されます。

### DefaultSeoとNextSeo

Next.jsでは、Next.jsアプリケーション向けのSEO管理用ライブラリとして、**next-seo**が提供されています。
ページごとに個別に**NextSeoタグ**を挿入することで、簡単にseoのためのメタ情報をページ内に設定することができます。

> ライブラリ公式ドキュメント
https://github.com/garmeeh/next-seo

また、next-seoライブラリが提供するコンポーネントの1つで、全ページに共通するSEOのデフォルト設定を管理するためのコンポーネントとして、**DefaultSeo**があります。タイトルや説明文、OGP（Open Graph Protocol）情報、Twitterカード情報などを一括管理できます。


使い分けとしては、動的ページや個別ページが多い場合に、共通部分を**DefaultSeo**にまとめ、個別のSEOは必要に応じて、**NextSeo**(DefaultSeoの設定は上書きされる)を使用するといったように設定することができます。

#### NextSeoの例
```tsx:NextSeoタグ
<NextSeo
  title=タイトルを入れる
  description=説明を入れる
  canonical=ページの正規版URLを入れる
  twitter={{ handle: '@アカウント名', site: 'アカウント名', cardType: 'summary' }}
  openGraph={{
    title: urlを共有した時に表示したいタイトル,
    description: urlを共有した時に表示したい説明,
    url: カノニカルurl,
  }}
/>

```
上記のtitle,description,canonicalを埋めると開発者ツールから以下のように確認できる。
![スクリーンショット 2024-12-15 17.40.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/b7b53ba6-d78f-b721-a4ed-b03194ab7c60.png)

ページのソースを表示ではこのようにみえる。
![スクリーンショット 2024-12-15 17.47.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/ca7f6636-8fd9-1b90-8393-4123941ca069.png)

##### メタ情報の確認方法
導入したメタ情報は、"Chrome(ブラウザ)でWebページを開く" →　"右クリック" → "ページのソースを表示" で確認することができる。この時確認できるものはサーバサイドでレンダリング(ssr)されたもの。

クライアントサイドでレンダリング(csr)されたものを確認する場合は、"開発者ツール" → "要素" → "head" で確認することができる。

##### 構成要素の説明
- **title**
ページのタイトルを設定(検索結果やブラウザタブに表示される）。
- **description**
ページの概要の説明(検索結果の概要として表示される）。
- **canonical**
ページの正規版URLを指定するための設定。検索エンジンに正しいURLを伝えることができるので、重複コンテンツが存在する場合でも、検索エンジンが正しいURLを評価しインデックスできます。
- **twitter**
リンクをTwitte(X)上でシェアした際に表示されるプレビューの形式を決定するもための設定。
cardTypeをsummaryにすることで、概要情報付きの小型カードが表示できる。
例えば、以下のように記事を共有したときに出るカードのこと。
![スクリーンショット 2024-12-16 18.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/3e32695c-8ed5-fbaf-1233-9fb6a0420e65.png)


- **OpenGraph**
ソーシャルメディアでのプレビュー情報（タイトル、説明、画像など）の設定。
OpenGraph（OGP）は、Metaが策定した規格でX(Twitter)以外の多くのソーシャルメディアプラットフォームが対応している。


#### DefaultSeoの例
```tsx:DefaultSeoタグ
<DefaultSeo
  title="title"
  description="description"
  canonical="https://example.com/"
  openGraph={{
    type: 'website',
    locale: 'ja_JP',
    url: 'https://example.com/',
    title: 'title',
    description: 'description',
    images: [
      {
        url: 'https://example.com/images/ogp.png',
        width: 1200,
        height: 630,
        alt: 'alt text',
      },
    ],
  }}
  twitter={{
    handle: '@handle',
    site: '@site',
    cardType: 'summary_large_image',
  }}
/>
```

DefaultSeoを設定することで、NextSeoが設定されていないページのメタ情報はDefaultSeoで指定した情報になる。

### 導入メリット

SEOタグの導入メリットはいくつかあります。

1. 検索エンジンの順位が向上することで、より多くのユーザーに見てもらえる
1. 検索結果やSNSプレビューでの魅力が向上することで、クリック率が向上する
1. カノニカルurlの設定で重複ページを回避することで、ペナルティを防ぎ、正しいページを評価してもらえる
1. OGPやTwitterカードでリンク見栄えをよくすることで、SNSでの表示最適化に繋がる

これら、適切なSEO対策によって多くの流入を得られ、アクセス数の増加に繋がります。

### SEOの分析ツール
以下のようなサイトでSEOの分析を行うことができます。

https://ko-hyo-ka.com/

他にもたくさんSEOを分析できるサイトがあるので、試してみてください。


## SSRを用いて動的にSEOタグを設定する
まず、わざわざSSRでSEOタグを入れるというタイトルにしたのには理由があります。
というのも、特定の状態では、同一のページにいるのにCSRとSSRで描画されたHTMLソースのSEOタグが異なって挿入されてしまうケースがあります。
それは、サーバーがHTMLを生成（SSR）して、かつ、SSRの関数の外で動的にページ名を決める(seoタグを挿入する)実装をした場合、CSR/SSRでそれぞれ確認できるSEOタグが異なってしまうのです。
これでは、動的に生成されたページに意図したSEOタグを挿入できていない恐れがあるため、適切なSEO対策ができていないということになります。
（ページのソースを表示と、開発者ツール>要素>headで表示したメタ情報が異なっちゃう）

サービスの特性にもよりますが、Webサイトの構造が大きくなってくると、静的に生成するページだけではなく、動的に生成するページが増えてくるはずです。そこで、サーバサイドからのpropsを用いて、動的に生成されるページにも適切なseoタグの挿入をできるようにします。

```tsx:ssrで生成したseo情報をcsrに渡す
type Props = {
  seo: {
    title: string,
    description: string,
    canonicalUrl: string
  };
};

const Page: NextPageWithLayout<Props> = ({ seo }) => {
      {/* SSRで生成したSEO情報を使用 */}
      <NextSeo
        title={seo.title}
        description={seo.description}
        canonical={seo.canonicalUrl}
        twitter={{ handle: '@XXXX', site: '@XXXX', cardType: 'summary' }}
        openGraph={{
          title: seo.title,
          description: seo.description,
          url: seo.canonicalUrl,
        }}
      />
}

// SSR
export const getServerSideProps = async (context: any) => {
    
    // url情報を取得してページ構造を把握する処理を書く

    // SEO情報を動的に生成する関数を実行して返り値を分割代入
    // url構造に基づき、titleやdescriptionを変化させる
    const { title, description, canonicalUrl } = generateSeoTags(url構造を引数にいれる);
    
    return {
        props: {
            seo: {
             title,
             description,
             canonicalUrl,
           }
        }
    };
};
```

ちなみに、useEffectはクライアントサイドじゃないと動かないので、useEffectを用いて動的ページ生成に対応したseoタグの導入を試みると、こちらもcsrとssrでseoタグが異なってしまうので、注意が必要です。

## 補足：SSRとCSRの役割の違い

#### SSRとCSRについて
SSR は初期HTMLを生成してブラウザに送信するプロセス。
ページがブラウザに表示され、JavaScriptが動作を開始した後は CSR が動作します。
SSRとCSRは連携して動作し、初期表示の速度とインタラクティブ性を両立する仕組みです。

#### SSRとCSRが組み合わさる例（Next.jsの仕組み）
1. SSRで初期HTMLを生成
検索エンジンやユーザーがアクセスしたとき、サーバー側でレンダリング済みのHTMLが送信される
1. CSRでインタラクティブにする
ブラウザがReactなどのJavaScriptをロードし、インタラクティブな動作を追加（ボタンクリックやスクロールなどの動作)

#### SSRとCSRの役割の違い
- SSRの役割
初期表示をサーバー側でレンダリングし、完全なHTMLを送信
ユーザーはページを早く表示できる（特にSEOやファーストビューで有利）


- CSRの役割
初期表示後、クライアント側でJavaScriptが動作し、ページがインタラクティブになる。例: ボタンのクリックイベントや、フォーム送信時の非同期通信

これらの違いを理解して適切にSEOタグを挿入できるようにすることが重要です。
適切にSEOタグが挿入されなければ、ページの評価が下がる恐れがあります。

## おわりに
今回は、検索エンジン最適化(SEO)のためのCSR/SSRにおけるメタ情報の導入方法について説明しました\:kissing_closed_eyes: chu☆

今回のアドカレでは2日分の投稿をしましたとさ。1回目の投稿はこちらから ↓
https://qiita.com/ayumun_jp/items/ee2168f2f29ce6f952dd