UI/UX
投稿日:

レビューの「信頼3点セット」が揃ったときだけ星を光らせる ─ 社会的証明のワンショット演出

こんにちは、株式会社ファストコーディングのBigViです。最近、夫とネットで加湿器を買いました。レビューが200件あって、星4.5で、写真付きのレビューもありました。「これなら大丈夫」と思って買いました。。届いたら、ちゃんと良かったです。

先日、お客さまから「商品ページにレビューセクションがあるけど、あまり見られていない」と相談されました。レビューは50件以上あって、平均4.3点。内容もいいです。でもスクロールで通り過ぎてしまう人が多いみたいです。

私もよくあります。レビューセクションがあっても、「あ、レビューね」って流してしまいます。止まって読むきっかけがないです。。

今回は「レビューの星評価・件数・実名が3つ同時に見えたとき、星を1回だけ光らせる」という演出を実装しました。小さい動きですが、離脱率とCTAクリック率に効果がありました。

なぜ「3点セット」が大事なのか

レビューの信頼感は、1つの要素だけでは弱いです。

  • 星評価だけ → 「本当かな?」
  • 件数だけ → 「多いけど、内容は?」
  • 実名だけ → 「この人だけかも」

でも3つが同時に見えると、「たくさんの人が、名前を出して、高く評価している」とわかります。これが「社会的証明」です。

この3つが画面に揃ったタイミングで、星をちょっとだけ光らせます。「ここ、見てください」という合図です。ただし1回だけ。何度も光ったらうるさいです。。

実装方法

HTML構造

<section class="review-section" id="js-review-section">
  <div class="review-header">
    <div class="review-stars" id="js-review-stars">
      <span class="star">★</span>
      <span class="star">★</span>
      <span class="star">★</span>
      <span class="star">★</span>
      <span class="star half">★</span>
      <span class="review-score">4.3</span>
    </div>
    <p class="review-count" id="js-review-count">
      <span class="count-number">58</span>件のレビュー
    </p>
  </div>
  <div class="review-list">
    <div class="review-item">
      <p class="reviewer-name" id="js-reviewer-name">田中 太郎さん</p>
      <p class="review-text">購入して3ヶ月ですが、とても満足しています。サポートの対応も丁寧でした。</p>
    </div>
  </div>
</section>

3つの要素にそれぞれIDを付けています。js-review-stars(星評価)、js-review-count(件数)、js-reviewer-name(実名)。この3つが全部画面に入ったかどうかを判定します。

CSSスタイル

.review-section {
  max-width: 640px;
  margin: 40px auto;
  padding: 32px;
  background: #fafafa;
  border-radius: 8px;
}

.review-header {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}

.review-stars {
  display: flex;
  align-items: center;
  gap: 2px;
}

.star {
  color: #ddd;
  font-size: 24px;
  transition: color 0.3s, text-shadow 0.3s;
}

.review-stars.is-active .star {
  color: #f5a623;
}

.review-stars.is-pulse .star {
  text-shadow: 0 0 12px rgba(245, 166, 35, 0.6);
}

.star.half {
  background: linear-gradient(90deg, #f5a623 50%, #ddd 50%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.review-score {
  font-size: 20px;
  font-weight: bold;
  margin-left: 8px;
  color: #333;
}

.review-count {
  font-size: 14px;
  color: #666;
}

.count-number {
  font-weight: bold;
  font-size: 18px;
  color: #333;
}

.reviewer-name {
  font-weight: bold;
  font-size: 14px;
  color: #333;
  margin-bottom: 4px;
}

.review-text {
  font-size: 14px;
  color: #555;
  line-height: 1.7;
}

ポイントは.is-pulseクラスです。このクラスが付くと、星にtext-shadowで光る効果が出ます。0.6秒だけ付けて、すぐ消します。

JavaScriptの実装

document.addEventListener('DOMContentLoaded', () => {
  const stars = document.getElementById('js-review-stars');
  const count = document.getElementById('js-review-count');
  const name = document.getElementById('js-reviewer-name');

  if (!stars || !count || !name) return;

  let hasFired = false;
  const visibleSet = new Set();

  const observer = new IntersectionObserver((entries) => {
    if (hasFired) return;

    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        visibleSet.add(entry.target.id);
      } else {
        visibleSet.delete(entry.target.id);
      }
    });

    if (
      visibleSet.has('js-review-stars') &&
      visibleSet.has('js-review-count') &&
      visibleSet.has('js-reviewer-name')
    ) {
      hasFired = true;
      observer.disconnect();

      stars.classList.add('is-active');

      requestAnimationFrame(() => {
        stars.classList.add('is-pulse');
      });

      setTimeout(() => {
        stars.classList.remove('is-pulse');
      }, 600);
    }
  }, {
    threshold: 0.5
  });

  observer.observe(stars);
  observer.observe(count);
  observer.observe(name);
});

やっていることを説明します。

  1. IntersectionObserverで3つの要素を監視します
  2. 各要素が画面の50%以上見えたら、visibleSetに追加します
  3. 3つ全部が揃ったら、星に色を付けて(is-active)、光らせます(is-pulse
  4. 0.6秒後に光を消します
  5. hasFiredフラグで1回だけ実行します。observer.disconnect()で監視も止めます

この書き方だと、3つの要素が離れた位置にあっても大丈夫です。全部が画面内に入った瞬間だけ反応します。

注意したこと

動きは1回だけ

何回も光ったら、広告っぽくなります。ユーザーは「うるさい」と感じます。1回だけ光って、あとは静かにしています。

星の色は残す

光(is-pulse)は0.6秒で消しますが、色(is-active)は残します。セクションをスクロールで通り過ぎても、戻ってきたときに星が黄色のままなので「あ、評価が高いんだ」とわかります。

パフォーマンス

IntersectionObserverはスクロールイベントより軽いです。発火したらdisconnect()するので、ずっと監視し続けることもないです。ページのパフォーマンスにはほぼ影響がないです。

アクセシビリティ

この演出は視覚的な補助です。星の色と光はCSSで制御していて、prefers-reduced-motionを設定しているユーザーには動きが自動的に無効になります。

@media (prefers-reduced-motion: reduce) {
  .star {
    transition: none;
  }
  .review-stars.is-pulse .star {
    text-shadow: none;
  }
}

実際の結果

このお客さまのプロジェクトで、A/Bテストを2週間やりました。

指標演出なし(A)演出あり(B)差分
レビューセクション到達率62.3%64.1%+1.8pt
レビューセクション離脱率38.5%29.2%-9.3pt
CTAクリック率4.1%5.3%+1.2pt

到達率はあまり変わらないです。でも離脱率がだいぶ下がりました。レビューセクションで止まって読む人が増えたということです。CTAクリック率も上がりました。レビューを読んで、信頼感が高まったからだと思います。

お客さまも「こんな小さい変化でこんなに差が出るの?」とびっくりしていました。。ただし、これは1つのプロジェクトでの結果です。効果はサイトの内容やユーザー層によって変わります。

まとめ

今回のポイントは以下の3つです:

  • 社会的証明の「3点セット」(星評価・件数・実名)が揃ったタイミングで演出する
  • IntersectionObserverで3要素の同時可視を判定する
  • 動きは0.6秒の1回だけ。静かで控えめな演出が効く

「レビューがあるのに読まれない」という課題は、コンテンツの問題じゃなくて、「見るきっかけ」の問題であることが多いです。今回の実装は30行ぐらいのJSで、既存のレビューセクションにすぐ追加できます。

株式会社ファストコーディングでは、こうしたUI改善やフロントエンドの実装サポートをしています。「レビューセクションのCVRを上げたい」「社会的証明をもっと効かせたい」という方は、お問い合わせフォームから気軽にご連絡ください。


※本記事は弊社外国人スタッフによる投稿です。言い回しや表現が不十分な個所がありますことご容赦いただきますようお願いいたします。