個人開発で無料SEOチェックツールを作った話 — Next.js × Cloudflare Workers × D1
はじめに
こんにちは、今井(@imai_director)です。
Web開発とマーケティングの両面からWebサイトの成長を支援しています。最近20年以上の自営業歴、有形営業、無形営業、個人法人営業、マーケティングの知見から、Kindleで『三方良しで勝つ 江戸商人に学ぶ現代WEB戦略』という本を出しました。
今回は、個人開発で 無料のSEOチェックツール を作った経緯と技術的な中身について書きます。
URLを入力するだけで、45項目以上のSEOチェックを実行し、100点満点のスコアで診断結果を返すツールです。
なぜ作ったか
SEOチェックツールは世の中にたくさんあります。ただ、使っていて感じていた不満がいくつかありました。
- 構造化データの診断が弱い: JSON-LDの有無や内容まで踏み込んでチェックしてくれるツールが少ない
- 改善方法が抽象的: 「メタディスクリプションを改善しましょう」と言われても、具体的にどう書けばいいのか分からない
- 無料枠が少なすぎる: 1回試しただけで課金を求められるツールが多い
- 日本語対応がいまひとつ: 海外ツールの翻訳精度が低い
「じゃあ自分で作るか」と思ったのがきっかけです。
特に構造化データ(JSON-LD)の診断に力を入れたかった。構造化データはリッチスニペット獲得に直結するのに、きちんと診断してくれるツールが少ない。意外と重要なのにマーケターも知っておいた方が良いと思いました。
それと、20年以上自営業をやってきた身としては、せっかくSEOをチェックして数値化できるなら、クライアントへの提案や報告にそのまま使える営業ツールにもしたいという気持ちがありました。スコアで現状を可視化し、改善コードを提示し、PDFでレポートを渡せる。エンジニアだけでなく、Web制作会社やフリーランスの営業現場でも役立つツールを目指しています。
できること
SEOスコア診断(100点満点)
4つのカテゴリ、45項目以上をチェックします。
| カテゴリ | 配点 | 主な項目 |
|---|---|---|
| 構造化データ | 40点 | JSON-LDの有無・種類・必須プロパティ・ネスト構造 |
| 基本SEO | 30点 | title・meta description・OGP・canonical・hreflang |
| コンテンツ | 20点 | 見出し構造・画像alt・内部リンク・テキスト量 |
| 技術的SEO | 10点 | HTTPS・レスポンス速度・viewport・robots.txt |
構造化データに40点という大きな配点を置いているのが特徴です。
Core Web Vitals
Google PageSpeed Insights APIを使って、LCP・CLS・INPの3指標 + パフォーマンススコアを取得。モバイル・デスクトップ両方に対応しています。
ドメインパワー
Open PageRank APIを使い、0〜10スケールでドメインの強さを表示します。
その他の機能
- 競合比較: 複数サイトのスコアを横並びで比較(Basic以上)
- 改善コード自動生成: 指摘箇所に対して、コピペで使えるHTMLコードを生成(Basic以上)
- キーワード調査: サジェスト・見出し抽出・共起語分析の3機能(Entry以上)
- PDF出力: 診断結果をPDFでダウンロード(Pro)
- 日英多言語対応: UIとチェック結果の両方を日本語・英語で表示
技術スタック
┌─────────────────────────────────────────────┐
│ フロントエンド(Vercel) │
│ Next.js 16 + React 19 + TypeScript │
│ Tailwind CSS + shadcn/ui │
│ seo.codequest.work │
└──────────────────┬──────────────────────────┘
│ fetch
┌──────────────────▼──────────────────────────┐
│ API(Cloudflare Workers) │
│ Hono + TypeScript │
│ api.codequest.work │
├─────────────┬──────────────┬────────────────┤
│ Cloudflare │ PageSpeed │ Open PageRank │
│ D1 (SQLite) │ Insights API │ API │
└─────────────┴──────────────┴────────────────┘
選定理由をざっくり書くと:
| 技術 | 選んだ理由 |
|---|---|
| Next.js (App Router) | SSG/SSR の柔軟性、SEO向けメタタグ生成が楽 |
| Cloudflare Workers + Hono | コールドスタートなし、D1との親和性、無料枠が太い |
| Cloudflare D1 | SQLiteベースで馴染みやすい、Workersとの一体運用 |
| Stripe | 決済のデファクト、Webhook処理が堅牢 |
| Sentry | フロント・Workers両方のエラーを一元監視 |
モノレポ構成
SEO_Checker/
├── apps/
│ └── web/ # Next.js フロントエンド
│ ├── app/[locale]/ # 多言語ルーティング
│ ├── components/ # UIコンポーネント
│ └── lib/ # ユーティリティ・翻訳・型定義
├── packages/
│ ├── api/ # Cloudflare Workers API
│ │ ├── src/routes/ # エンドポイント定義
│ │ ├── src/lib/ # ビジネスロジック
│ │ └── src/middleware/
│ └── database/
│ ├── schema.sql # D1スキーマ
│ └── migrations/ # マイグレーション
フロントとAPIを明確に分離しつつ、同じリポジトリで管理しています。個人開発では、このくらいの粒度がちょうどいいと感じています。
SEOチェックの仕組み
ざっくりとした処理の流れです。
1. ユーザーがURLを入力
2. APIがそのURLのHTMLをfetch
3. HTMLを解析(メタタグ・見出し・リンク・構造化データを抽出)
4. 45項目以上のチェックルールに通す
5. カテゴリ別にスコアを算出(合計100点)
6. 結果をフロントに返却 → D1に保存
HTML解析
html-analyzer.ts でHTMLを解析し、以下を抽出します。
-
<title>、<meta name="description">、OGPタグ -
<h1>〜<h6>の見出し構造 -
<img>の alt 属性 -
<link rel="canonical">、hreflang -
<script type="application/ld+json">の構造化データ
ブラウザのDOMパーサーは使えない(Workers環境)ので、正規表現と文字列処理で解析しています。
構造化データのチェック
構造化データの診断には独自のルールエンジンを実装しました。スキーマタイプごとに必須・推奨プロパティを定義し、JSON-LDのパースだけでなく、プロパティの過不足・ネスト構造の妥当性まで見ています。ここが他のツールとの差別化ポイントです。
外部API活用
PageSpeed Insights API
Core Web Vitalsの取得に使っています。注意点として、1回のリクエストに10〜30秒かかることがあります。フロント側ではローディングUIを出して、ユーザーを待たせすぎないようにしています。
Open PageRank API
ドメインパワーの取得に使用。無料プランで1時間あたり10,000リクエストまで使えます。返ってくるスコアは0〜10のfloat値。シンプルで使いやすいAPIです。
Google Autocomplete
キーワードサジェスト機能で使用。公式APIではありませんが、Googleの検索サジェストを取得できます。
Cloudflare D1の実践知見
D1はCloudflareのSQLiteベースのデータベースです。個人開発で使ってみて感じたことを書きます。
良かった点
- SQLiteの知識がそのまま使える: 新しいクエリ言語を覚える必要なし
- Workersとの一体感: バインディングで直接アクセスでき、接続管理が不要
-
マイグレーションが楽:
wrangler d1 migrations applyでスキーマ変更を適用 - コストが安い: 無料枠で十分運用できる
ハマった点
- JOINのパフォーマンス: 複雑なJOINを書くとレスポンスが遅くなりがち。クエリをシンプルに保つのが大事
- 型の扱い: SQLiteなので型が緩い。アプリ側でしっかりバリデーションする必要がある
-
ローカル開発:
wrangler devでローカルD1が使えるが、本番データとの同期は手動
Stripe決済の実装
フリーミアムモデルで4プラン(Free / Entry / Basic / Pro)を提供しています。
実装のポイント
- Checkout Session: Stripeのホスト型決済画面を使用。自前でカード入力フォームを作る必要なし
- Webhook: 決済完了・プラン変更・解約のイベントを受け取り、D1のプラン情報を更新
- 冪等性の担保: Webhookはリトライされることがあるので、同じイベントを2回処理しない設計が必要
Stripeは公式ドキュメントが充実しているので、実装自体はスムーズでした。
こだわったポイント
日英多言語対応
URLに言語コードを含むルーティング(/ja/...、/en/...)で日英を切り替えています。翻訳はキーと値のペアで管理し、UIだけでなく、APIのレスポンス(チェック結果のメッセージ)も言語に応じて出し分けています。
JSON-LD一元管理
自サイトのJSON-LDは lib/json-ld/ フォルダで一元管理しています。ページごとに最適な構造化データを出力する設計です。SEOチェックツールを作っている以上、自分のサイトの構造化データがおろそかだと説得力がないので、ここはかなり気を使いました。
チャットウィジェット
FAQ自動応答のチャットウィジェットを自作しました。キーワードマッチングで回答を返し、マッチしなかった質問を管理画面で確認できるようにしています。「ユーザーが何に困っているか」を把握し、FAQの改善に直接活かせる仕組みです。
外部のチャットサービスを使わず自作した理由は、ユーザーの声をプロダクト改善に直接活かしたかったからです。
料金設計
| プラン | 月額 | 主な機能 |
|---|---|---|
| Free | ¥0 | 月10回チェック、登録不要 |
| Entry | ¥980 | 月30回、キーワード調査 |
| Basic | ¥2,980 | 月100回、競合比較、改善コード |
| Pro | ¥9,800 | 月300回、PDF出力、技術SEO完全診断 |
無料プランは登録不要にしています。メールアドレスの入力なしで、すぐに試せる。ここのハードルを下げることが、利用者を増やす上で一番大事だと思っています。
運用
- エラー監視: Sentry でフロント・API両方を監視
- アナリティクス: GA4 でユーザー行動を計測
- チャットログ分析: 管理画面で未回答の質問を確認 → FAQを改善
-
LLM対応:
llms.txtとllms-full.txtを公開し、AIクローラーにもサービス内容を伝えやすくしている
今後の展望
現時点で無料APIだけで実現できる機能はほぼ実装しました。今後は有料APIの導入を検討しています。
- 獲得キーワード調査: あるドメインがどんなキーワードでランクインしているか
- 検索ボリューム: キーワードの月間検索数
- 被リンク分析: バックリンクの数と質
DataForSEO APIが候補で、初回$50のデポジットで始められます。ユーザー数の推移を見ながら判断する予定です。
まとめ
個人開発でSEOチェックツールを作ってみて学んだことは:
- 差別化ポイントを絞る: 「構造化データ診断に強い」という一点に集中した
- 自分が欲しいものを作る: SEOに関わる仕事をしているからこそ、「ここが足りない」が見えた
- まず使ってもらう: 無料・登録不要で試せるハードルの低さが大事
技術的には、Cloudflare Workers + D1 + Hono の組み合わせがSaaS開発にかなり向いていると感じました。コールドスタートがなく、個人開発のバックエンドとして強くおすすめできます。
よかったら使ってみてください。フィードバックも歓迎です。
Discussion