フローティングボタン(追従ボタン)がどこでクリックされた知る方法

多くのサイトで利用される 【フローティングボタン(追従ボタン)】。

スマホ画面の下部や右下に固定され、ユーザーの行動を強力に後押しするUIです。

しかし 「どの位置で押されたのか?」 を正確に知ることは意外と難しく、

改善のヒントは大量にあるのに“感覚頼り”で最適化されているケースが多くあります。

この記事では、

クリック計測の基本 → フローティングボタンの計測方法 → 自分でコードを書けるテンプレート

までをまとめて紹介します。


1. なぜ「どこでクリックされたか」を知るべきなのか?

フローティングボタンは常に画面に表示されるため、通常のCTAと比べて“押される理由”が曖昧になりがちです。

例えば:

  • 商品を読み終えたタイミングで押されたのか?
  • 途中スクロール中に押されたのか?
  • 最初から興味が高く、すぐ押されたのか?

これらを分けて分析することで、次のような改善が可能になります。

行動パターン 改善例
ページ序盤で押されがち 上部のメリット訴求を強化
2000px以上スクロール後に押されがち 商品説明の改善余地を探す
途中で押されなくなる 中盤の離脱要因(画像/文章量/読みづらさ)を改善

“押された瞬間の文脈”を知ることは、CVR改善の近道です。

2. 計測に必要な情報:3つだけ覚えればOK

クリック計測に必要なのは、次の3つです。

① どの要素が押されたか(セレクタ)

例)

<button class="floating-cta">申し込む</button>
  • .floating-cta (class=“floating-cta” となっている場合)
  • #cta-fixed (id=“cta-fixed” となっている場合)

など、サイトごとに異なるので開発者ツールで確認します。

② どのタイミングで計測するか(発火タイミング)

基本は クリック時 です。

③ 何を記録するか(取得したい情報)

フローティングボタンの場合、特に役立つのが以下の3つ:

  • ボタンテキスト … どのCTA文言が押されやすいか
  • 現在のURL … どのLPで押されたか
  • スクロール位置 … どのユーザー心理段階で押されたか

スクロール位置は “px をバケット分け(例:800pxごと)” が便利です。

※3章で紹介するのテンプレートではこれらは自動で取得します


3. 実際にイベントコードを作る方法(テンプレートあり)

ここからは

Ptengine / Google Tag Manager / 自作計測など、どのツールでも使える

クリック取得JSの書き方を紹介します。

:pushpin: クリック計測コードのテンプレート(コピペOK)

以下のテンプレートに、

  • クリック対象セレクタ

を当てはめればすぐ使えます。

▼ フローティングボタンのクリック計測コード

(function () {

  if (window.__ptengine_floating_banner_click_v1) {
    console.warn('[ptengine] Floating CTA listener is already initialized.');
    return;
  }
  window.__ptengine_floating_banner_click_v1 = true;

  // ================================
  // 設定:対象セレクタを変更してください
  // ================================
  var TARGET_SELECTOR = '.floating-cta';  // IDの場合は'#xxxx'、classの場合は'.xxxx'



  function bucketizeScrollY(y) {
    if (y <= 800) return '~800px';
    var base = Math.floor((y - 1) / 800);
    var min = base * 800 + 1;
    var max = (base + 1) * 800;
    return min + 'px-' + max + 'px';
  }



  function getCleanUrl() {
    var url = location.href;
    url = url.split('?')[0];  // クエリ除去
    url = url.split('#')[0];  // ハッシュ除去
    return url;
  }



  function closest(el, selector) {
    while (el && el !== document && el !== window) {
      if (matches(el, selector)) return el;
      el = el.parentNode;
    }
    return null;
  }

  function matches(el, selector) {
    var fn = el.matches || el.msMatchesSelector || el.webkitMatchesSelector;
    if (fn) return fn.call(el, selector);
    return false;
  }



  var lastSentMap = new WeakMap();
  function shouldSend(el) {
    var now = Date.now();
    var prev = lastSentMap.get(el) || 0;
    if (now - prev < 500) return false;
    lastSentMap.set(el, now);
    return true;
  }


 
  function sendTrack(eventName, payload, retryCount) {
    try {
      if (window.ptengine && typeof ptengine.track === 'function') {
        ptengine.track(eventName, payload);
        console.log('[ptengine] track sent:', eventName, payload);
        return;
      }

      if (retryCount <= 0) {
        console.warn('[ptengine] track failed after retries:', eventName, payload);
        return;
      }

      setTimeout(function () {
        sendTrack(eventName, payload, retryCount - 1);
      }, 500);

    } catch (err) {
      console.warn('[ptengine] track error:', err);
    }
  }



  function clickHandler(e) {
    var target = closest(e.target, TARGET_SELECTOR);
    if (!target) return;
    if (!shouldSend(target)) return;

    setTimeout(function () {
      try {
        var scrollY = window.scrollY || window.pageYOffset || 0;
        var bucket = bucketizeScrollY(scrollY);

        var payload = {
          'button_text': (target.innerText || '').replace(/\s+/g, ' ').trim(),
          'url': getCleanUrl(),           // ← 改善:クエリ & ハッシュ除去
          'scroll_bucket': bucket
        };

        console.log('[cta clicked]', payload);

        sendTrack('floating_cta_clicked', payload, 12);

      } catch (err) {
        console.warn('[ptengine] click payload error:', err);
      }
    }, 0);
  }


  document.addEventListener(
    'click',
    function (e) {
      clickHandler(e);
    },
    true
  );

  console.log('[ptengine] Floating CTA click listener initialized:', TARGET_SELECTOR);
})();

4. 開発者ツールで動作確認する方法

  1. 対象ページを開く
  2. F12 → Console
  3. 上記コードを貼り付けて Enter
  4. フローティングボタンをクリック
  5. Consoleにログが出ていれば成功!

5. Google Tag Manager / Ptengine への設置方法

どちらもシンプルです。

■ Google Tag Manager

  1. 新規タグ → 「カスタムHTML」
  2. 上記コードを <script>〜</script> で囲んで貼り付け
  3. 発火条件:
  • 対象LPだけ
  • 全ページ
  • etc
  1. プレビューで確認し、公開

■ Ptengine Experience

  1. 対象ページの「ページ編集」
  2. [コードモード] → [JavaScript] に貼り付け
  3. 公開するだけ

6. よくあるトラブルと解決法

現象 原因 対策
計測されない セレクタが違う クリックした要素の class / id を再確認
スクロール位置が全部同じ 上部でテストしている もっと下までスクロールして検証
クリックされているのにログが出ない 別要素がクリックを奪っている closest() を使って判定する

7. まとめ:フローティングボタン計測は“1時間でできる改善投資”

:point_up:データ取得後はイベント分析画面からステップで確認できます。
①イベント分析画面へ→②対象のイベントを選択→③カテゴリから確認したいデータを選択

フローティングボタンはCVRに直結するUIであり、

「どこで押されたか知るだけで改善できる」 非常にコスパの高い分析テーマです。

  • 必要なのはクリックイベント
  • スクロール位置で文脈が分かる
  • URL+ボタンテキストで用途も明確になる

さらにこの記事で紹介したテンプレートを使えば、

開発経験がなくても自分で計測コードを作れるようになります。




いかがでしたか?
少々難易度の高い内容でもありますので、

  • もっとカスタマイズしてデータを取得したい!
  • うまくデータが取れずサポートして欲しい!
  • ステップが理解できず教えて欲しい!
  • ピクセル数だと直感的にイメージしづらく助けて欲しい、、

というようなご要望があれば、ぜひチャットよりご質問ください。