フォアグラウンドの合計時間を計算する

このガイドでは、ユーザーがページをアクティブに閲覧した合計時間を正確に計算する方法について説明します。ページ滞在時間などの従来の指標では、ページがバックグラウンドで表示されている時間も誤って含まれることがよくあります。VisibilityStateEntry API を使用すると、「フォアグラウンド時間」のみを測定できるため、ユーザー エンゲージメントのより適切な指標が得られます。

フォアグラウンド時間の計算の実装

PerformanceTimeline API は、可視性の状態の変化をパフォーマンス エントリとして公開します。visibilitychange イベントに反応してセッション全体で手動で時間を累積するのではなく、いつでも視認性の履歴全体をクエリできます。

必須: visibility-state パフォーマンス エントリをクエリして、実際のフォアグラウンド時間を計算する必要があります。

/**
 * Calculates total time the page was in the visible state.
 *
 * @returns {number} Total foreground time in milliseconds.
 */
function getTotalForegroundTime() {
  // MANDATORY: Query the visibility-state entries from the performance timeline.
  const entries = performance.getEntriesByType('visibility-state');

  // Fallback: If the browser does not support VisibilityStateEntry,
  // the API will gracefully return an empty array.
  if (entries.length === 0) {
    // Return total time since navigation start as a fallback.
    return performance.now();
  }

  let totalForegroundTime = 0;

  for (let i = 0; i < entries.length; i++) {
    // Only calculate duration for periods where the state was 'visible'
    if (entries[i].name === 'visible') {
      const start = entries[i].startTime;

      // The end time is the start time of the next state change,
      // or the current time if this is the final entry.
      const end = i + 1 < entries.length
          ? entries[i + 1].startTime
          : performance.now();

      totalForegroundTime += (end - start);
    }
  }

  return totalForegroundTime;
}

フォールバックとブラウザのサポート

VisibilityStateEntry API は Performance Timeline に新たに追加されたもので、すべてのブラウザでサポートされているわけではありません。

performance.getEntriesByType('visibility-state') は、サポートされていないブラウザでは空の配列を返すため、機能検出が計算フローに組み込まれています。続行する前に、エントリが返されるかどうかを必ず確認してください。

API がサポートされていない場合は、performance.now() を返すことをおすすめします。これは、ナビゲーションからの合計時間を表します。これは、視認性状態の履歴が利用できない場合のエンゲージメント時間の上限として妥当な値です。

const entries = performance.getEntriesByType('visibility-state');

// If the array is empty, the API is likely unsupported.
if (entries.length === 0) {
  // Fallback: Return total time since page load.
  return performance.now();
}