先週、私たちは wp-rankings.com を公開しました。
WordPress.orgリポジトリのすべてのプラグインを追跡します:成長率、インストール数の推定、ランキング、勢い、キーワードの順位、そして競合比較。
動作環境はこちらです:
- 60,000件以上のリスティング
- すべてに40個のカスタムフィールド
- 背後にある1,620万行の履歴データ
- ローンチ日には3,000人のリアルな訪問者が訪れ、そのほとんどが数時間以内に集中しました
- 最初の5日間で10,000件以上のユニーク訪問、まだベータ版
- 最適化作業を一切行う前の段階で、Google PageSpeedスコアは92
すべてGeoDirectory上で実現。
検索は独自のElasticsearch拡張機能を通じて行われます。これはこの規模のサイト向けに開発したGeoDirectoryアドオンです。なぜ必要だったかについては後述します。
GeoDirectoryがどこまでスケールするのか、常に質問を受けます。以前の答えは「あなたが思うより遥かに先まで、クライアントサイトがその証拠です」というものでした。今では、誰でもアクセスして負荷をかけられる公開サイトがあります。
この記事では、その構築方法を紹介します。
このサイトが存在する理由
WordPress.orgはかつて、すべてのプラグインページにアクティブインストール数の成長グラフを表示していました。ある時点でそれが削除され、復活を求めるTracチケット #6511は、今もオープンのままです。
そのグラフは、プラグインが実際に成長しているかどうかを確認できる唯一の手段でした。
それがなければ、「10,000件以上のアクティブインストール」というバケツの中の数字しか得られず、それが急成長中の10,000件なのか、静かに減り続けている19,000件なのか、まったくわかりません。
そこで4年前、私たちはWordPress.orgのプラグインAPIを毎日取得してデータを蓄積し始め、wp-rankings V1を構築しました。
それ以来、一日も欠かしていません。
リポジトリ全体にわたる4年間の毎日のスナップショット。これは後から遡って作成することができない、唯一無二のデータです。
V2はその進化版で、さらに多くの統計情報を備え、そのデータに対してついに世界水準のフロントエンドを構築した成果です。
リスティングの構造
リポジトリ内のすべてのプラグインは、GeoDirectoryのリスティングです。 gd_place 投稿として、データはGeoDirectoryの詳細テーブルに格納されており、 wp_geodir_gd_place_detail.
各プラグインには40個のカスタムフィールドがあります。アクティブインストール数、ダウンロード数、評価、評価数、サポートスレッド数、解決済みスレッド数、バージョン、動作確認済みバージョン、WordPress.orgランク、さらに独自に算出してライトバックする値も含まれます。
ここが人々が軽く見がちな部分です。
GeoDirectory のカスタムフィールドは、実際のスキーマ、実際のテーブル、実際のカラム型を持つ本物のデータ構造です。計算済みの成長率は FLOAT カラムに格納されます。
インデックスも張れる、ソートもできる、フィルタリングもできる。データベースのカラムそのものだから、当然そのように動作します。
ある程度の規模のサイトで、投稿メタ値を使って WordPress アーカイブをソートしようとしたことがあれば、これがなぜ重要なのかおわかりでしょう。
投稿メタはスキーマのコスプレをしたキー・バリュー型ストアであり、少し踏み込んだクエリを投げ始めた途端に崩壊します。
この記事の残りすべては、このひとつの判断にかかっています。データをカスタムフィールドに正しく入れてしまえば、あとは自ずとうまくいきます。
検索とソート、そして私たちが犯したミス
この記事でどこか一箇所だけ読むとしたら、ここです。
トレンドソートが必要でした。7日間の成長率でアーカイブを並べ替え、今まさに動いているものを確認するためです。
このプロジェクトの実装の大部分は Claude Code が担っており、最初の回答はカスタム SQL でした。カスタムの JOIN と、GeoDirectory のクエリに無理やりくっつけたカスタムの order-by フックです。
一見合理的に見えました。ローカル環境では問題なく動作しました。
本番サイトでは、パフォーマンスが崩壊しました。それまで速かった検索が、数十秒かかるようになったのです。
すぐに気づき、AI にそのコードをすべて捨てさせ、代わりに GeoDirectory の流儀でやり直させました。
正しい修正はシンプルでした。 growth_7d を GeoDirectory のカスタムフィールドとして追加します。これにより詳細テーブルに FLOAT カラムが作成されます。バックグラウンドジョブで値を計算し、そのフィールドに書き込みます。
あとは GeoDirectory 自身のソートシステムにソートを登録し、他の項目と同様に GeoDirectory にソートさせるだけです。 growth_7d_desc。以上です。
60,000 件のリスティングでも、再び高速になりました。
これが教訓です。そしてそれはこのプロジェクトをはるかに超えた話です。
AIコーディングツールは、デフォルトでインフラを再構築しようとします。ソートの問題を渡せば、トレーニングで何百万回も見てきたSQLに手を伸ばします。
StiofanがGeoDirectoryのクエリレイヤーを大規模データセット向けに長年かけて最適化してきたことを、AIは知りません。
これから構築しようとしているものがすでにすべて作られ、本番環境でテストされ、10年かけて磨き上げられてきたことも、AIは知りません。
AIは解決済みの問題に対して劣ったバージョンを自信満々に出荷し、それに大満足するのです。
ですから、GeoDirectoryサイトでClaudeやChatGPTを使うなら、与えられる最も価値ある指示はこれです:
GeoDirectoryのネイティブな検索・ソート・フィルターのインフラを迂回しないこと。カスタムフィールドで拡張すること。
それがカスタムフィールドの目的です。それがすべてのコツです。
GeoDirectoryが終わり、私たちのコードが始まるところ
カスタムプラグインは2つあります。
1つ目はスクレイパーです。Stiofanが4年前に構築したもので、仕事はひとつ:毎日WordPress.orgのプラグインAPIを取得し、見つけた情報をリスティングに書き込むこと。このデータセットが存在する理由はそれだけで、以来ずっと静かに稼働し続けています。
2つ目はアナリティクスプラグインで、V2の新機能です。1,620万行のスナップショットテーブルを管理しています。1日1プラグインにつき1行:順位、インストール数の区分、推定インストール数、成長率、モメンタム状態。
時系列データはディレクトリの仕事ではなく、GeoDirectoryにそれを求めることは決してありません。そのテーブルは独自のスキーマ、インデックス、バックグラウンドジョブを持ち、GeoDirectoryの完全に外側に位置しています。
しかし、結果は戻ってきます。
アナリティクスプラグインは自身のデータに対して重い処理を行い、その出力をGeoDirectoryのカスタムフィールドに書き込みます。7日間の成長率は数百万行の履歴データから計算され、リスティング上の単一のFLOATとして表示されます。
GeoDirectoryの観点からは、それはただの別のフィールドです。他のフィールドと同様に、ソートし、フィルターし、表示します。
外で計算する。中に保存する。GeoDirectoryにクエリさせる。
それが3行で表すアーキテクチャであり、非常に大規模なデータセット上にありながらサイトが速い理由です。アーカイブクエリは1,600万行に触れることなく、数時間前に計算された1つの数値を読み取るだけです。
個別リスティングページ
プラグインページはダッシュボードです。指標カード、信頼度評価付きの推定アクティブインストール数、30日・90日・1年・全期間の成長チャート、モメンタム分類器、次のマイルストーン予測、レビューとサポートの統計、WordPress.orgのキーワードランキング、そして最大3つの競合との比較カードを備えています。
その裏側は、標準的なGeoDirectoryのシングルリスティングページをストックのBlockstrapで表示しているだけです。カスタムテーマは使っていません。
ダッシュボード自体は私たちのコードです。Chart.jsをカスタムフィールドのデータで動かしています。通常のBlockstrapユーザーがこれを手作りするのは難しく、そうでないふりをしても意味がありません。
ただし、ここで声を大にして言いたいのは、もう手作りする必要はないということです。
2年前なら、こういったページを作るには開発者を何週間も雇う必要がありました。
今では、作りたいものを説明するだけで、AIが作り上げてくれます。チャート、カード、比較テーブル、条件付きバッジまで。
今やほぼ簡単にできるのは、難しい部分がすでに完成しているからです。データはGeoDirectoryのカスタムフィールドの中に、構造化・型付き・クエリ可能な状態で揃っていました。
AIはクリーンなデータ層の上に構築するのが得意です。でも、データ層を一から生み出すのはとても苦手です。
整理されたカスタムフィールドを渡して成長チャートを依頼すれば、昼食前には完成します。クエリ層の設計を任せると、私たちが身をもって学んだように、サイトを平気で壊してしまいます。
だから役割分担はシンプルです。GeoDirectoryがデータとクエリを担当し、AIがその上に必要なものを構築する。
この順番で進めれば、こういったサイトは一人でも十分に作れます。
アーカイブ
ここで、これまでのすべてが報われます。
トレンドページには、アクティブインストール数が10,000以上のプラグインが、7日間の成長速度順に表示されます。ランク、プラグイン、24時間の動き、7日間の動き、成長率、推定アクティブインストール数が確認できます。
これはすべてGeoDirectoryのListingsブロックで実現されています。
GeoDirectory自身のリスティングブロックを使い、GeoDirectoryのソートオプションで並び替え、GeoDirectoryのカスタムフィールドを読み込んでいます。トレンドソートはGeoDirectoryのソートシステムに組み込まれており、他のソートと並んでいるため、リスティングが機能するどこでも使えます。
カスタムSQLはどこにも使っていません。
統計ページからは直接このページにリンクされています。
そのページにあるすべてのインストール数バケットは、フロアがすでに適用されたトレンドへのリンクになっているため、「10万インストール以上で勢いのあるプラグインを表示」がワンクリックで実現します。
データをカスタムフィールドに取り込み、ソートを適切に登録すれば、アーカイブはGeoDirectoryがすでに提供しているパーツから自動的に組み上がります。
申請フロー
プラグインのオーナーはリスティングを申請できます。これはGeoDirectoryのネイティブな申請機能に、独自の認証ロジックを追加したものです。
プラグインの Plugin URI: ヘッダー(メインPHPファイル内のもの)を確認し、申請者がそのドメインを管理していることを検証します。
メール認証、クリックで自動承認。
最初の1週間で約100件のプラグインが申請されました。
このサイトの他の場所と同じパターンです。
GeoDirectoryが機能を提供します。ビジネスルールはその上に乗せるだけです。
トラフィック、速度、そしてElasticsearchの話
ローンチはほぼすべてXによって牽引されました。
投稿が広まり、WordPressコミュニティの著名な人物数名が取り上げたことで、トラフィックが一気に押し寄せました。
ローンチ初日に3,000人のリアルユーザー。24時間に均等に分散したわけではなく、そのうちの数時間に集中していました。
計測について一言。これは多くの人が引っかかるポイントです。Cloudflareはその期間に72,000ユニークを報告しましたが、サーバーログでは約3,000人の人間でした。残りはボットです。
クライアントにディレクトリのトラフィックを報告する場合は、喜ぶ前にサーバーログを確認してください。
スタックは耐え切りました。GeoDirectory Cloud、前段にCloudflare、LiteSpeedキャッシュ。
特別なものは何もありません。
Google PageSpeedは92点を付けており、まだ最適化は始めていません(ベータ終了後に着手予定です)。
では、正直なところをお話しします。
このサイトの検索は、GeoDirectory 専用の独自 Elasticsearch 拡張機能を通じて動作しています。
カスタムフィールド 40 個を持つ 60,000 件のリスティングと、計算値によるソートという条件では、検索とカスタムソートが想定以上に遅くなっていました。
MySQL が本来以上の処理を担ってしまっていたのです。
ほとんどのディレクトリサイトは、そこまでの規模に達することはありません。
GeoDirectory のネイティブ検索は高速であり、数千件程度のリスティングを運用しているなら、それが最適な選択肢です。私たちも自信を持ってそうお伝えします。
wp-rankings はまさにスケールの限界領域にあり、Elasticsearch 拡張機能は MySQL の限界を超えたサイト向けに、カスタムビルドでインストール・設定するものです。
重要なのは、GeoDirectory の検索レイヤーにプラグインとして組み込める点です。
内部のエンジンを置き換えるだけで、その上にあるすべてはネイティブのまま機能します。検索・ソート・フィルターは引き続き GeoDirectory が管理します。
方向は逆でも、基本的な考え方は同じです。
GeoDirectory のインフラと連携して動くこと。それを迂回しようとしないこと。一方はサイトをスケールさせ、もう一方はサイトを壊します。
その他のスタック構成
UsersWP アカウント、ログイン、会員登録、プロフィール管理に使用。
Blockstrap、および Blockstrap page builder pluginをテンプレートおよびすべてのビジュアル要素に使用。
Turnstile をログインと会員登録に導入。 AyeCode Connect.
GetPaid と UsersWP Membership プレミアムティアに対応する予定です。まだ構築していませんが、需要が本物だと証明されれば着手します。
予想外だった需要が、広告です。
すでに6人ほどがサイトのスポンサーになりたいと申し出てくれたので、 GeoDirectory Advertising アドオンを次に追加します。セルフサービス形式なので、スポンサーは私たちの手を借りずに自分で掲載枠を購入できます。
AyeCodeスタック全体が、まさに設計通りの働きをしています。ここに回避策は一切ありません。
これが証明すること
「GeoDirectoryはどこまでスケールするのか?」という問いに、以前は肩をすくめてクライアントサイトのリストを見せるしかありませんでした。
今は、実際に行って試せる公開サイトがあります。
6万件のリスティング。それぞれに40のカスタムフィールド。その裏に1,600万行の履歴データ。
ほとんどのディレクトリサイトを潰してしまうようなトラフィックの急増も、まったく揺らぐことなく吸収しました。
2人で構築しました。
実装の大部分はAIの支援を受けており、本当に問題が生じたのは、AIにGeoDirectoryの内部構造を再設計させてしまったときだけでした。AIをツールとして活用していた間は順調でした。
ぜひご覧ください: wp-rankings.com
同じようなものを構築したいなら、何で動いているかはもうご存知のはずです。