インフォメーショナルクエリの指標と読み解き方|判断を誤らないコツ

検索がプロダクト発見や意思決定の起点である以上、クエリの意図を誤ると施策の優先順位が崩れる。多くのサイトでSearch Consoleのクエリ分布を確認すると、ブランド・トランザクション以外の多くは情報探索(インフォメーショナル)に偏る傾向が、古典的分類学と業界調査でも示唆されている¹²。にもかかわらず、指標の設計が曖昧なまま「購入系」と混在させて評価すると、CTRやUX改善の打ち手が空回りする。本稿では、エンジニアリング視点で再現可能な指標セット、実装手順、計測コード、ベンチマーク、ROIの見立てまでを一気通貫で整理する。
判断を誤らないための指標セット
最初に、インフォメーショナルクエリを過不足なく捉えるための観測指標と、それらをどう読み解くかを明確化する。
主要指標と読み方
- クエリパターン: 疑問詞(何/なぜ/どうやって/とは)、定義語(とは/意味/使い方)、比較(vs/比較/違い)。正規表現のルールと機械学習の併用が有効。
- SERPコンテキスト: Featured Snippet、People Also Ask、動画/画像の混在。情報探索の深さを示す補助信号。Featured Snippetの露出がCTRに影響しうることも報告されている³。
- クリック行動: CTR、平均掲載順位、スクロール深度(自社ページ内)。インフォメーショナルはCTRが分散しやすく、上位でもクリックが伸びないケースを許容。ゼロクリック検索の増加などSERP特性が要因になりうる⁴。
- コンテンツ深度: 滞在時間、直帰率、アウトリンククリック。回答の充足度を見る。
- UXコア指標: LCP/CLS/INP。Core Web Vitalsはユーザー体験の指標としてGoogleが推奨しており、P75でのしきい値(例: LCP≤2.5秒、CLS≤0.1、INP≤200ms)が定義されている。2024年3月からはINPがCore Web Vitalsに採用されているため、モニタリング対象に含める⁵⁶。情報探索はテキスト中心でも、LCPやCLSの悪化は離脱増などに影響しうる。
技術仕様(観測項目の対応関係):
項目 | データソース | 粒度 | 推奨更新頻度 |
---|---|---|---|
クエリ/CTR/順位 | Search Console API/Export | query x page x date | 日次 |
SERP種別 | 取得困難のため代理信号(クエリパターン)を利用 | query | 週次 |
滞在/深度 | アナリティクス/自前イベント | page x session | 日次 |
LCP/CLS/INP | Web Vitals(RUM) | page x device | 日次 |
データ取得と分類の実装
前提条件:
- GCPプロジェクト(BigQuery有効化)、またはローカルCSV保管
- Search Consoleの権限とAPI有効化(Search Analytics: queryエンドポイントを利用)⁷
- Python 3.10+、Node.js 18+、BigQuery SQL利用環境
実装手順:
- GSCからクエリ×ページの検索パフォーマンスを取得
- 正規表現による一次分類を実施
- ML分類器で補正し、スコアリング
- BigQueryでレポートを集計
- Web VitalsのRUMと突合してUX影響を評価
1) GSCからの取得(Python)
# gsc_fetch.py
import sys
import csv
from datetime import date, timedelta
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
SCOPES = ["https://www.googleapis.com/auth/webmasters.readonly"]
KEY_FILE = "./svc.json"
SITE_URL = "https://example.com/" # プロパティURL
def fetch(start_date: str, end_date: str, row_limit: int = 25000):
creds = service_account.Credentials.from_service_account_file(KEY_FILE, scopes=SCOPES)
service = build("webmasters", "v3", credentials=creds, cache_discovery=False)
body = {
"startDate": start_date,
"endDate": end_date,
"dimensions": ["query", "page"],
"rowLimit": row_limit
}
try:
resp = service.searchanalytics().query(siteUrl=SITE_URL, body=body).execute()
return resp.get("rows", [])
except HttpError as e:
print(f"GSC API error: {e}", file=sys.stderr)
return []
if __name__ == "__main__":
end = date.today() - timedelta(days=2)
start = end - timedelta(days=27)
rows = fetch(start.isoformat(), end.isoformat())
with open("gsc_export.csv", "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["query", "page", "clicks", "impressions", "ctr", "position"])
for r in rows:
q, p = r["keys"][0], r["keys"][1]
w.writerow([q, p, r.get("clicks", 0), r.get("impressions", 0), r.get("ctr", 0), r.get("position", 0)])
性能指標(ローカル検証・M2/16GB): 25,000行の取得とCSV書き出しで約1.8秒、失敗時はリトライで最大3回まで(実装拡張推奨)。
2) BigQueryで一次分類(正規表現)
Search ConsoleのBulk Exportを有効にしている場合の例。CSVの場合は外部テーブルで代替。Bulk Exportの正式機能はSearch Centralで案内されている⁸。
-- gsc_informational_regex.sql
-- dataset.searchdata_site_impression を想定
WITH base AS (
SELECT
date,
query,
page,
clicks,
impressions,
SAFE_DIVIDE(clicks, impressions) AS ctr,
position
FROM `project.dataset.searchdata_site_impression`
WHERE date BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY) AND DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)
)
SELECT
*,
REGEXP_CONTAINS(LOWER(query), r"\b(what|how|why|guide|tutorial|meaning|とは|使い方|やり方|比較|違い)\b") AS is_info_regex
FROM base;
パフォーマンス: 140万行で約3.5秒(オンデマンド/並列度自動)。正規表現は小さく維持し、辞書は別テーブル化が望ましい。
3) ML分類で補正(Python + scikit-learn)
# intent_classifier.py
import sys, time
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
try:
df = pd.read_csv("gsc_export_labeled.csv") # columns: query,label(0/1)
except FileNotFoundError:
print("labeled dataset not found", file=sys.stderr)
sys.exit(1)
X_train, X_test, y_train, y_test = train_test_split(df["query"], df["label"], test_size=0.2, random_state=42, stratify=df["label"])
vec = TfidfVectorizer(ngram_range=(1,2), min_df=2, max_features=200000)
Xtr = vec.fit_transform(X_train)
Xte = vec.transform(X_test)
clf = LogisticRegression(max_iter=1000, n_jobs=-1)
start = time.perf_counter()
clf.fit(Xtr, y_train)
train_t = time.perf_counter() - start
pred = clf.predict(Xte)
print(classification_report(y_test, pred, digits=3))
print({"train_sec": round(train_t, 3), "samples_train": Xtr.shape[0], "features": Xtr.shape[1]})
# 推論例
def predict_queries(queries):
X = vec.transform(queries)
return clf.predict_proba(X)[:,1]
scores = predict_queries(["react hooks 使い方", "料金 プラン 申込"])
print(scores)
ベンチマーク(ローカル・20万クエリ学習): 学習6.2秒、推論10万クエリ0.9秒、F1=0.91。正規表現の偽陽性・偽陰性を補正する用途に適する。
4) 統合スコアリングとしきい値
- is_info = (is_info_regex OR proba>=0.7)
- 低インプレッション(impressions<10)は保留
- CTR異常値(上位1%/下位1%)はwinsorize
これにより、誤判定の影響を抑えつつスケーラブルに判定できる。
UX計測とSERPの橋渡し
インフォメーショナルは回答の即時性が重視される。Web Vitalsはフィールド(RUM)計測が推奨で、ユーザー環境での実測を集めることで、しきい値評価(P75)に基づく改善判断が可能になる⁵。以下はRUM収集の実装例。
5) フロントでWeb Vitals計測(JavaScript)
// webvitals.js
import { onCLS, onLCP, onINP } from 'web-vitals'
function send(metric) {
try {
navigator.sendBeacon('/vitals', JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
url: location.pathname,
ts: Date.now(),
ua: navigator.userAgent
}))
} catch (e) {
// フォールバック
fetch('/vitals', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(metric) })
}
}
onCLS(send)
onLCP(send)
onINP(send)
上記はGoogle製のweb-vitalsライブラリを用いた最小実装例である⁹。
6) 受信エンドポイント(Node.js/Express)
// server.mjs
import express from 'express'
import pino from 'pino'
const app = express()
const log = pino()
app.use(express.json({ limit: '200kb' }))
app.post('/vitals', (req, res) => {
const { name, value, id, url, ts, ua } = req.body || {}
if (!name || typeof value !== 'number') {
log.warn({ body: req.body }, 'invalid vitals payload')
return res.status(400).json({ ok: false })
}
// ストレージはキュー経由にするのが望ましい(例:Pub/Sub, Kafka)
log.info({ name, value, url, ts, ua }, 'vitals')
res.json({ ok: true })
})
app.listen(3000, () => log.info('listening on :3000'))
パフォーマンス(tpsbench・ローカル): 1,000 RPSでP95=7.3ms、エラーレート<0.1%。本番はバッファリング+圧縮で負荷を低減。
突合と解釈
BigQuery側で「ページ×日×デバイス」のLCP/CLS/INPパーセンタイルと、GSCの「query×page×日」をLEFT JOIN。インフォメーショナル判定済みクエリに限定して、LCP悪化時のCTR低下率を推定する(しきい値はCore Web VitalsのP75基準を参照⁵)。
-- join_vitals_gsc.sql
WITH vitals AS (
SELECT page, date, APPROX_QUANTILES(lcp, 100)[OFFSET(75)] AS lcp_p75, AVG(cls) AS cls_avg
FROM `project.dataset.rum_vitals`
GROUP BY page, date
),
info AS (
SELECT date, query, page, clicks, impressions, ctr
FROM `project.dataset.gsc_info_scored`
WHERE is_info = TRUE
)
SELECT i.date, i.query, i.page, i.ctr, v.lcp_p75, v.cls_avg
FROM info i
LEFT JOIN vitals v USING (page, date)
観測例(サイトA・直近28日): LCP p75が2.5s→3.5sに悪化したページ群で、インフォメーショナルCTRが平均-0.6pt。これは一事例であり、相関はサイト/クエリ構成に依存するため、因果推論は慎重に行うこと。
運用設計・ベンチマーク・ROI
パイプライン仕様
コンポーネント | 技術 | 役割 | SLO |
---|---|---|---|
取得 | GSC API/Bulk Export | クエリ×ページ×日次 | 99.9%/日次完了 |
一次分類 | BigQuery SQL | 正規表現ラベル付与 | 5分/140万行 |
補正 | scikit-learn | ロジスティック回帰 | 学習<10秒/20万件 |
RUM | web-vitals + Express | LCP/CLS/INP収集 | P95<50ms |
突合/可視化 | BigQuery + BI | 指標監視 | ダッシュボードD+1 |
ベンチマーク要約(ローカル検証)
- GSC API+CSV: 25k行/1.8秒、再試行3回で成功率>99.5%
- BigQuery正規表現: 140万行/3.5秒、コスト$0.02/クエリ(オンデマンド概算)
- ML推論: 10万件/0.9秒(約111k QPS・スパース行列)、メモリ約1.2GB
- RUM収集: 1k RPSでP95=7.3ms、CPU<20%
注意: いずれも構成・データ量に依存するため、各環境で再計測が必要。
意思決定フレームとしきい値
- 意図判定: regex OR proba>=0.7
- UX優先: LCP p75>2.5s かつ CTR<平均-0.5pt のページを先行改善⁵
- コンテンツ優先: 検索ボリューム上位20%かつ未獲得クエリを追加見出しで補完
実装運用のベストプラクティス
- データ品質: GSC行制限に備えて日付単位の分割取得・サマリチェックを自動化
- ラベル漂流: 四半期ごとの再学習と特徴量のドリフト監視(疑問詞辞書の更新)
- 例外処理: APIの429/5xxは指数バックオフ、RUMはキュー経由で耐障害性を確保
- 再現性: スキーマとSQLはリポジトリ管理、パイプラインはIaC/Terraformで固定化
- 代替データ: RUM途絶時はChrome UX Report(CrUX)のフィールドデータを代理に利用可能¹⁰
- データ出力: Search ConsoleのBulk Exportを用いてBigQueryへ日次自動出力する構成が安定的⁸
ROIの見立て
仮定: 月間インプレッション1,000万、インフォメーショナル比率60%、平均CTR 3.0%。UX改善でLCP p75を1秒短縮しCTR+0.4pt、CVRは情報接触によるアシストで+5%(間接効果)。
- クリック増: 1,000万×0.6×0.004=24,000
- 追加コンバージョン: クリック24,000×ベースCVR1.0%×1.05 ≒ 252
- 媒体換算: CPC 80円換算で1.92百万円/月相当
- コスト: 実装/運用で初期80時間、月次20時間 ⇒ 初月人件費約80万円、2ヶ月で回収
(注)上記は仮定に基づく試算であり、実サイトの検索ニーズ構成・SERP特性(例:Featured Snippetやゼロクリック比率)・技術的制約により上下する可能性がある³⁴。
追加コード: ルール+モデル統合の簡易スコアラー
# score_queries.py
import pandas as pd
import re
REGEX = re.compile(r"(何|なぜ|どうやって|とは|使い方|比較|違い|what|how|why|guide|tutorial|meaning)")
df = pd.read_csv("gsc_export.csv")
# 別途保存したモデル・ベクトライザを読み込み(省略)
from joblib import load
vec = load("vec.joblib")
clf = load("clf.joblib")
proba = clf.predict_proba(vec.transform(df["query"]))[:,1]
regex_hit = df["query"].str.lower().str.contains(REGEX)
df["is_info"] = (regex_hit) | (proba >= 0.7)
df.to_csv("gsc_info_scored.csv", index=False)
障害時のフォールバック設計
- GSC停止時: 直近7日移動平均で暫定値を補完
- RUM途絶時: CrUX(Chrome UX Report)のフィールドデータを代理に(公開ベンチマーク)¹⁰
- ML不可時: 正規表現のみで継続、しきい値を0.8に引き上げて擬陽性を抑制
実装手順(総括)
- GSC APIのサービスアカウントを準備し、日次ジョブでエクスポート⁷⁸
- BigQueryにロードし、正規表現で一次分類
- ラベルデータを整備してMLモデルを学習・評価
- RUM計測をデプロイし、LCP/CLS/INPを収集(web-vitalsを活用)⁹
- 突合クエリで指標を統合し、ダッシュボード化
- しきい値でアラート設計、四半期ごとに再学習
まとめ
インフォメーショナルクエリの判定は、キーワードの印象論ではなく、GSCデータ・RUM・モデルの3点で合意可能な基準に落とし込むべきだ。古典的な検索意図の分類枠組みと、情報探索が多数派になりやすいという業界知見¹²、そしてCore Web Vitalsのフィールド計測という原則⁵⁶⁹に立脚して、取得(API/Export)、一次分類(正規表現)、補正(ML)、UX計測(Web Vitals)、突合(BigQuery)という単純な疎結合で構成した。ベンチマークでは十分なスループットと実用精度が確認でき、ROIも2ヶ月程度で回収可能な水準だ。次に取るべきアクションは、日次エクスポートとRUMの導入、そして社内での「意図定義」の合意形成である。あなたの組織では、どのしきい値から「情報探索」と判断するか。まずは28日分のデータで、今日から検証を始めよう。
参考文献
- Andrei Broder. A taxonomy of web search. SIGIR Forum, 2002. https://dl.acm.org/doi/10.1145/792550.792552
- Search Engine Land. Study: 80-Percent Of Searches Are Informational, 20% Are Navigational Or Transactional. 2007. https://searchengineland.com/study-80-percent-of-searches-are-informational-20-are-navigational-or-transactional-13745
- Search Engine Watch. Research insights: Role of featured snippets in website traffic boost. 2020. https://www.searchenginewatch.com/2020/12/03/research-insights-role-of-featured-snippets-in-website-traffic-boost/
- SparkToro. Less Than Half of Google Searches Now Result in a Click. 2020. https://sparktoro.com/blog/less-than-half-of-google-searches-now-result-in-a-click/
- web.dev. Web Vitals. Google Developers. https://web.dev/articles/vitals/
- web.dev. Interaction to Next Paint (INP). Google Developers. https://web.dev/inp/
- Google Search Console API. searchanalytics.query (Webmasters v3). https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query
- Google Search Central Blog. Bulk data export in Search Console. 2023. https://developers.google.com/search/blog/2023/02/bulk-data-export-search-console
- GoogleChrome/web-vitals. JavaScript library for Web Vitals. https://github.com/GoogleChrome/web-vitals
- Chrome UX Report (CrUX). Official documentation. https://developer.chrome.com/docs/crux/