📊

個人開発のバイクサイトでCTR 1.2%→改善を目指してリッチスニペットを実装した話

に公開

個人開発のバイクサイトでCTR 1.2%→改善を目指してリッチスニペットを実装した話

はじめに

個人開発のバイクポータルサイト「MotoHub」を運営しています。

Google March 2026コアアップデート後、掲載順位は25.3→7.8まで回復したのに、CTR(クリック率)が1.2%のまま。順位7〜8位なら2〜4%が目安なので、明らかに低い。

原因を調べていくと、バイク業界で構造化データをちゃんとやってるサイトがほぼゼロという事実に気づきました。

CTR 1.2%の原因

検索結果がテキストだけ

Google検索結果でのMotoHubの表示を確認すると、画像も★評価も価格表示もない。競合のGooBike、Webike、BDSも同様にテキストだけでした。

唯一、価格.comが一部でリッチスニペットを出していますが、バイクカテゴリでは力を入れていない様子。

つまり、MotoHubが先にリッチスニペットを出せれば、検索結果で唯一画像付きで表示されるバイクサイトになる

他業界では当たり前

食べログ、Amazon、楽天トラベル、クックパッド...。リッチスニペットを活用している業界は多いのに、バイク業界だけが取り残されている。

業界 使ってるスキーマ 代表例
EC/通販 Product + ★評価 + 価格 Amazon、楽天
レシピ Recipe + 調理時間 + 画像 クックパッド
ホテル Hotel + ★評価 + 価格帯 楽天トラベル
レストラン LocalBusiness + ★評価 食べログ
中古バイク ❌ 誰もやってない

Product JSON-LDを実装する

Bladeコンポーネントとして実装

LaravelのBladeコンポーネントでProduct スキーマのJSON-LDを実装しました。

// resources/views/components/jsonld/product.blade.php

@props([
    'listing',
    'reviewStats' => null,
])

@php
    $images = $listing->images ?? [];
    $price = $listing->total_price ? $listing->total_price * 10000 : null;
@endphp

<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "Product",
    "name": "{{ $listing->title }}",
    "image": @json($images),
    "brand": {
        "@type": "Brand",
        "name": "{{ $listing->manufacturer->name ?? '' }}"
    },
    @if($price)
    "offers": {
        "@type": "Offer",
        "price": "{{ $price }}",
        "priceCurrency": "JPY",
        "availability": "{{ $listing->is_sold_out ? 'https://schema.org/SoldOut' : 'https://schema.org/InStock' }}",
        "url": "{{ url()->current() }}"
    },
    @endif
    @if($reviewStats && $reviewStats->review_count > 0)
    "aggregateRating": {
        "@type": "AggregateRating",
        "ratingValue": "{{ number_format($reviewStats->avg_rating, 1) }}",
        "reviewCount": "{{ $reviewStats->review_count }}",
        "bestRating": "5",
        "worstRating": "1"
    },
    @endif
    "description": "{{ Str::limit(strip_tags($listing->description ?? ''), 200) }}"
}
</script>

実装のポイント3つ

① 画像は配列で渡す

$listing->images はアクセサで、local_image_pathsimage_urls の優先順で解決し、完全なURLの配列を返します。Googleは配列の最初の画像をサムネイルに使います。

② 価格はJPY(円単位)

DBには万円単位で保存しているので、JSON-LD出力時に * 10000 で円に変換。37.0370000。titleなど人間が読む場所では「37万円」のままにしています。

③ aggregateRatingはレビューがある場合のみ

レビュー0件でaggregateRatingを出すと、Googleがエラーとして扱います。$reviewStats->review_count > 0 の条件分岐が必須。

車種モデルページにはAggregateOffer

個別車両ページだけでなく、車種モデルページ(例:レブル250のページ)にはAggregateOfferで価格レンジを出力しました。

{
    "@type": "AggregateOffer",
    "lowPrice": "350000",
    "highPrice": "850000",
    "priceCurrency": "JPY",
    "offerCount": "1200"
}

これで検索結果に「¥350,000〜¥850,000」のように表示される可能性があります。

title改善:「相場判定」を入れる

構造化データだけでなく、titleも改善しました。

Before:

ダンク インジェクション仕様|143,000円|2014年年式|39,242km - MotoHub

After:

Dio110 Lite | 26.4万円 | 相場26.1万円の相場並み判定 - MotoHub

変更点:

  • 価格を万円表示に統一
  • 「年年式」の重複を修正
  • 相場との比較判定を追加(「割安」「相場並み」「割高」)

「割安判定」と表示されたら、クリックして確認したくなりますよね。

// title生成ロジック(簡略版)
$titleParts = [];
$titleParts[] = $listing->title;

if ($listing->total_price) {
    $titleParts[] = number_format((float)$listing->total_price, 1) . '万円';
}

if ($marketPosition) {
    $avg = number_format($marketPosition['avg_price'], 1);
    $label = match(true) {
        $marketPosition['diff_pct'] <= -10 => '割安',
        $marketPosition['diff_pct'] >= 10 => '割高',
        default => '相場並み',
    };
    $titleParts[] = "相場{$avg}万円の{$label}判定";
}

$title = implode(' | ', $titleParts) . ' - MotoHub';

JSON-LDはインデックス登録に影響するか?

構造化データについて調べていて気になったのが、「インデックス登録にプラスになるのか?」という点です。

Googleは公式に「構造化データはランキングシグナルではない」と明言しています。つまり、JSON-LDを入れたから直接的に順位が上がったりインデックスが優先されるわけではありません。

ただし、間接的にはプラスになります

  • ページの内容理解が向上: Googleが「これは商品ページで、画像があって、価格があって、レビューがある」と正確に理解できるようになる
  • CTR向上→流入増: リッチスニペットでクリックが増えると、結果的にトラフィック増→評価向上
  • クロール品質: 構造化データのエラーが多いとクローラーを遠ざける可能性がある(逆に正しい実装はプラス)

ある事例では、構造化データ導入後にCTRが約1.8倍に向上したという報告もあります。

実装結果

ブラウザのDevToolsで確認:

Type: Product
  @context: "https://schema.org"
  @type: "Product"
  aggregateRating:
    @type: "AggregateRating"
    ratingValue: "3.8"
    reviewCount: "2"
  brand:
    name: "ホンダ"
  image: Array(1)
  offers:
    price: "370000"
    priceCurrency: "JPY"

22万ページの車両詳細 + 2,200ページの車種モデルに一括適用。

デプロイ後、Aboutページは数時間でGoogleに反映されました。サムネイル画像付きの検索結果が表示されています。

車両詳細ページの★評価+価格+バイク写真のリッチスニペットは、再クロール待ちです。

バイク業界の比較

サイト Product JSON-LD image ★評価 価格
GooBike
Webike
BikeBros
価格.com △(一部)
MotoHub

まとめ

  • 掲載順位が改善してもCTRが低いなら、構造化データとtitleの改善が効く
  • バイク業界ではリッチスニペットの実装がほぼゼロ。先行者利益が取れる
  • Product JSON-LDにimage、aggregateRating、priceを入れるだけで検索結果が劇的に変わる
  • 個人開発の機動力で、大手が社内稟議してる間にデプロイ完了

効果の計測は1〜2週間後。CTRがどう変化したかは、また記事にします。


MotoHub: https://motohub.jp

Discussion