Free プラン / 匿名ユーザーに対して Google AdSense 広告を表示する際の、対象ページ・スロット配置・広告形式・CLS 対策を定義する。
本仕様は ビジネスモデル・課金設計 の「ad-free を有料プランの付加価値にする」方針を実装に落とし込んだものであり、親 Issue #230 の実装着手前に配置設計を確定させる目的で作成する。
1. 概要
- 広告プロダクト: Google AdSense(手動配置 /
<ins class="adsbygoogle">)
- Auto Ads は採用しない。理由は以下の 3 点:
- CLS 制御: 手動配置なら広告枠の
minHeight を固定できる
- 配置品質: Auto Ads はコンテンツ構造を無視してオーバーレイを挿入 するため UX を損なう
- ポリシー準拠: コンテンツ比率・誤クリック誘導を自前でコントロールする必要がある
- Publisher ID:
ca-pub-2848807786857797(公開情報、apps/web/public/ads.txt に記載)
- 収益化戦略上の位置付け: Free プランの持続可能性を広告収益で担保し、有料プラン(Plus / Pro)は「広告非表示」を付加価値として訴求する(
apps/web/src/views/home/ui/pricing-section/pricing-section.tsx の adFree 行と整合)
2. 表示対象ユーザー
判定マトリクス
| ユーザー状態 | plan | 広告表示 |
|---|
| 匿名(未ログイン) | — | 表示 |
| ログイン済 Free | free | 表示 |
| ログイン済 Plus | plus | 非表示 |
| ログイン済 Pro | pro | 非表示 |
判定ロジック
- 新設する
useShouldShowAds() フックで判定する(実装は #232)
- 内部で既存の
useUserSubscription()(apps/web/src/features/user-subscription/model/use-user-subscription/use-user-subscription.ts)を利用する
- 匿名ユーザー時は
useUserSubscription() の query が無効(enabled=false)になるため、フォールバックとして Free 相当で扱う
- プランの定義は
packages/shared/src/user/user-subscription/user-subscription.ts の planSchema = z.enum(["free", "plus", "pro"]) に準拠
3. 対象ページとスロット配置
広告を表示するのは /search と /videos/[videoId] の 2 ページのみ。
3.1 /search(検索結果ページ)
- 主要導線:
/(ヘッダー検索 or CTA)→ /search?q=...、または検索履歴・直接リンク
- ページ特性: サービス内で最長のスクロールを生むページ。検索結果を Grid 形式で無限スクロール風に表示するため、ユーザー滞在時間が長い
- 配置の狙い: スクロール深度が深いユーザーを自然な位置で捕捉する
スロット一覧
| ID | 位置 | 導線トリガー | 形式 | 最小高 |
|---|
search-result-midroll | 結果グリッドの 3 件目と 4 件目の間(以降 5 件ごとに繰り返し) | 検索実行 → 結果をスクロール中に自然視界に入る | インフィード広告 | 280px |
search-result-bottom | 結果リスト末尾、ページネーション直前 | スクロール終端 | レスポンシブディスプレイ | 280px |
- 空状態(0 件ヒット、未検索)時は
search-result-bottom のみ表示し、search-result-midroll は表示しない
search-result-midroll の繰り返し頻度は AdSense の「1 ページあたりの広告比率」ポリシーを侵さない範囲で調整する(初期値 5 件ごと、実測で調整)
- インフィード広告は検索結果カードと視覚的に近いスタイルにするが、「広告」ラベルを上部に必ず表示する(ポリシー準拠、ユーザー錯誤防止)
3.2 /videos/[videoId](動画詳細ページ)
- 主要導線:
/search → 結果カードクリック → /videos/[videoId]
- ページ特性: YouTube プレイヤー + 字幕ビューア + マッチハイライトで構成される縦長ページ
- 配置の狙い: プレイヤー視聴開始時と字幕読了後の 2 点で広告に触れさせる
スロット一覧
| ID | 位置 | 導線トリガー | 形式 | 最小高 |
|---|
video-detail-below-player | YouTube プレイヤーと字幕ビューアの間 | 再生開始時にスクロールなしで視界に入る | レスポンシブディスプレイ | 250px |
video-detail-below-subtitle | 字幕ビューア末尾、関連動画セクション上 | 字幕読了後、次アクション前 | マルチプレックス | 300px |
video-detail-below-player は プレイヤー直下ゆえに誤クリックのリスクが高いため、上下に margin: 16px 以上の余白を設ける
- 字幕ビューア 内部にミドルイン広告を挿入する案は、字幕読書体験を分断するため 初回実装では見送る
- 右サイドバーが存在しても、初回実装では広告枠として利用しない(レイアウトの視認性を優先)
3.3 対象外ページとその理由
| ページ | 除外理由 |
|---|
/(ホーム) | CTA / Pricing への導線が密集しており、広告で離脱率を増やしたくない |
/account/* | 集中度の高い短尺ページ、ユーザーの作業体験を妨げたくない |
/login | 認証ページは摩擦を最小化する |
/admin/* | 運用管理用、対象外 |
/privacy, /terms, /contact | 規約系・低流量、表示メリットが小さい |
/changelog | 低流量、運用コストに見合わない |
4. 広告形式と CLS 対策
4.1 使用する広告形式