• #SEO
  • #Nuxt
  • #Jリーグ
  • #設計
financial-data完了

決定事項

動的ルーティングを採用(2軸構造)

項目決定内容
URL構造ハブ + クラブ別 + 年度別の3層構造
index.vuePhase 1では現行維持、Phase 2でハブ化
無効slug時404エラー(一覧へのリンク付きエラーページ)
OGP画像クラブカラー + テキストのみ(ロゴ不使用)

URL設計(確定)

/financial-quiz/jleague                     # ハブページ(Phase 2で実装)
/financial-quiz/jleague/club/[club]         # クラブ別の時系列財務
/financial-quiz/jleague/year/[year]         # 年度別のリーグ比較(Phase 3)

ファイル構造

apps/web/app/pages/financial-quiz/jleague/
├── index.vue              # Phase 1: 現行維持 → Phase 2: ハブページ化
├── club/
│   └── [club].vue         # クラブ別: /jleague/club/kashima-antlers
└── year/
    └── [year].vue         # 年度別: /jleague/year/2024(Phase 3)

各ページの役割

ページ役割
/jleagueハブ。2軸の入口とクラブ一覧-
/jleague/club/[club]クラブの時系列財務データ。年度は矢印キーで切替/jleague/club/kashima-antlers
/jleague/year/[year]年度別のリーグ比較(スポンサー/入場料/観客動員など)/jleague/year/2024

ハブページの構成(Phase 2で実装)

/financial-quiz/jleague(index.vue)

コンテンツ

  1. 2つの大きなカード
    • 「クラブ別の財務時系列」→ 人気クラブまたはランダムへリンク
    • 「年度別のリーグ比較」→ 最新の利用可能年度へ動的リンク
  2. クラブ一覧カード
    • 62クラブへのリンク
    • 検索/フィルタ機能(オプション)

: カードのリンク先は固定値ではなく、データから最新年度・利用可能年度を動的に取得する

SEOメタ

useSeoMeta({
  title: 'Jリーグ財務データ | クラブ別・年度別分析',
  description: 'Jリーグ全62クラブの財務諸表を可視化。クラブ別の時系列分析、年度別のリーグ比較が可能。',
})

クラブ別ページ(/jleague/club/club

機能

  • 現在のindex.vueのロジックを移植
  • 年度切り替えは矢印キー(◀ ▶)でページ内操作
  • 年度はURLに含めない(シンプルなURL + 年度切替UXを優先)

SEOメタ

useSeoMeta({
  title: `${club.name}の財務データ | Jリーグ財務分析`,
  description: `${club.name}の財務諸表(BS・PL)を比例縮尺で可視化。営業利益増減分析も。`,
  ogTitle: `${club.name} - 財務データ`,
})

無効slugの挙動

存在しないクラブ名(例:/jleague/club/invalid-club)へのアクセス時:

404エラーを返す(302リダイレクトはソフト404扱いになりSEO的に不利)

// [club].vue
const club = clubs.find(c => c.ticker === route.params.club)
if (!club) {
  // 404エラーを返す(一覧へのリンク付きエラーページを表示)
  throw createError({
    statusCode: 404,
    statusMessage: 'クラブが見つかりません',
    data: {
      suggestion: '/financial-quiz/jleague'  // エラーページで一覧リンクを表示
    }
  })
}

年度別ページ(/jleague/year/year

機能(Phase 3で実装)

  • 指定年度の全クラブ比較
  • 比較軸の例:
    • スポンサー収入ランキング
    • 入場料収入ランキング
    • 観客動員数ランキング
    • 営業利益ランキング

SEOメタ

useSeoMeta({
  title: `${year}年度 Jリーグ財務比較 | 全クラブランキング`,
  description: `${year}年度のJリーグ全クラブ財務データを比較。売上高、営業利益、観客動員数などでランキング。`,
})

OGP画像の動的生成

方針

  • クラブロゴは使用しない(許諾なし)
  • クラブカラー + テキストベースで生成

実装

defineOgImage({
  component: 'JLeagueOgImage',
  clubName: club.name,
  clubColor: club.primaryColor,  // クラブカラー(背景/アクセント)
})

OGP画像に含める要素

要素説明
クラブ名大きく中央に表示
クラブカラー背景色またはアクセントカラー
「財務データ」の文言コンテンツの種類を明示
サイト名例: 「eurekapu.com」

生成タイミング

  • ビルド時(SSG): 62クラブ分を事前生成
  • Nuxt OG Imageのプリレンダリング機能を使用

現状の課題(参考)

現在の実装

URL: /financial-quiz/jleague(固定)

ファイル: apps/web/app/pages/financial-quiz/jleague/index.vue

// クラブ選択は内部状態で管理(URLに反映されない)
const selectedClubIndex = ref(1)
const selectedClub = computed(() => clubs.value[selectedClubIndex.value])

// SEOメタ情報は固定
useSeoMeta({
  title: 'Jリーグクラブ財務データ',
  description: 'Jリーグクラブの財務諸表を比例縮尺で可視化。BS・PLの推移を直感的に理解。',
})

問題点

問題詳細
SEO効果が低い62クラブすべてが1つのURLに集約
URLで共有不可特定クラブの状態を共有できない
OGP固定汎用的なタイトルのみ
インデックス効率1ページとしてしかインデックスされない

実装ステップ

Phase 1: クラブ別ページ + 現行index維持

  1. ディレクトリ構造作成
    • apps/web/app/pages/financial-quiz/jleague/club/[club].vue
  2. 既存ロジックの移植
    • index.vueの内容をclub.vueへコピー
    • ルートパラメータからクラブを取得するよう変更
    • index.vueは現行のまま維持(Phase 2でハブ化)
  3. SEOメタの動的生成
    • クラブ名を含むtitle/description
  4. OGP画像コンポーネント作成
    • components/OgImage/JLeagueOgImage.vue
  5. 無効slug時の404実装
    • createErrorで404を返す
    • エラーページに一覧へのリンクを表示
  6. SSG設定
    • 62クラブのルートをプリレンダリング対象に追加

Phase 2: ハブページ化

  1. index.vueをハブに改修
    • 2つの入口カード(リンク先は動的に決定)
    • クラブ一覧リンク
    • 現行の財務表示機能は削除

Phase 3: 年度別ページ(将来)

  1. 年度別ページの実装
    • apps/web/app/pages/financial-quiz/jleague/year/[year].vue

SSG設定

// nuxt.config.ts
// 注: データソースは実際のファイル形式に合わせる
// - JSONの場合: import clubs from './data/jleague-clubs.json'
// - TSの場合: import { jleagueClubs } from './data/jleague-clubs'
// - composableの場合: useJLeagueData()から取得

import { jleagueClubs } from './data/jleague-clubs'

export default defineNuxtConfig({
  nitro: {
    prerender: {
      routes: [
        '/financial-quiz/jleague',
        ...jleagueClubs.map(c => `/financial-quiz/jleague/club/${c.ticker}`),
        // Phase 3で追加
        // ...years.map(y => `/financial-quiz/jleague/year/${y}`)
      ]
    }
  }
})

期待される効果

指標BeforeAfter(期待)
インデックスページ数163+(ハブ + 62クラブ + 年度別)
「鹿島アントラーズ 財務」検索ランディングしにくい専用ページにランディング
SNS共有時のOGP汎用的クラブ名・カラー入りの具体的な画像
URLの共有性不可クラブ指定で共有可能
将来拡張性低い年度別比較など追加容易

次のアクション

Phase 1(完了)

  • クラブのticker一覧を確認(英語slug用)
  • club/[club].vueのスケルトン作成
  • 既存index.vueのロジックをコピー・移植
  • SEOメタの動的生成実装
  • OGP画像コンポーネント作成(テキスト+カラーのみ)
  • 無効slug時の404実装
  • SSGプリレンダリング設定

Phase 2(完了)

  • index.vueをハブページに改修
  • 2つの入口カード(動的リンク)+ クラブ一覧

Phase 3(将来)

  • year/[year].vueの設計・実装
  • 年度別リーグ比較機能