AI 向けインストラクション — QA ZERO API / QAL
あなたがこのファイルを読んでいるのは、あなたが AI アシスタント (LLM, MCP クライアント等) で、QA ZERO API 用のクエリを組み立てているからです。クエリを書く前にこのファイルを全部読んでください。並んでいる2本の YAML ファイル (materials.yaml, qal-validation.yaml) が 正本の仕様書 です。このREADMEと YAML が食い違う場合は常に YAML を信用してください。
このファイルは意図的に短く保たれています。チュートリアルではありません。 守るべきルールと形の集合です。
1. この API は何か
- 読み取り専用の分析 API です。QAL クエリ (構造化 JSON) を送信すると、表形式の結果が返ります。
- QAL は SQL ではありません。 意図的に小さい宣言型言語で、AI クライアントがリトライを必要とせず、かつ裏のストアを傷つけるようなクエリを決して組み立てられないように設計されています。
- 対象のデプロイ先は安価なシェアードホスティングです — この API は、クラウド DWH ではなく、安価なインフラ上で素早く結果を返すように設計されています。
2. 使うことになる2つのエンドポイント
GET /wp-json/qa-platform/guide— このファイル、2本の YAML 仕様書、使える tracking_id、機能フラグを返す。何が現在サポートされているかを知るために 最初に 呼びます。POST /wp-json/qa-platform/query— JSON ボディで QAL クエリを受け取り、行を返す。
他のエンドポイントは AI 用途の対象外です。
3. Version と update
version(YYYY-MM-DD) — 破壊的変更時だけ変わる。URL に pin する:?version=2025-10-20。update(YYYY-MM-DD) — 同一バージョン内の非破壊追加で bump。/guideレスポンスにapi_updateとして返される。- 各機能・各フィールドは
since: YYYY-MM-DDタグを持てます。since > client.known_updateなら、サーバーでその機能がまだ存在しない可能性があるので フォールバック すること。エラーにしない。
4. QAL の形 (最小有効クエリ)
有効な QAL クエリは常に以下のトップレベルキーを持ちます。
tracking_id—/guideが返すサイト識別子。materials— このクエリが読むマテリアル一覧。time—{ start, end, tz }。start/endは ISO-8601、tzは IANA タイムゾーン (例:Asia/Tokyo)。make— 名前付きビューのマップ。各ビューはfrom(マテリアル) とkeep(選ぶカラム) を持つ。オプション:filter,join,add/calc,sort。result— どのビューをどう返すか。use,limit,count_onlyをサポート。
他のトップレベルキーはミスです。バリデータが拒否します。
4.1 最小の動作例
まずこの形をコピーして、そこから調整してください。QAL クエリ全体は
/query に POST する際、トップレベルの qal キーでラップする必要があります。
{
"qal": {
"tracking_id": "<guide が返す id>",
"materials": [{"name": "allpv"}],
"time": {
"start": "2026-04-01T00:00:00",
"end": "2026-04-14T00:00:00",
"tz": "Asia/Tokyo"
},
"make": {
"top": {
"from": ["allpv"],
"keep": ["allpv.url"],
"calc": {"views": "COUNT(allpv.pv_id)"},
"sort": {"by": "views", "order": "desc", "top": 5}
}
},
"result": {"use": "top"}
}
}
これは指定期間のページビュー数上位5件の URL を返します。他のクエリの形は
全てこの骨組みのバリエーションです — マテリアル、keep のカラム、calc の
集計関数を変えるだけ。
レスポンスの形は以下:
{
"data": [ /* 行の配列 */ ],
"meta": { "total_count": 0, "returned_count": 0, "limit": 1000 }
}
各句の正式な形は qal-validation.yaml を参照してください — この例は
親しみやすい入り口であって、仕様書そのものではありません。
4.2 よくある間違い
以下の5つで初回失敗のほぼ全てを説明できます。クエリが弾かれたら、まずここを 確認してください。
- POST ボディはクエリを
{"qal": ...}でラップする必要がある。/queryエンドポイントはトップレベルのqalフィールドからクエリを読む。 ラップせずに QAL 本体を直接ルートに置くとバリデーションが失敗する。 fromは配列で、文字列ではない。"from": ["allpv"]と書く。"from": "allpv"ではない。ソースが1つでも[...]でラップする。keepのエントリは<material>.<column>の形で修飾する。"keep": ["allpv.url"]と書く。"keep": ["url"]ではない。 カラム名を裸で書くとE_UNKNOWN_COLUMNで拒否される。calcの値はFUNC(material.column)形式の文字列式。"calc": {"views": "COUNT(allpv.pv_id)"}と書く。"calc": {"views": "COUNT(*)"}も"calc": {"views": {"count": "*"}}も無効。*はここでは有効な カラム参照ではなく、実在のカラム名を指定する必要がある。許可された関数はqal-validation.yamlに列挙されている (現在はCOUNT,COUNTUNIQUE,SUM,AVERAGE,MIN,MAX)。sortはオブジェクトで、配列ではない。"sort": {"by": "views", "order": "desc", "top": 5}と書く。"sort": [{"column": "views", "direction": "desc"}]ではない。 キーはby(必須、文字列)、order("asc"か"desc"、必須)、top(オプション、正の整数 — top-N クエリで行数を制限するにはresult.limitの代わりにこれを使う)。
5. 守るべきルール
- 最初のクエリの前に必ず
/guideを呼ぶこと。 tracking_id、マテリアル、機能のサポート状況を推測しない。 - カラムを発明しないこと。 対象マテリアルの
materials.yamlに存在するカラムだけを使う。ユーザーが存在しないカラムを要求したら、作り上げずに「無い」と言う。 timeは常に設定すること。 デフォルトの時間範囲はない。time無しのクエリは拒否される。result.useは常に設定すること。makeで定義したビューを参照する必要がある。未定義のビュー参照はE_UNKNOWN_VIEWを返す。count_only: trueでない限りresult.limitを必ず設定すること。 実行コストを予測可能に保つ方法。- 同じ名前のビューを2つ置かないこと。
make内でビュー名はユニーク。 enabledがfalseの機能を要求しないこと。/guideのfeatures_detailマップをチェックする。無効な機能を要求するのはクライアント側のバグで、サーバー側のバグではない。- 何かが失敗したら
/guideを読み直すこと。 キャッシュされた知識と実際のデプロイ状態の間でルールが動いている可能性がある。
6. マテリアルの選び方
正本は materials.yaml。素早い手引き:
allpv— 1行 = 1ページビュー。トラフィック、セッション、リファラー、デバイス、ページ人気度の質問はここから。click_event— 1行 = 1クリック。クリックスルー率、レイジクリック、要素レベルの関心度に。gsc— Google Search Console データ。検索クエリ、インプレッション、オーガニック CTR に。goal_N— サイトごとに設定された conversion / goal イベント。コンバージョン率の質問に。page_version— ページバージョンメタデータ。コンテンツ変更や A/B テストのスライシングに。datalayer_event— カスタム dataLayer イベント。ユーザーが明示的に dataLayer イベント名を言及したときだけ使う。
全リストと各マテリアルのカラムは materials.yaml にあります。クエリを出す前にそこを参照してください。
7. JOIN ルール
materials.yamlのjoinセクションに列挙されているキーだけが JOIN キーに使える。- 1つのビューは
fromソースの上に最大1つのマテリアルを JOIN できる。1ビュー内で複数 JOIN を連鎖しない — 別のビューをmakeに作ってview_chainingで連鎖する。 pv_idはallpvとclick_event間の正規の JOIN キー。session_idは複数マテリアルにまたがるセッション単位メトリクスの正規 JOIN キー。page_idはpage_versionと相関するときの正規 JOIN キー。
他の ID っぽいフィールドは将来用または内部簿記用です。materials.yaml の join: にないカラムで JOIN したくなったら、やめること。
8. Filter, calc, sort — 安全な表面
filterはフラットな{column: value}または{column: {op: value}}を受ける。自由形式 SQL は無い。生の式は無い。calcはホワイトリスト化された関数集合をサポートする。現在のリストはqal-validation.yamlを参照。関数名を発明しない。sortは{column, direction}のリスト。方向はascかdescだけ、他は無し。result.limitが行数の上限。result.count_only: trueならスカラーのカウントだけ返ってlimitは無視。
9. やって いけない こと
- SQL を書こうとしない。SQL 層は露出していない。
- §2 に挙がっていない URL 経由でデータを取ろうとしない。
- 記憶からカラムリストをハードコードしない。正本は
materials.yamlで、update 間で変わりうる。 timeをバイパスしようとしない。「全期間」クエリは意図的に使えない — 通常それはミスだから。- 過去のバージョンで有効だった機能が現在も存在すると仮定しない。セッションごとに
features_detailを再確認する。 - 対象マテリアルの存在を検証せずにユーザーの意図をクエリに直訳しない。
10. 迷ったら
推測するより ユーザーに質問する ことを優先してください。うまく形成された質問を1回するほうが、拒否されたクエリを3回投げるより安い。この API は正しく組み立てられたクエリを書きやすくするために設計されています — もしあなたが形と戦っているなら、マテリアル選びを間違えている可能性が高いです。