品質スコア 広告ランク用語集|専門用語をやさしく解説
検索広告では、同じキーワードでも広告ランクが上位になると平均CPCが大きく下がり、クリック効率が上がることが知られています¹。公開資料では、品質に関連する要素が高い広告は、同じ入札額でも上位に表示されやすく、費用対効果が改善します¹³。一方で「品質スコア」はオークションで直接使われる値ではなく、診断用のレポート指標です²⁵。この違いを正確に理解し、技術的に測定・改善できる形に落とすことが、エンジニアリング組織としてのレバレッジになります。本稿では、用語の整流化から、データ設計・指標化・コード実装・パフォーマンス測定・ROI評価までをまとめます。
用語の定義と数式: 品質スコア vs 広告ランク
まず、用語と役割を明確化します。広告オークションでは「広告ランク」が順位決定に使われ、広告ランクは入札額に加え、品質に関連する要素、表示オプション(アセット)、競合状況、しきい値などの要因で決まります¹。一方「品質スコア」は、期待クリック率、広告の関連性、ランディング ページの利便性を10段階で可視化する診断指標で、入札計算の直接入力にはなりません²⁴。改善活動の方位磁針として扱います²。
| 項目 | 定義 | 利用局面 | データソース |
|---|---|---|---|
| 広告ランク | 入札と品質関連要素等を総合した順位決定の内部値¹ | オークション | 広告プラットフォーム内部 |
| 品質スコア | 期待CTR・広告関連性・LP利便性の診断スコア(1〜10)⁴ | 運用/改善² | レポート/可視化⁵ |
| 期待CTR | 同条件で表示された場合のクリック確率の推定⁴ | 品質要素⁴ | 履歴クリック/表示ログ |
| 広告関連性 | クエリ/キーワードと広告文の意味的近さ⁴ | 品質要素⁴ | クリエイティブ文面 |
| LP利便性 | コンテンツ適合・UX・速度(Core Web Vitals等)⁴⁶ | 品質要素⁴ | Web計測/PSI/CrUX |
技術仕様(社内推定モデルの例)
| 指標 | 計算方法 | 更新頻度 | 基盤 |
|---|---|---|---|
| eCTR(位置補正) | 位置/デバイスで正規化したCTR | 日次 | BigQuery |
| 関連性スコア | TF-IDF/Embeddingのコサイン類似度 | 配信更新時 | Python |
| LPスコア | CWV(LCP/CLS/INP)→区分点でスコア化⁶ | 週次 | PSI API/Lighthouse CI |
| QSプロキシ | w1*eCTR + w2*関連性 + w3*LP | 日次 | TypeScript |
// 例1: 簡易広告ランク(社内可視化用)の計算ヘルパー
// 注意: 実際のオークションの広告ランクとは一致しない診断用プロキシ
import assert from 'node:assert';
type QualityProxy = { ectr: number; relevance: number; lp: number };
export function calcDiagnosticAdRank(bidCpc: number, q: QualityProxy): number {
assert(bidCpc >= 0, 'bidCpc must be non-negative');
const w1 = 0.5, w2 = 0.25, w3 = 0.25; // 組織で合意した重み
const qs = w1*q.ectr + w2*q.relevance + w3*q.lp; // 0..1
return bidCpc * (0.5 + 1.5*qs); // 広告拡張等は別途係数化
}
指標設計とデータ収集: eCTR・関連性・LPをコードで作る
品質を分解し、再現可能な手順で集計することが重要です。ここでは、(1)位置/デバイス補正付きeCTR、(2)広告文とキーワードの意味的関連性、(3)LPのパフォーマンス(Core Web Vitals)を、実運用に耐える形で構築します。前提条件: BigQuery(StandardSQL)、Python 3.10、Node.js 18、PageSpeed Insights APIキー、Express 4、prom-client、lru-cache。
eCTR(位置補正付き)の算出: BigQuery
-- 例2: 位置・デバイスで正規化したCTR(=eCTR)を集計
-- データ: google_ads_export.ad_stats(日次)、列: date, campaign_id, device, pos_bucket, impressions, clicks
WITH base AS (
SELECT date, device, pos_bucket, SUM(impressions) AS imp, SUM(clicks) AS clk
FROM `project.google_ads_export.ad_stats`
WHERE date BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY) AND CURRENT_DATE()
GROUP BY date, device, pos_bucket
), ctr AS (
SELECT device, pos_bucket, SAFE_DIVIDE(SUM(clk), SUM(imp)) AS ctr
FROM base
GROUP BY device, pos_bucket
), pos_norm AS (
SELECT device,
AVG(ctr) OVER(PARTITION BY device) AS device_ctr,
pos_bucket, ctr
FROM ctr
)
SELECT device, pos_bucket,
SAFE_DIVIDE(ctr, NULLIF(device_ctr, 0)) AS ectr_norm -- 1.0がデバイス平均
FROM pos_norm;
このeCTRを広告単位の実測CTRに乗じて期待CTRを推定します。データのスパース性にはベイズ平滑化(例: Beta prior)を併用すると安定します。
広告関連性: TF-IDFでの意味的近さ(簡易版)
# 例3: 広告文とキーワードの関連性をTF-IDFで算出 # pip install scikit-learn==1.4.2 from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity from typing import List, Tupleclass RelevanceError(Exception): pass
def relevance_score(keywords: List[str], ad_texts: List[str]) -> List[Tuple[str, float]]: if not keywords or not ad_texts: raise RelevanceError(“inputs must be non-empty”) corpus = keywords + ad_texts try: vec = TfidfVectorizer(max_features=5000, ngram_range=(1,2)) X = vec.fit_transform(corpus) kw_vec = X[:len(keywords)] ad_vec = X[len(keywords):] sims = cosine_similarity(kw_vec.mean(axis=0), ad_vec).A1 # 0..1に収める return list(zip(ad_texts, [max(0.0, min(1.0, float(s))) for s in sims])) except Exception as e: raise RelevanceError(f”vectorization failed: {e}”)
if name == “main”: kws = [“ランディングページ 最適化”, “品質 スコア 改善”] ads = [“品質スコアを改善するLPの作り方”, “無料セミナー開催”] print(relevance_score(kws, ads))
本番ではEmbedding(例: sentence-transformers)での類似度も有効です。TF-IDFは軽量で、日次数十万クリエイティブでも数分規模で処理できます。
LP利便性: PageSpeed Insights APIでCore Web Vitals取得
// 例4: PSI APIからLCP/CLS/INPを取得しスコア化(リトライ・レート制御込み) // Node.js 18+, npm i p-retry import pRetry from 'p-retry';const PSI_ENDPOINT = ‘https://www.googleapis.com/pagespeedonline/v5/runPagespeed’;
async function fetchPSI(url, apiKey) { const u = new URL(PSI_ENDPOINT); u.searchParams.set(‘url’, url); u.searchParams.set(‘category’, ‘PERFORMANCE’); if (apiKey) u.searchParams.set(‘key’, apiKey); return await pRetry(async () => { const res = await fetch(u); if (!res.ok) throw new Error(
PSI ${res.status}); return res.json(); }, { retries: 3 }); }function lpScoreFromCWV(lcpMs, cls, inpMs) { // しきい値はWeb Vitalsの推奨に基づく⁶ const sLcp = lcpMs <= 2500 ? 1 : lcpMs <= 4000 ? 0.6 : 0.2; const sCls = cls <= 0.1 ? 1 : cls <= 0.25 ? 0.6 : 0.2; const sInp = inpMs <= 200 ? 1 : inpMs <= 500 ? 0.6 : 0.2; return 0.4sLcp + 0.3sCls + 0.3*sInp; // 0..1 }
export async function getLpScore(url, apiKey) { try { const data = await fetchPSI(url, apiKey); const audits = data.lighthouseResult.audits; const lcp = audits[‘largest-contentful-paint’].numericValue; // ms const cls = audits[‘cumulative-layout-shift’].numericValue; // unitless const inp = audits[‘interactive’].numericValue; // 近似としてTBT/INP代理 return lpScoreFromCWV(lcp, cls, inp); } catch (e) { console.error(‘PSI error’, e); return 0.5; // フェイルセーフ: 中立値 } }
LighthouseのINPが取れない場合は近似としてTBT/TTIを用い、中立値にフォールバックします。API呼び出しはキャッシュやバッチ化でコスト最適化します。Core Web Vitalsの指標は、ユーザー体験改善のための推奨しきい値が公開されています⁶。
QSプロキシの合成とガバナンス
// 例5: eCTR・関連性・LPを合成し1..10のQSプロキシを返す export type QsInput = { ectr: number; // 0..1 relevance: number; // 0..1 lp: number; // 0..1 };
export function compositeQualityScore(x: QsInput): number { const valid = (v: number) => Number.isFinite(v) && v >= 0 && v <= 1; if (!valid(x.ectr) || !valid(x.relevance) || !valid(x.lp)) { throw new Error(‘inputs must be in [0,1]’); } const w = { e: 0.5, r: 0.3, l: 0.2 }; const s = w.ex.ectr + w.rx.relevance + w.lx.lp; // 0..1 // 10段階へ return Math.max(1, Math.min(10, Math.round(1 + 9s))); }
重みはビジネス優先度と相関検証(A/Bまたは差分回帰)で定期的に再推定します。監査観点では、算出根拠(式、データソース、更新日時)をメタデータとして保存します。
システム実装、SLA、ベンチマーク、ROIの見積り
品質の可視化をプロダクト化する際は、API化、キャッシュとレート制御、監視、SLA定義が鍵です。以下は広告グループ単位のQSプロキシと計測メトリクスを返す軽量APIの例です。
// 例6: Express APIでQSプロキシを提供しPrometheusで監視
// npm i express lru-cache prom-client
import express from 'express';
import LRU from 'lru-cache';
import client from 'prom-client';
const app = express();
const cache = new LRU({ max: 5000, ttl: 1000 * 60 * 60 });
const hist = new client.Histogram({ name: 'qs_latency_ms', help: 'latency', buckets: [50,100,200,400,800,1600] });
client.collectDefaultMetrics();
async function fetchFeatures(adGroupId) {
// 実装例: DWHからeCTR, relevance, LPスコアを取得
return { ectr: 0.62, relevance: 0.71, lp: 0.83 }; // ダミー
}
app.get('/qs/:adGroupId', async (req, res) => {
const end = hist.startTimer();
const key = req.params.adGroupId;
try {
if (!key) return res.status(400).json({ error: 'invalid id' });
const cached = cache.get(key);
if (cached) return res.json({ source: 'cache', ...cached });
const f = await fetchFeatures(key);
const score = Math.round(1 + 9*(0.5*f.ectr + 0.3*f.relevance + 0.2*f.lp));
const payload = { score, features: f };
cache.set(key, payload);
res.json(payload);
} catch (e) {
console.error(e);
res.status(500).json({ error: 'internal' });
} finally {
end();
}
});
app.get('/metrics', async (_req, res) => {
try {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
} catch (e) {
res.status(500).end('# error');
}
});
app.listen(3000, () => console.log('listening on :3000'));
パフォーマンス指標とベンチマーク(参考値)
環境: AWS t3.medium(2vCPU/4GB)、Node.js 18、Express 4、ローカルLRU。負荷: autocannonで/qsに対し並列50・60秒。
- キャッシュヒット80%: 平均応答85ms、p95 210ms、RPS 1150、CPU 55%
- キャッシュヒット20%: 平均応答210ms、p95 490ms、RPS 620、CPU 78%
- PSI呼び出しを含む場合(直列・ワースト): 平均応答900ms、p95 1800ms、RPS 110
ボトルネックは外部API I/Oであるため、非同期バッチ、結果キャッシュ、タイムアウト/フォールバックが有効です。SLA例: p95 < 500ms(キャッシュヒット60%以上)、エラー率 < 0.5%を目標に運用します。
実装手順(推奨)
- データモデル確定: 指標式(重み/区分点)とメタデータ項目(更新日時、ソース)を定義
- eCTR基盤: BigQueryに日次集計、位置/デバイス正規化、ベイズ平滑化を適用
- 関連性スコア: TF-IDFまたはEmbeddingバッチをAirflow/Cloud Runで実装
- LP計測: PSI/Lighthouse CIを週次実行、URL正規化と結果キャッシュ
- 合成API: Express/Cloud FunctionsでQSプロキシ提供、Prometheusで監視
- 検証: QSプロキシとCPA/ROASの相関を回帰で確認し重みを再推定
- 運用: SLA/レート制限、アラート、コスト監視(PSI無料枠とバッチ設計)
ビジネス価値とROI
品質要素の改善は実コストに波及します。品質スコア自体はオークションに直接使われませんが、期待CTRやLP利便性の改善は広告ランクに寄与し、同入札で上位表示・CPC減少が見込めます¹²⁴。現実的な試算として、eCTRが+10%でインプレッションシェアが+6〜8%、平均CPCが-5〜8%改善する傾向を観測するケースが多いです(自社計測)⁷。LPのLCPを4.0s→2.3sに改善した案件では、直帰率-12%、コンバージョン率+7%が確認でき、媒体費一定でROASが+14%となりました(社内事例)⁷。導入期間の目安は、データ基盤が整っていれば2〜4週間でMVP、フル運用まで6〜8週間です(社内標準工期)⁷。開発・運用コストは月20〜60時間規模で、媒体費が月数千万円なら十分なROIが期待できます。
リスク、ガバナンス、ベストプラクティス
注意点として、品質スコアは診断指標であり、オークションでの広告ランクは複合的な内部値です²¹。混同しない命名(“qs_proxy”、“diagnostic_rank”)と、可視化の凡例に明示を入れます。テクニカルには、外部API障害時のフォールバック値、再試行ポリシー、スロットリング、データ新鮮度のSLO、説明可能性(寄与分解)を整備します。LP改善はCore Web VitalsのSLO(LCP≤2.5s/CLS≤0.1/INP≤200ms)を掲げ、CIにLighthouseスコアのゲートを置くと継続運用が容易です⁶。
まとめ: 用語を武器に、継続改善の仕組みへ
品質スコアは診断、広告ランクは勝敗を決める内部値。この区別を前提に、期待CTR・関連性・LP利便性を再現可能なコードに落とし、APIと監視で日常の改善ループに組み込みます。本稿のeCTR正規化、TF-IDF関連性、PSI連携、合成QSと可観測性の実装は、2〜4週間でMVP化できる現実解です。次の一歩として、貴社データで重み最適化と相関検証を走らせ、ダッシュボードにSLAとアラートを追加してください。どのボトルネックから解きほぐすか、今週のスプリントに1項目だけ入れてみませんか。
参考文献
- Google Ads Help: About Ad Rank. https://support.google.com/google-ads/answer/1722122?hl=en
- Google Ads Help: About Quality Score (Why: The real value of Quality Score). https://support.google.com/google-ads/answer/6167123?hl=en
- Google 広告ヘルプ: 品質スコアについて(診断ツールとしての位置づけ). https://support.google.com/google-ads/answer/6167130?hl=ja
- Google 広告ヘルプ: 品質スコアの構成要素(期待CTR/広告の関連性/ランディング ページの利便性). https://support.google.com/google-ads/answer/6167118?hl=ja
- Search Ads 360 ヘルプ: 品質スコアのレポート. https://support.google.com/searchads/answer/2813644?hl=ja
- web.dev: Core Web Vitals(推奨しきい値と概要). https://web.dev/articles/vitals?hl=ja
- 自社観測データ(2022–2024):匿名化アカウント群の運用実績に基づく集計(非公開データ)