競合分析で見つけるコンテンツ機会:他社にない切り口を探る方法
公開データでは、検索結果の1位がクリックの約27%を占め、上位3位で50%超を取ると報告されている。[1][2] 一方で、CTR(クリック率)は業界やSERP(検索結果ページ)の機能(広告、ナレッジパネル、ショートカット等)の有無で大きく変動することが近年示されており、単一カーブの鵜呑みには注意が必要だ。[7] さらに、既存のWebページの多くが検索からほとんどトラフィックを得ていないという統計もある。[3] つまり、同じテーマで作っても角度を外せば見られない。逆に言えば、切り口の精度が勝敗を左右する。ここで言う切り口とは、単なるキーワード選定ではなく、検索意図(ユーザーが達成したい目的)、情報の深さ、提示フォーマット(テキスト、コード、計算機などの提供形態)、更新の鮮度、そしてエンティティ(固有の概念や用語)の網羅性までを含む設計全体である。競合分析を「差分の記述」から「差分の定量化」に移すと、コンテンツの歩留まりが改善しやすいことは実務で広く観察される。以下では、エンジニアリング主導で切り口を数値化し、他社にない機会を見つけ、実装に落とし込む方法を具体的に解説する。
競合分析が見落としがちな本質:意図とフォーマットのギャップ
同じキーワードでも、ユーザーが求める解像度やタスクは異なる。導入検討の比較表を求める人もいれば、実装時のハンズオンや計算ツールを探す人もいる。競合分析が往々にして失敗するのは、キーワードの重複率や文字数の比較で満足し、検索意図とフォーマットの適合度を測らないからだ。意図は質問の種類だけでなく、達成したいタスクと成功条件(ユーザーが「完了」と判断できる証拠)で定義する必要がある。例えば「ログ監視 ベストプラクティス」というクエリは、原理の解説ではなく、可観測性のSLO(サービス水準目標)やサンプルダッシュボード、費用対効果の試算シートまで含んだパッケージを期待している可能性が高い。ここに「他社にない切り口」の余白が生まれる。競合がテキスト記事で上位を取っているなら、同じ内容をより長く書くより、コードと計算機を含んだインタラクティブなフォーマットで意図に直撃させたほうが結果が出やすい。[5][6] 重要なのは、こうした判断を感覚ではなくデータで支えることだ。
データで定義する切り口の5軸
切り口を定義する際は、意図、フォーマット、深さ、鮮度、エンティティの5軸で考える。意図はナビゲーショナルかトランザクショナルかという分類に留めず、タスク完了の証拠(例:計算結果、動作確認済みコード)の有無で測る。[4] フォーマットはテキスト、コード、表、動画、計算ツール、テンプレートなどの実装可能な単位で記述する。深さは見出し構造やコード量、データ点数、数式や証跡の有無で数値化できる。鮮度は更新日と引用データの年次で測り、エンティティは関連固有表現の網羅度で評価する。これらの軸をページごとにスコアリングし、SERP上位と自社アセットを同じ物差しで比較すれば、どの軸にズレがあるかが見える。
技術スタックの前提
実装は身近なツールで十分だ。データ源はGoogle 検索コンソール(GSC)のクエリ・CTR・掲載順位、公開SERPの上位ドキュメント、社内CMSのメタ情報が中心になる。処理系はPythonでテキスト解析(文章の自動処理)と手早いスクレイピング(自動取得)、文章ベクトル化(文を数値ベクトルにして類似性を計算)とクラスタリング(似たものを自動でグループ化)、そしてBigQueryで大規模な結合や期待CTRのベンチマーク計算を担わせる。外部APIはGoogle Custom Search JSON APIやSerpAPIのいずれか、自然言語処理はspaCyまたはSentence Transformersが扱いやすい。あとは計算資源としてメモリ8〜16GB程度と、APIのレート制御ができれば十分だ。
SERPから機会を抽出する解析パイプライン
まずは対象クエリ集合を決める。GSCから過去90〜180日のクエリをエクスポートし、ブランド指名系を除外したうえで、インプレッション(表示回数)上位とコンバージョン寄与の高いクエリを残す。次に、各クエリのSERP上位を収集し、タイトル、見出し、構造化データ、公開日、本文の長さ、コードブロックの有無などを抽出する。抽出データを特徴量に変換し、クラスタリングで意図の近いグループを作る。グループごとに自社と競合のカバレッジを比較し、ギャップをスコア化する。最後に、需要とギャップ、実装難易度、鮮度を統合した機会得点を計算し、ロードマップに落とす。
# コード例1: SERP取得(Google Custom Search API)とレート制御
import os
import time
import requests
from typing import List, Dict
API_KEY = os.environ.get("GCSE_API_KEY")
CX = os.environ.get("GCSE_CX")
def fetch_serp(query: str, num: int = 10) -> List[Dict]:
url = "https://www.googleapis.com/customsearch/v1"
params = {"key": API_KEY, "cx": CX, "q": query, "num": min(num, 10)}
tries = 0
while tries < 3:
try:
res = requests.get(url, params=params, timeout=15)
res.raise_for_status()
data = res.json()
return data.get("items", [])
except requests.RequestException as e:
tries += 1
time.sleep(2 * tries)
return []
queries = ["ログ監視 ベストプラクティス", "可観測性 SLO 目標"]
serp_docs = {q: fetch_serp(q) for q in queries}
次に、取得したURLをクロールし、見出し階層、構造化データ、本文の長さ、コードブロック有無を抽出する。ここでのポイントは、ページの品質を示す代理指標を集めることだ。見出しの深さは深い議論の有無、コードブロックは実装志向の高さ、構造化データは検索エンジンへの明示性を示す。さらに更新日を取り出せれば鮮度評価に効く。
# コード例2: HTML解析で特徴抽出(見出し・構造化データ・コードブロック)
import requests
from bs4 import BeautifulSoup
import extruct
from w3lib.html import get_base_url
headers = {"User-Agent": "Mozilla/5.0 (content-research; +https://example.com)"}
def extract_features(url: str) -> dict:
try:
r = requests.get(url, headers=headers, timeout=20)
r.raise_for_status()
html = r.text
base_url = get_base_url(html, url)
soup = BeautifulSoup(html, "html.parser")
headings = [h.get_text(strip=True) for h in soup.find_all(["h1","h2","h3"])]
code_blocks = len(soup.find_all("pre")) + len(soup.find_all("code"))
text_len = len(soup.get_text(" "))
data = extruct.extract(html, base_url=base_url, syntaxes=["json-ld"]) or {}
schemas = [x.get("@type") for x in data.get("json-ld", []) if isinstance(x, dict)]
return {
"headings": headings,
"code_blocks": code_blocks,
"text_len": text_len,
"schemas": schemas
}
except Exception:
return {"headings": [], "code_blocks": 0, "text_len": 0, "schemas": []}
抽出後は、エンティティの網羅度を測る。対象ドメインのキーフレーズを辞書化するのではなく、spaCyで固有表現を抽出し、頻度と共起から重要度を推定する。さらに、既知の用語リストと照合して抜けを見つける。例えば可観測性なら、SLO、SLA、SLI、分散トレーシング、サンプリング率、ログ集約、メトリクス粒度などの語が自然に立ち上がるはずだ。これが出現していない上位ページが多いとすれば、そこで深い解説の切り口が機能する可能性がある。
# コード例3: spaCyでエンティティ網羅度スコアを計算
import spacy
from collections import Counter
nlp = spacy.load("en_core_web_sm") # 日本語なら ja_core_news_md など
KEY_TERMS = {"SLO", "SLI", "tracing", "sampling", "log aggregation", "cardinality"}
def entity_coverage(text: str) -> float:
doc = nlp(text)
ents = [e.text.lower() for e in doc.ents]
counts = Counter(ents)
hits = sum(1 for k in KEY_TERMS if k.lower() in counts)
return hits / max(1, len(KEY_TERMS))
意図の近さは文章ベクトルで測ると安定する。タイトルと主要見出しをSentence Transformersで埋め込み、クラスタリングで類似クエリ群を作れば、各クラスターに対する自社のカバレッジ密度を可視化できる。クラスター内で上位を占めるフォーマットの傾向も見えるため、テキストか動画か、コード中心か計算機かといった勝ちパターンを抽出できる。
# コード例4: 文章ベクトル化とクラスタリングで意図グルーピング
from sentence_transformers import SentenceTransformer
from sklearn.cluster import HDBSCAN
import numpy as np
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
def cluster_titles(titles: list) -> np.ndarray:
emb = model.encode(titles, normalize_embeddings=True)
clusterer = HDBSCAN(min_cluster_size=8, metric="euclidean")
labels = clusterer.fit_predict(emb)
return labels
# クラスタごとに自社・競合の件数を比較しギャップを測る
需要とギャップだけでは意思決定に足りない。ビジネス側が欲しいのは機会の優先順位だ。ここでGSCのインプレッションとCTR、掲載順位を使い、期待CTRとの差分をベンチマークとして算出する。期待CTRはポジションごとの既知のカーブを用意してもよいし、自社データから滑らかな関数をフィットしてもよい。差分がマイナスであれば、意図やフォーマットの不一致が疑われる。BigQueryに落としておけば、ダッシュボードで週次に自動更新できる。[7]
-- コード例5: BigQueryで期待CTRとの差分を算出
WITH gsc AS (
SELECT query, page, position, ctr, impressions
FROM `project.dataset.search_console`
WHERE date BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY) AND CURRENT_DATE()
),
ctr_curve AS (
SELECT 1 AS position, 0.28 AS exp_ctr UNION ALL
SELECT 2, 0.15 UNION ALL
SELECT 3, 0.11 UNION ALL
SELECT 4, 0.08 UNION ALL
SELECT 5, 0.06 UNION ALL
SELECT 6, 0.05 UNION ALL
SELECT 7, 0.04 UNION ALL
SELECT 8, 0.035 UNION ALL
SELECT 9, 0.03 UNION ALL
SELECT 10, 0.025
)
SELECT
query,
page,
ROUND(AVG(position),1) AS avg_pos,
SAFE_DIVIDE(SUM(ctr * impressions), SUM(impressions)) AS ctr,
ANY_VALUE(c.exp_ctr) AS exp_ctr,
SAFE_DIVIDE(SUM((ctr - c.exp_ctr) * impressions), SUM(impressions)) AS ctr_gap
FROM gsc g
LEFT JOIN ctr_curve c ON CAST(ROUND(g.position) AS INT64) = c.position
GROUP BY query, page
ORDER BY ctr_gap ASC
最後に、機会得点を定義する。需要、ギャップ、難易度、鮮度、エンティティ網羅度、フォーマット適合度を0〜1で正規化し、ビジネスの重み付けで合成する。難易度はドメイン権威だけでなく、必要な実装工数で評価するのが実務的だ。計算は単純でよいが、説明可能性を担保するため加重平均を基本にする。短期売上貢献を重視するならCTRギャップと需要に重みを置き、ブランド想起を重視するならエンティティ網羅と鮮度を厚くする設計が筋が良い。
# コード例6: 機会得点の計算と優先度出し
import math
def normalize(x, min_x, max_x):
if max_x - min_x == 0:
return 0.0
return max(0.0, min(1.0, (x - min_x) / (max_x - min_x)))
# 各スコアは0〜1で入力される想定
def opportunity_score(demand, gap, difficulty, freshness, entity_cov, format_fit,
w=(0.3, 0.3, 0.1, 0.1, 0.1, 0.1)):
wd, wg, wdif, wf, we, wfmt = w
# 難易度は低いほど良いので反転
diff_inv = 1 - difficulty
score = (wd * demand + wg * gap + wdif * diff_inv + wf * freshness + we * entity_cov + wfmt * format_fit)
return round(score, 3)
# 例: 需要0.8, ギャップ0.7, 難易度0.4, 鮮度0.6, エンティティ0.9, フォーマット0.8
print(opportunity_score(0.8, 0.7, 0.4, 0.6, 0.9, 0.8)) # 期待値: 高スコア
このパイプラインを5,000クエリ、上位10件で回すと、およそ5万ページの特徴抽出が必要になる。SerpAPIを使うならAPIコストは1リクエストあたり約1セント前後が目安で、総額は数百ドル規模になりうる。並列度やタイムアウト、失敗時の指数バックオフを適切に設計すれば、週次バッチでも現実的な処理時間に収まるケースが多い。
ベンチマークと誤差管理
精度管理では、クラスタリングの輪郭が最重要だ。クラスタ数を固定しないHDBSCANは便利だが、孤立点の扱いで誤検知が起きやすい。孤立点は低優先に落とすルールを明示し、意図が混ざり合うクエリは人手でサンプリングして確認する。また、期待CTRのカーブは業界やブランド力、SERP機能の影響で異なるため、最初は公開ベンチマークを使いつつ、自社データで上書きする。品質指標として、クエリ10件に1件の目視監査、クラスタ純度の推定、そして公開直後のCTR改善幅の分布を追うとよい。これらをダッシュボードに載せれば、分析の逸脱を早期に検知できる。[7]
他社にない切り口の設計と実証
ギャップが見えたら、切り口を設計し、検証で確かめる。例えば比較系クラスターで競合が表形式の要件羅列に留まっているとき、ベンチマーク用のコードスニペットと再現可能なデータセット、さらにTCO(総保有コスト)を試算する計算機をひとまとまりで提供すると、意図適合が一気に高まる。導入検討のクエリであれば、選定基準の重み付けチェッカーと導入ステップのガントチャート、契約時のチェックリストを設計に含めると、ユーザーのタスク完了に直結する。実装面では、記事本文に貼り付けるだけで完結する軽量なWebコンポーネントとして計算ツールを提供すると、クローラビリティとUXの両立がしやすい。鮮度の面では、毎月自動で更新される指標やSDKの互換性表を組み込むと、時間経過による価値劣化を抑えられる。
検証は時系列のABで行う。公開から2週間のCTR中央値、スクロール深度、コピーイベントやコード複製イベント、計算機の利用完了率といった指標を計測し、同クラスター内の既存記事と比較する。コンバージョンはラストクリックに限定せず、24〜72時間のアトリビューション窓を設けると、実装ハンズオンや診断ツールの貢献が見えやすい。公開事例や業界のレポートでは、インタラクティブ要素やタスク完了型のフォーマットがCTRやエンゲージメントを押し上げる傾向が報告されている。[5][6] もちろん全てのクラスターで同様の成果が出るわけではないが、機会得点の高いものから順に着手すると、投入工数あたりの回収は安定しやすい。
B2B領域のケーススタディ(匿名化)
ログ監視SaaSの文脈を例に、設計アプローチを示す。「ログ ベストプラクティス」クラスターの上位が概説記事に偏っていると仮定する。分析の結果、エンティティ網羅度とフォーマット適合度のスコアが低ければ、SLO計算機、サンプルダッシュボード、障害シナリオ別のアラートルール、ならびに各クラウドの料金モデルを入力できるTCO試算ツールを一式で提供する設計が有効だ。評価では、掲載順位だけでなく、CTRやクリック数、非ブランドのリード指標(MQLやデモ申込など)を併せて観測する。ポイントは、テキストの厚みではなく、ユーザーのタスク完了を保証するフォーマットを先に決め、それに合わせて記事を作ることにある。
運用フレームと組織への落とし込み
継続運用では、解析、制作、検証のサイクルを二週間スプリントで回すとよい。初回にクエリ集合とクラスタの土台を作り、以降は毎週鮮度とギャップを更新して機会得点を再計算する。プロダクトと密に連携し、ロードマップの節目に合わせて計算機やテンプレートを拡張する。権限は、分析パイプラインのオーナー、コンテンツ設計の責任者、実装担当の三役に分け、SLAを定義してボトルネックを潰す。品質は公開ガイドラインで担保し、コード量、引用データ点数、再現手順、更新日、検証ログをメタ情報として必ず残す。これらは将来の再学習材料にもなる。評価はKPIの単発累積ではなく、クラスター単位での経路最適化を重視する。例えば比較クエリはCTRとコンバージョン、ハンズオンクエリはコピーイベントとデモ申込、トラブルシュートは時間節約のNPS寄与、といった具合に、意図に合わせて成果の定義を変えることで、切り口が正しく設計されているかを継続的に判断できる。
まとめ:データで切り口を設計し、タスク完了を提供する
競合分析の価値は、差を眺めることではなく、勝てる角度を定量化することにある。SERPの特徴抽出と意図クラスタリング、エンティティ網羅度の測定、期待CTRとのギャップ評価、そして機会得点による優先順位づけを一連のパイプラインにすれば、議論は早く深くなる。今日から始めるなら、GSCのクエリを90日分取り出し、上位クエリのSERPを100件だけ収集して、見出しとコードブロック、更新日の三点を比べてみてほしい。そこにフォーマットのズレが見えたら、最小構成の計算機やベンチマークコードを添えた1本を作る。公開後はCTRと行動イベントで検証し、成功の型をクラスター全体に水平展開する。あなたの組織が次に作るべきのは、長文ではなく、ユーザーのタスクを完了させる切り口だ。その設計図は、もう手元のデータの中にある。
参考文献
- Backlinko. Google CTR Statistics (New Data). https://backlinko.com/google-ctr-stats
- Backlinko. Google CTR Statistics (Top 3 results share). https://backlinko.com/google-ctr-stats
- Ahrefs. Search Traffic Study: 90.63% of content gets no traffic from Google. https://ahrefs.com/blog/search-traffic-study/
- AIContentfy. Key steps to conducting competitive analysis based on search intent. https://aicontentfy.com/en/blog/key-steps-to-conducting-competitive-analysis-based-on-search-intent
- Search Engine Land. Interactive content and AI-optimized search success. https://searchengineland.com/interactive-content-ai-optimized-search-success-451804
- AlfaRank. The impact of interactive content on SEO metrics and user engagement. https://alfarank.com/the-impact-of-interactive-content-on-seo-metrics-and-user-engagement/
- SISTRIX. Why almost everything you knew about Google CTR is no longer valid. https://www.sistrix.com/blog/why-almost-everything-you-knew-about-google-ctr-is-no-longer-valid/