• #FAQ
  • #JSON-LD
  • #構造化データ
  • #Vue.js
  • #コンポーネント設計
開発tax-lpメモ

税理士LP FAQ共通化と業種別質問カード

2026-02-08の税理士LP開発作業の記録。複数業種のランディングページにおいて、FAQ管理の一元化、業種別質問カード、パンくずコンポーネント、JSON-LD構造化データ対応、表現の全面修正、業種別faviconの作成を行った。


1. FAQ共通化のアーキテクチャ設計

課題: FAQの散在

これまで各業種のFAQは、それぞれのfrontmatter(faqセクション)やコンポーネント内にインラインで記述されていた。同じ内容(「初回相談は無料ですか?」「顧問料はいくらですか?」など)が複数箇所に重複しており、修正時にすべてを手作業で更新する必要があった。

税理士紹介セクション(プロフィール情報など)が既に一箇所で管理されていたのと同様に、FAQも一元管理したいという方針が決まった。

設計: app/config/faq.ts による一元管理

FAQデータを app/config/faq.ts に集約するアーキテクチャを採用した。

app/config/faq.ts
├── 共通FAQ(全業種共通の質問と回答)
│   ├── 初回無料相談について
│   ├── 顧問料の目安
│   ├── オンライン対応
│   ├── 対応エリア
│   └── ...
└── 業種別FAQ(業種固有の質問と回答)
    ├── 業種A: 業種A特有のFAQ
    ├── 業種B: 業種B特有のFAQ
    ├── 業種C: 業種C特有のFAQ
    ├── 業種D: 業種D特有のFAQ
    └── 業種E: 業種E特有のFAQ

TypeScriptのインターフェースを定義し、型安全にFAQを管理する構造にした。各業種のコンポーネント(例: IndustryAFaq.vue, IndustryBFaq.vue)は、この設定ファイルからデータを読み込んで表示する。

実装手順

  1. app/config/faq.ts を新規作成 -- interfaceとデータを定義
  2. content.config.ts を更新 -- FAQスキーマの調整
  3. composableを更新 -- FAQ取得ロジックの共通化
  4. 既存FAQコンポーネントを更新 -- 3つの既存コンポーネントをconfig参照に変更
  5. 新規FAQコンポーネントを作成 -- 追加業種用のFAQコンポーネント
  6. frontmatterから faq セクションを削除 -- 各業種の index.md からインラインFAQを除去

各業種のLandingコンポーネントにFAQコンポーネントを組み込み、テンプレート別のビジュアルスタイルは維持しつつ、データソースを統一した。

メリット

  • FAQの修正が1ファイルで完結する
  • 共通質問の追加・削除が全業種に即座に反映される
  • 業種固有のFAQも同じ構造で管理でき、見通しがよい
  • 型チェックにより、必須フィールドの漏れを防止できる

2. パンくずコンポーネント(LpBreadcrumb.vue)

背景

記事一覧ページ(articles/index.vue)や記事詳細ページ(articles/[slug].vue)、通常レイアウトに、パンくずナビゲーションがインラインで記述されていた。共通コンポーネントとして切り出すことで、スタイルの統一と保守性を改善した。

実装

LpBreadcrumb.vue コンポーネントを作成し、以下の3箇所で利用する形に置き換えた。

  • articles/index.vue -- 記事一覧ページ
  • articles/[slug].vue -- 記事詳細ページ(インラインのパンくずを置換)
  • 通常レイアウト -- インラインのパンくずを置換

パンくずは業種名やページタイトルに応じて動的に生成される。


3. 業種別質問カード(IndustryQuestions)

コンセプト

各業種のランディングページに「よくある疑問」として、その業種特有の悩みや質問を提示するカードセクションを追加した。FAQとは異なり、こちらは「税理士に相談する前にユーザーが抱えている疑問」を視覚的に提示し、相談への導線を作る役割を持つ。

各業種分の実装

各業種について IndustryQuestions コンポーネントを作成した。

業種コンポーネント質問例
業種AIndustryAQuestions.vue「スタッフの給与計算が面倒」「経費をどこまで落とせる?」
業種BIndustryBQuestions.vue「物件ごとの収支が把握できない」「青色申告と白色申告の違いは?」
業種CIndustryCQuestions.vue「請求書の管理が追いつかない」「インボイス制度にどう対応する?」
業種DIndustryDQuestions.vue「開業届を出すタイミングは?」「経費の線引きがわからない」

各コンポーネントは対応するLandingコンポーネント内に、FAQセクションの直前に配置した。

frontmatterへの反映

各業種の index.md のfrontmatterに industryQuestions フィールドを追加し、質問データをコンテンツ側からも管理できる構造にした。


4. 記事導線(LatestArticles)コンポーネントの追加

目的

一部の業種のランディングページに、関連記事へのリンクセクションを追加した。既に LatestArticles コンポーネントがある業種もあったが、未実装の業種があった。

実装

未実装だった業種用に LatestArticles コンポーネントを新規作成し、対応するLandingコンポーネントに組み込んだ。業種向けの記事(確定申告のポイントなど)へのリンクを表示する。


5. 記事コンテンツの追加

特定の業種向けのコンテンツを充実させるため、記事を3件作成した。記事一覧やLatestArticlesコンポーネントから参照される。


6. FAQ構造化データ(JSON-LD)

目的

Google検索結果でFAQリッチスニペットを表示させるため、FAQセクションにJSON-LD構造化データを追加した。

実装

index.vue にFAQPageスキーマのJSON-LDを出力する処理を追加した。app/config/faq.ts のデータから動的に FAQPage 型の構造化データを生成し、useHead<script type="application/ld+json"> として埋め込む。

// FAQPage 構造化データの概要
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "初回相談は無料ですか?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "はい、初回のご相談は無料です。..."
      }
    }
    // ... 各FAQをQuestion/Answer形式で出力
  ]
}

SSGでプリレンダリングされるため、クローラーがJavaScriptを実行しなくても構造化データを読み取れる。


7. 「節税」「税務戦略」「手取り最大化」表現の全面削除

理由: 税理士倫理と誤解防止

税理士は税務の専門家として、法令に基づいた適正な申告を支援する立場にある。「節税」という表現はグレーゾーンを攻めるような印象を与えかねず、「税務戦略」も同様に攻撃的なニュアンスを持つ。「手取り最大化」は税負担を不当に軽減するかのような誤解を招く可能性がある。

税理士の広告規制(税理士法第43条・日本税理士会連合会の広告規定)の観点からも、誇大な表現や誤解を招く表現は避けるべきとされている。

対応範囲

LP本体の全コンテンツ(各業種の index.md frontmatter + 本文、コンポーネント、ページ)を対象に、以下の表現を削除・言い換えた。

修正前修正後
節税適正な申告 / 税務サポート
税務戦略税務、丸ごとおまかせ
手取り最大化帳簿管理・申告の負担軽減

修正の方針

各業種のLP全体を対象に、上記の表現を一括で言い換えた。

  • キャッチコピーやヒーローセクションの見出しは、具体的なサービス内容に言い換え
  • 業務範囲外の表現(例: 税理士の業務外となる表現)は、正確なサービス内容に修正
  • 一部の業種では「節税」「手取り最大化」の使用頻度が多かったため、帳簿管理や確定申告の負担軽減といった具体的な表現に置換

記事(articles)内の「節税」は事実の説明として使われているケースが多いため、LP本体のみを対象とした。


8. 業種別favicon SVGの作成

背景

全業種で同じ「税」の文字のfaviconを使っていたため、ブラウザのタブバーで複数業種を開いた際に区別がつかなかった。

作成したfavicon

各業種ごとにアイコンとテーマカラーの異なるSVG faviconを作成した。ハサミ、ビル、コード(</>)、ペイント(パレット)、ブリーフケースなど、業種の特徴を表すアイコンを採用している。

動的切り替え

SSGのため、各業種ページでプリレンダリング時にfaviconのパスが確定する。app.vue で業種判定を行い、useHead で対応するfaviconを動的に設定する。

<!-- app.vue での favicon 動的設定(概要) -->
<script setup>
const route = useRoute()
const industry = computed(() => {
  // ルートパスから業種を判定
})

useHead({
  link: [
    {
      rel: 'icon',
      type: 'image/svg+xml',
      href: computed(() => `/favicon-${industry.value}.svg`)
    }
  ]
})
</script>

nuxt.config.ts の静的favicon指定は削除し、動的設定に一本化した。

確認

Chrome DevToolsで各業種ページを開き、以下を検証した。

  • favicon link タグの href が業種に応じて正しく切り替わること
  • SVGファイルがブラウザで正しくレンダリングされること(直接URLアクセスで確認)
  • 各アイコンが視覚的に区別しやすいこと

9. 全体のビルド確認

すべての変更を加えた後、SSGビルド(pnpm generate)を実行し、全ルートが正常にプリレンダリングされることを確認した。


まとめ

この日の作業で、税理士LPは以下の改善を得た。

  • 保守性: FAQデータが1ファイルに集約され、修正コストが大幅に下がった
  • SEO: JSON-LD構造化データにより、Google検索でFAQリッチスニペットが表示される可能性が生まれた
  • UX: 業種別質問カードで、ユーザーの悩みに寄り添う導線を追加した
  • ブランド品質: 不適切な表現を除去し、税理士としての信頼性を担保した
  • 視認性: 業種別faviconで、タブバーでの業種識別が容易になった
  • コード品質: パンくずコンポーネントの共通化により、インラインの重複コードを排除した