analyzing-funnel-correlation について
PostHog で、ファネルのコンバージョンや離脱に関連するイベントやプロパティ値を調べる分析スキルです。オッズ比で成功群と失敗群を比較し、相関は因果関係を示さないことも伝えます。
主な機能
- 01ファネルのステップと期間の定義
- 02イベント相関シグナルの比較
- 03人物またはイベントプロパティの分析
- 04件数とシグナルの注意点の提示
活用シーン
- 01ファネルのコンバージョンに関連するイベントの特定
- 02コンバージョン群と離脱群のプロパティ値の比較
- 03実験候補となるシグナルの特定
MCP 対応
PostHog のツールでインサイトとスキーマを読み取り、ファネルと SQL を実行して、ファネルのアクターを確認します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill analyzing-funnel-correlationインストール後、Claude Code で/analyzing-funnel-correlationを入力して読み込まれたか確認します。
詳細
ファネル相関の分析
ファネル相関では、ファネルに入った人々を2つのグループに分けて比較します。最後のステップを完了した人(成功)と、完了しなかった人(失敗)です。 候補となる各イベントまたはプロパティ値について分割表を作成し、オッズ比を計算します。 オッズ比が1を上回る場合、そのシグナルはコンバージョンと関連しています。1を下回る場合は、離脱と関連しています。 比率が1から離れるほど、相関は強くなります。
相関は因果関係を意味するものではありません。その点をユーザーに伝え、強いシグナルを検証する実験を提案してください。
ワークフロー
- ファネルの定義を確認します。ステップイベント、日付範囲、コンバージョンウィンドウを確認してください。
ユーザーが保存済みインサイトを指定した場合は、
insight-getで読み込みます。read-data-schemaでステップイベントを確認します。 query-funnelでファネルを実行し、流入した合計人数とコンバージョンした人数を記録します。 以下のSQLでも同じ範囲の合計人数が得られる必要があります。一致しない場合は、まずステップのフィルターを修正してください。- 以下のイベント相関クエリを
execute-sqlで実行します。 - ユーザーが人物属性について尋ねた場合は、プロパティ用のバリエーションを実行します。
- 成功シグナルと失敗シグナルの上位項目を、それぞれの人数とともに報告します。
シグナルに該当する人を確認するには、
query-funnel-actorsを使うか、そのイベントまたはプロパティでファネルをフィルターします。
イベント相関
ステップイベント、日付範囲、コンバージョンウィンドウ(windowFunnel では秒数、INTERVAL では日数)、ステップ数を置き換えます。
ステップを増やす場合は、windowFunnel に event = '...' 条件を追加し、最後のステップを steps = N に設定します。
WITH
funnel_actors AS (
SELECT
person_id AS actor_id,
windowFunnel(1209600)(toDateTime(timestamp), event = 'step one', event = 'step two') AS steps,
arraySort(groupArrayIf((toUnixTimestamp(timestamp), event = 'step two'), event IN ('step one', 'step two'))) AS step_events,
arrayReverseFill(t -> t > 0, arrayMap(x -> if(x.2, x.1, 0), step_events)) AS next_final,
arrayFirstIndex((x, t) -> NOT x.2 AND t > 0 AND t <= x.1 + 1209600, step_events, next_final) AS attempt,
toDateTime(if(attempt > 0, step_events[attempt].1, arrayFirst(x -> NOT x.2, step_events).1)) AS first_timestamp,
toDateTime(next_final[greatest(attempt, 1)]) AS final_timestamp
FROM events
WHERE event IN ('step one', 'step two')
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY actor_id
HAVING steps >= 1
),
totals AS (
SELECT countIf(steps = 2) AS success_total, countIf(steps < 2) AS failure_total
FROM funnel_actors
),
per_event AS (
SELECT
e.event AS name,
countDistinctIf(a.actor_id, a.steps = 2) AS success_count,
countDistinctIf(a.actor_id, a.steps < 2) AS failure_count
FROM events AS e
JOIN funnel_actors AS a ON e.person_id = a.actor_id
WHERE e.timestamp >= now() - INTERVAL 30 DAY
AND e.timestamp > a.first_timestamp
AND e.timestamp < if(a.steps = 2, a.final_timestamp, a.first_timestamp + INTERVAL 14 DAY)
AND e.event NOT IN ('step one', 'step two')
GROUP BY name
)
SELECT
name,
success_count,
failure_count,
success_total,
failure_total,
((success_count + 1) * (failure_total - failure_count + 1))
/ ((success_total - success_count + 1) * (failure_count + 1)) AS odds_ratio
FROM per_event
CROSS JOIN totals
WHERE success_count + failure_count >= least(25, 0.02 * (success_total + failure_total))
ORDER BY abs(log(odds_ratio)) DESC
LIMIT 20
このクエリは、ファネルへの流入からコンバージョンまでのイベントのみを数えます。
step_events には、時間順に並んだ最初と最後のステップのイベントが格納されます。next_final は、1回の処理で各イベントに対する次の最後のステップの時刻を取得します。
コンバージョンした人については、attempt がウィンドウ内に最後のステップがある最初の流入を選択するため、両方のタイムスタンプが同じ試行から取得されます。
ステップが複数ある場合は、groupArrayIf に最初と最後のステップのイベントのみを残します。この場合、試行では中間のステップが無視されるため、コンバージョンに至った流入より前の流入から間隔が始まることがあります。
コンバージョンしなかった人については、最初の流入からコンバージョンウィンドウが終了するまでのイベントを数えます。
windowFunnel は整数秒で比較するため、タイムスタンプも整数秒を使用します。同じ精度を保ってください。そうしないと、一部のコンバージョンで一致する試行が見つからなくなります。
ファネルのステップイベントは、定義上コンバージョンと相関するため除外されます。
プロパティ相関
人物プロパティの値を比較するには、人物をプロパティでグループ化し、イベントの結合を省略します。
WITH
funnel_actors AS (
SELECT
person_id AS actor_id,
windowFunnel(1209600)(toDateTime(timestamp), event = 'step one', event = 'step two') AS steps,
any(person.properties.$browser) AS value
FROM events
WHERE event IN ('step one', 'step two')
AND timestamp >= now() - INTERVAL 30 DAY
GROUP BY actor_id
HAVING steps >= 1
),
totals AS (
SELECT countIf(steps = 2) AS success_total, countIf(steps < 2) AS failure_total
FROM funnel_actors
),
per_value AS (
SELECT
toString(value) AS name,
countIf(steps = 2) AS success_count,
countIf(steps < 2) AS failure_count
FROM funnel_actors
GROUP BY name
)
SELECT
name,
success_count,
failure_count,
((success_count + 1) * (failure_total - failure_count + 1))
/ ((success_total - success_count + 1) * (failure_count + 1)) AS odds_ratio
FROM per_value
CROSS JOIN totals
WHERE success_count + failure_count >= least(25, 0.02 * (success_total + failure_total))
ORDER BY abs(log(odds_ratio)) DESC
LIMIT 20
代わりに1つのイベントのプロパティを見るには、per_event をそのイベントでフィルターし、e.properties.<name> でグループ化します。
結果の読み取りには注意が必要です
- 各セルに加算される
+ 1は事前分布です。ゼロ除算を防ぎ、少数のデータに基づくシグナルの影響を抑えます。 WHEREフィルターは、25人未満、または流入者の2%未満にしか見られなかったシグナルを除外します。小規模なグループでは比率が不安定になります。- 一方のグループがもう一方の10倍を超える場合、比率の信頼性は低くなります。その点をユーザーに伝えてください。
success_totalまたはfailure_totalが0の場合、比較対象がありません。$pageview、$pageleave、$feature_flag_calledなど、全員が送信するノイズイベントによってリストが埋まることがあります。有用なシグナルが見えなくなる場合は、これらを除外してください。- グループベースのファネルでは、
person_idを$group_Nに、人物プロパティをグループプロパティに置き換えます。また、ファネルステップのWHERE句にAND $group_N != ''を追加してください。そのグループに属さないイベントのキーは空です。このフィルターがないと、それらのイベントはコンバージョン可能な1人の偽のアクターとして扱われます。