複数ツールのデータを1画面に集約するマーケティングダッシュボードを構築した話

スタートはClaude Codeを使い始めたところから
マーケティングチームの近藤です。WEBサイト、SNS、プレスリリースなど各ツールを利用してマーケティングや広報の仕事をしてます。通常ではコードを書くことは一切しない業務です。そんな中、ここ数年、社内・社外問わずAI駆動開発が話題になってきていて、非エンジニアでさえClaude codeでの業務効率化を行うようになってます。私も最近やっとClaude codeにも慣れてきて、ちょっと違う方法で今までちょっと欲しかったけど周りにお願いして作成してもらうまでもないものを作ってみようから始まりました。
なぜダッシュボードが必要だったか
月に一回の情報共有会前に、 HubSpot を開き数値を拾い、次に WordPress に切り替え、その後 PR Times の管理画面からPVを——。それぞれの数字をドキュメントにコピーしていると30分が過ぎていたました。
自社 のマーケ・広報を担当していると、確認しなければならない数字が複数のツールに散らばっています。
- PV や流入数 → Google Analytics 4(GA4)
- 検索キーワードの順位 → Google Search Console(GSC)
- プレスリリースの閲覧数 → PR Times 管理画面
- 問い合わせや案件情報 → HubSpot
- SNS のインプレッション → X アナリティクス
複数のツールにログインして数字を確認し、ドキュメントにまとめる作業は意外と相当な時間を費やします。また「先週と比べてどう変化したか」を横断的に把握することもなかなか困難でした。
そこでこれらのデータを1つの画面で確認できればと思い社内ダッシュボードを構築してみることにしました。
なぜ Looker Studio や Notion ではなく Next.js を選んだか
「Google スプレッドシート」「Looker Studio」「Notion データベース」など、ノーコードで作れる選択肢も検討しました。
| ツール | 課題 |
|---|---|
| Looker Studio | GA4・GSC との接続は簡単だが、PR Times(CSV)や HubSpot との連携が難しい |
| Notion DB | データ入力の自動化が難しく、手動更新の手間が残る |
| Google スプレッドシート | データは集められるが、複数ソースの並列表示・UI カスタマイズに限界がある |
Next.js を選んだのは「複数の API と CSV を組み合わせて自由にレイアウトできる」「サーバーサイドで API キーを安全に扱える」という2点が決め手でした。
なにより、Claude Codeからのオススメ(というか自動的にその流れ)だったというのが大きいです。
ダッシュボードが完成するまでの全体の流れ
Step 1: 何のデータを集めるか整理する(所要時間:半日)
↓
Step 2: Next.js でダッシュボードを作る(所要時間:エンジニア 2〜3 人日)
↓
Step 3: Basic 認証を設定して社外から見えないようにする(所要時間:1〜2 時間)
↓
Step 4: GA4・GSC のデータを取り込む(スナップショット方式)(初回:1〜2 時間 / 月次:5 分)
↓
Step 5: PR Times のデータを CSV から取り込む(所要時間:30 分)
↓
Step 6: Vercel に本番デプロイする(所要時間:1〜2 時間)
↓
Step 7: 月次のデータ更新フローを確立する
Step 1:データソースの整理——取得方法を先に決める
何をするか
「どのデータを、どの方法で取得するか」を先に決めます。データ取得方法の見極めを最初に行うことで、後工程の手戻りを防ぎます。
Claude codeと壁打ちしながら1つずつ確認していきました。
整理した結果
| データ種別 | ツール | 取得方法 |
|---|---|---|
| PV・ユーザー数 | GA4 | スナップショット(詳細は Step 4) |
| 検索クリック数・順位 | Google Search Console | スナップショット(詳細は Step 4) |
| プレスリリース閲覧数 | PR Times | CSV ダウンロード(詳細は Step 5) |
| 問い合わせ・案件数 | HubSpot | API でリアルタイム取得 |
| SNS 投稿の反応 | X(Twitter) | API でリアルタイム取得(※後述の注意あり) |
| テックブログ閲覧数 | Qiita・自社ブログ | API・RSS でリアルタイム取得 |
| イベント情報 | Connpass | JSON ファイルで管理 |
データ取得方法は「リアルタイム API」と「スナップショット(手動更新)」の2種類があります。毎日変わるデータはリアルタイム、月単位で見るデータはスナップショットで十分です。最初にこの仕分けをしておくと、後半の実装が大幅にシンプルになります。
実際は手元で動かすのとVercelにデプロイしたときでは取得方法が変わったデータもあります。
⚠️ X API の利用プランに注意
X(Twitter)API は2023年以降に有料化されており、現在は無料・Basic・Pro の3プランに分かれています。
| 指標 | 無料プラン | Basic プラン以上 |
|---|---|---|
| いいね数・RT 数・リプライ数 | ✅ 取得可 | ✅ 取得可 |
| インプレッション数(impression_count) | ❌ 0 が返る | ✅ 取得可 |
インプレッション数はダッシュボードの重要指標ですが、無料プランでは取得できず 0 が返ります。利用前にプランと費用をご確認してください。
⚠️ データ取得方法を事前に調べておく
| 確認項目 | 例 |
|---|---|
| API は公開されているか | PR Times は非公開 → CSV 方式に変更 |
| 社内のクラウドポリシー制約はないか | GCP 組織ポリシーで API キー発行が制限されていた |
| データの更新頻度は何が適切か | 月次確認なら月1回更新で十分 |
Step 2:Next.js でダッシュボードを作る
ダッシュボードの構成
| ページ | 内容 |
|---|---|
| サマリー | 主要指標の一覧(PV・クリック数・HubSpot 案件数など) |
| GA4 詳細 | PV・UU・流入チャネルの推移グラフ |
| GSC 詳細 | 検索順位・キーワード別クリック数 |
| PR Times | 記事別閲覧数ランキング |
| X(SNS) | インプレッション・エンゲージメント率 |
| HubSpot | 案件パイプラインと活動ログ |
技術スタック
| 項目 | 採用技術 |
|---|---|
| フレームワーク | Next.js 16(App Router) |
| 言語 | TypeScript |
| ホスティング | Vercel |
Next.js の「App Router」では、サーバーコンポーネントとクライアントコンポーネントを明確に分離できます。API キーはサーバーコンポーネント側のみで扱うため、ブラウザの DevTools からは参照できません。
Step 3:Basic 認証を設定する——社外からのアクセスを遮断する
| 方式 | 採否 | 理由 |
|---|---|---|
| Basic 認証 | ✅ 採用 | 実装コストが低く、社内閲覧専用ダッシュボードの用途に合っている |
| Google SSO | ❌ 見送り | 設定コストがかかる。社外共有が不要なため今回は過剰 |
| Vercel Authentication | ❌ 無効化 | Vercel アカウントを持つ人しか見られなくなるため不適切 |
パスワードはソースコードには書かず、Vercel 管理画面の「Project Settings → Environment Variables」で管理しました。GitHub にコードを公開していてもパスワードが漏れません。
❗️message alert
Vercel にはデフォルトで「Vercel Authentication」機能があります。有効のままにすると Vercel アカウントを持つ人しかアクセスできませんでした。 Basic 認証を使う場合は必要ないので無効化してください。
Project Settings → Deployment Protection → Vercel Authentication → 無効化
Step 4:GA4・GSC のデータをスナップショット方式で取り込む
なぜスナップショット方式を採用したか
当初は GA4 と GSC の API を本番サーバー(Vercel)から直接呼ぶ予定でしたが、社内の Google Cloud 組織ポリシーによりサービスアカウントキーファイルの発行が制限されていることが判明しました。
いろいろ調べて、そこまでリアルタイム性も求めないという判断で「スナップショット方式」を採用しました。
【スナップショット方式の仕組み】
① 月に1回、担当者のPCでスクリプトを実行する
↓
② ローカルPCがGoogleの認証情報を使ってAPIにアクセスし、データをJSONファイルに保存
↓
③ そのJSONファイルをGitHubにpushする
↓
④ VercelがビルドしてJSONが本番環境にバンドルされる
↓
⑤ ダッシュボードがJSONから数値を読み込んで表示する
更新コマンドと初回設定
# 初回のみ:ローカルPCのGoogle認証情報を設定する gcloud auth application-default login # 月次の更新(GA4・GSC 両方のスナップショットを取得) npm run update-snapshot
Vercel に JSON を含めるための設定
Vercel のサーバーレス関数はデフォルトでは data/ ディレクトリのファイルを含みません。next.config.ts に以下の設定が必要です。
// next.config.ts
outputFileTracingIncludes: {
'/': ['./data/**/*'],
}
❗️message alert
この設定がないと、ローカルでは動くのに Vercel では動かないという問題が発生していました。Claude Codeにログを投げて解決できました。「スナップショットが読み込めない」エラーが出た場合はまずここを確認してください。
メリット・デメリット
| 項目 | 内容 |
|---|---|
| ✅ メリット | API 障害が起きてもダッシュボードが壊れない |
| ✅ メリット | API キーをサーバーに置かなくて済む |
| ✅ メリット | コマンド1つで更新できる |
| ⚠️ デメリット | 月次の手動更新が必要(リアルタイムではない) |
Step 5:PR Times のデータを CSV から取り込む
PR Times は公式 API を公開していません。RSS フィードも提供していますが閲覧数データは含まれないため、CSV ダウンロードで対応することにしました。
❗️message alert
PR Times 管理画面には2種類の CSV があります。記事ごとのPV数などを表示したければ、「記事別 CSV」を選択してください。
| 種類 | 内容 | 使うもの |
|---|---|---|
| 全期間の集計 CSV | 全記事の合計のみ | ❌ |
| 記事別 CSV | 各記事の閲覧数・日別データ | ✅ |
| ::: |
ダウンロード手順:
1. PR Times 管理画面にログイン
2. プレスリリース一覧 → 記事を開く
3. 「アクセス解析」→「CSV ダウンロード」
4. data/accessdata.csv として保存 → git push
PR Times の CSV は Shift-JIS エンコーディングで出力されます。コード側で new TextDecoder('shift_jis') を使って UTF-8 に変換する処理が必要だったようです。
Step 6:Vercel に本番デプロイする
当初は Google Cloud Run へのデプロイも試みましたが、社内の Google Cloud 組織ポリシーにより --allow-unauthenticated(認証なしの一般公開)設定が禁止されていることが判明し、Vercel に切り替えました。
Vercel は GitHub リポジトリと連携するだけで自動デプロイが設定でき、初期設定のコストが低い点が今回の用途に合っていました。
GitHub main ブランチに push するだけで自動デプロイ(1〜2分で反映)
Step 7:月次のデータ更新フロー——所要時間 約5分
| 作業 | 所要時間 |
|---|---|
npm run update-snapshot の実行(GA4・GSC 取得) | 約1分 |
| PR Times 管理画面で記事別 CSV をダウンロード | 約2分 |
git add → git commit → git push の実行 | 約1分 |
| Vercel デプロイ完了の確認 | 約1分 |
| 合計 | 約5分 |
作業を通じて学んだこと
1. 社内ポリシーは事前に確認する
「GA4 の API キーを発行しようとしたら組織ポリシーでブロックされた」「Cloud Run に公開しようとしたら一般公開できなかった」など、環境制約で計画変更が2回発生しました。クラウドサービスを使うプロジェクトでは、情報システム部門に事前に「何ができて何ができないか」を確認しておくと手戻りが減ります。
2. データ取得方法は最初に見積もる
「API でリアルタイム取得できると思っていたら CSV しか提供していなかった」はよくあるケースです。データソースが決まった段階で、API 仕様・CSV エクスポートの有無・更新頻度を一覧で整理しておくと後半がスムーズになります。これについてはClaude codeに聞きながら修正していけたので、最初に全て調べるて開始が遅れるよりは進めたことが正解だったと思いました
3. 「更新されなくなったダッシュボードは使われなくなる」
今回は更新作業を 1コマンド + CSV ダウンロード にまで簡略化することで、月1回・約5分の運用負荷に収めました。「毎月10分以内に更新できるか」を実装前の判断基準にしておくと、技術選択の優先度が明確になります。
まとめ
| 項目 | 内容 |
|---|---|
| フロントエンド | Next.js 16(App Router) |
| ホスティング | Vercel |
| 認証 | Basic 認証 |
| データ管理 | リアルタイム API + スナップショット JSON + CSV |
| デプロイ方法 | GitHub push → Vercel 自動デプロイ |
| 月次更新工数 | 約5分 |
複数のツールに散らばっていたデータを1画面に集約することで、マーケティング指標の確認コストを削減できました。GA4 や PR Times のような「API 制約がある」ツールに対しても、スナップショット方式や CSV 取り込みを活用すれば無理なく組み込めます。
今後は数値を分析して次のアクションをコメントで出してもらうようなもの考えています。
よくある質問(今回、引っかかったところ)
Q. 数値が古いまま表示されています
A. GA4・GSC・PR Times のデータは自動更新されません。月次の更新手順(Step 7)を実施してください。
Q. PR Times の数字が 0 または表示されない
A. 「全期間集計 CSV」をダウンロードしている可能性があります。Step 5 の手順で「記事別 CSV」を再ダウンロードしてください。
Q. X のインプレッション数がすべて 0 になる
A. X API の無料プランではインプレッション数を取得できません。Basic プラン以上への変更が必要です。
Q. Vercel のビルドが失敗した
A. Vercel ダッシュボードのビルドログを確認してください。多くの場合、TypeScript エラーか環境変数の未設定が原因です。
