Github Actions で SEO 対策！サイトマップ作成を自動化！

こんにちは。ぬこすけです。

この記事では私が運営しているサイト「[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)」で実際にやっている **[Github Actions](https://github.co.jp/features/actions) を使ってサイトマップ作成の自動化** について紹介します。

https://nuko-programming.com/ranking/Python/page/1

次の構成でお話しますが、「サイトマップなんて知ってるぜ」「Github Actionsも使いまくってるぜ」という中上級者の方は最初の「[サイトマップとは？](#サイトマップとは)」や「[Github Actions とは？](#github-actions-とは)」は読み飛ばして OK です。

- [サイトマップとは？](#サイトマップとは)
- [Github Actions とは？](#github-actions-とは)
- [Github Actions でサイトマップ作成を自動化してみた](#github-actions-でサイトマップ作成を自動化してみた)
- [Github Actions のファイル例](#github-actions-のファイル例)
- [まとめ](#まとめ)

合わせてこちらの記事も書いたのでよかったらぜひ読んでみてください！

https://qiita.com/nuko-suke/items/26dd5988eeeee9c11bd4

## サイトマップとは？

みなさんは**サイトマップ**をご存知でしょうか？
もし Web に興味があるのであればサイトマップについて知っておいて損はないはずです。

サイトマップは簡単にいうと「**クローラー向けのフロアマップ**」といえるでしょう。
みなさんは百貨店やショッピングモールで買い物をする時、フロアマップを見て行きたいお店に行くと思います。

![building_shopping_mall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164159/1dd51ba7-b22d-8934-2a9b-35fe5694608b.png)

同じく Google に代表されるクローラーもフロアマップを見てあなたの Web サイトを巡回します。
巡回を促進することで、**新しく作ったページを素早くインデックス**（ Google などの検索エンジンに登録されて検索結果に表示されるようになること）されたり、あるいは**更新したページも早く評価してもらえる**ようになります。

Google も次のような場合にサイトマップが有用であることを紹介しています。

>次の場合にサイトマップが必要になることがあります。
>* サイトのサイズが非常に大きい。その場合、新しいページや更新されたばかりのページの一部が Google のウェブクローラによるクロール対象から漏れることがあります。
>* サイトにどこからもリンクされていない、または適切にリンクされていないコンテンツ ページのアーカイブが大量にある。サイトのページがうまく相互に参照されていない場合でも、サイトマップに含めることで Google が一部のページを見落とさないようにできます。
>* サイトが新しく、外部からのリンクが少ない。Googlebot などのウェブクローラは、ページからページヘリンクをたどることによってウェブをクロールします。そのため、他のサイトからのリンクがないページは Google のクローラに検出されないことがあります。
>* サイトに動画や画像などのリッチメディア コンテンツが多数含まれている、またはサイトが Google ニュースに表示されている。サイトマップがあれば、状況に応じて Google 検索でサイトマップからの追加情報が考慮されます。

https://developers.google.com/search/docs/advanced/sitemaps/overview?hl=ja&visit_id=637617380646088330-2488650453&rd=1

私は[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)という技術書ランキングサイトを作りましたが、**サイトマップの影響は大きい** と実感しています。

サイトマップがなかった時はクローラーも全くサイトを巡回してくれなかったのですが、**サイトマップを作成したとたん、数倍の勢いで巡回が走りました**。

サイトマップはフロアマップなので必ずしもどのサイトでも必要になるわけではありませんが、作成しておいて損はないでしょう。

ではサイトマップを機能させるためにはどうしたら良いのでしょうか？
サイトのルート階層に次のような `sitemap.xml` を配置することで機能させることができます。

```xml
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com</loc>
    <lastmod>2022-06-25</lastmod>
  </url>
  <url>
    <loc>https://example.com/page/1</loc>
    // lastmod はあってもなくても良い
    <lastmod>2022-06-25</lastmod>
  </url>
  ...
</urlset>
```

このようなページの URL を書いた xml ファイルをサイトに配置します。

具体例をあげると、[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)では次のようなサイトマップを作っています。

https://nuko-programming.com/sitemap.xml

このように `sitemap.xml` を配置することで、クローラーのサイト内の巡回を促すことができます。

続いて Github Actions について説明します。

## Github Actions とは

Github 上で実行できる CI/CD (継続的インテグレーション/継続的デリバリー) のためのサービスです。

https://github.co.jp/features/actions

これだけ聞いてもよくわからないと思いますが、具体的に何ができるかをいくつか例をあげてみましょう。

* メインのブランチにマージした時に自動でデプロイ。
* Git でリモートにプッシュした時に自動でテスト実行。
* 毎日決まった時間に自動でスクリプトを実行。

このように**Git の操作や時間などを起点に自動でデプロイやテストなどを実行することができます**。

**Github Actions は手軽にプロジェクトに導入できます**。
あなたが開発しているリポジトリのルート階層から `.github/workflows` ディレクトリを作成し、 yml ファイルを置くだけです！

yml ファイルは予め決められたフォーマットで記述していきます。
簡単な例を挙げてみましょう。
次の例では main ブランチにプッシュされた時に、 `Node.js` でスクリプトを実行します。

```yml
name: run-script

on:
  push:
    branches:
      - main

jobs:
  script:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '16'
      - name: Run Script
        run: node myscript.js
```

yml ファイルの書き方は公式ドキュメントに記載があります。

https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions

Github Actions はこのような感じで**気軽に導入することができます**。

## Github Actions でサイトマップ作成を自動化してみた

私が運営しているサイト[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)の例を紹介します！

主に次のようなステップで定期的にサイトマップ作成処理をしています。

1. API サーバーを起動する
2. API にリクエストし、 `sitemap.xml` を作成する
3. 作成したサイトマップをコミットしてプッシュする

### 1. API サーバーを起動する

[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)では技術書のデータを `GCP` 上に立てている API サーバーで管理しています。

この API にリクエストすることで URL の元となる技術書の ID などを取得します。
例えば https://nuko-programming.com/ranking/Python/book/49a8209c-8424-434a-8c88-2ef0210ca96a のように URL の末尾部分が ID になっているので、このような URL 生成に必要なデータを API から取得します。

API サーバーの起動のためのスクリプトを用意して実行しています。

### 2. API にリクエストし、サイトマップを作成する

URL　生成に必要なデータを API から取得して `sitemap.xml` を作成するスクリプト( `JavaScript` )を実行します。
簡単にスクリプトのイメージは次の通りです。

```js
import fs from 'fs/promises';
import fetchBooks from './fetchBooks'
// xml 生成には xml2js というライブラリを使っています
import { Builder } from 'xml2js';

try {
  const baseUrl = 'https://nuko-programming.com';

  // API にリクエスト
  const books = await fetchBooks();

  // xml に記述する URL のリスト作成
  const urls = books.map(({ keyword, id }) => ({
    loc: `${baseUrl}/ranking/${keyword}/book/${id}`
  }));

  // xml 生成
  const builder = new Builder();
  const sitemap = {
    urlset: {
      $: {
        xmlns: 'http://www.sitemaps.org/schemas/sitemap/0.9',
      },
      url: urls,
    },
  };
  const xml = builder.buildObject(sitemap);

  fs.writeFile('./public/sitemap.xml', xml);
} catch (e) {
  console.error(e);
  process.exit(1);
}

```

### 3. 作成したサイトマップをコミットしてプッシュする

2 で作成した `sitemap.xml` をコミットしてプッシュします。

[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)の場合は [Vercel](https://vercel.com/) というホスティングサービスと Github を連携しており、 main ブランチにプッシュすると自動で `Next.js` アプリケーションがデプロイされます。

ここのデプロイ方法については人によってまちまちでしょう。
例えば、 `Azure Static Web Apps` を使って `Next.js` アプリケーションをデプロイすることもできます。

https://docs.microsoft.com/ja-jp/azure/static-web-apps/deploy-nextjs

## Github Actions のファイル例

[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)で使っている Github Actions の yml ファイル例を紹介します（紹介用なので全てが同じではないです）。

```yml
name: daily-deploy

on:
  schedule:
    - cron: '0 0 * * *' # UTC なので注意！！

env:
  GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }}

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 180 # タイムアウト設定しないと永遠に処理走って大変になる場合がある
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: npm
      - name: Install Dependencies
        run: npm ci
      - name: Start Instance
        # package.json にスクリプトを登録しておく
        run: npm run start-gcp
      - name: Create Sitemap
        run: npm run create-sitemap
      - name: Git Setting
        run: |
          git config --local user.email メールアドレス
          git config --local user.name ユーザー名
      - name: Commit Sitemap
        run: |
          git add ./public/sitemap.xml
          git commit -m "Add sitemap.xml by Github Actions"
          git pull
          git push origin
      # 実行後は API サーバーを落としておく
      - name: Stop Instance
        if: ${{ always() }}
        run: npm run end-gcp
```

## まとめ

Google などのクローラーにサイト巡回してもらえるよう、 Github Actions を使ってサイトマップ生成を自動化するお話を紹介しました。

実は[ぬこぷろ](https://nuko-programming.com/ranking/Python/page/1)ではサイトマップ生成以外にも Github Actions を使って Twitter の bot を運用していたりもします。

https://qiita.com/nuko-suke/items/26dd5988eeeee9c11bd4

Qiita エンジニアフェスタ 2022 というのを今やっているそうなので、興味ある方は記事投稿して盛り上げて行きましょう〜。

https://qiita.com/official-campaigns/engineer-festa/2022