5.6 KiB
5.6 KiB
Forum Post Detail Funnel SQL
This project now stores tracking events in table forum_track_events.
Daily rollup is also available in forum_track_daily_summary.
Key columns:
event_namelabelpost_iduser_idvisitor_idcta_variantcreated_at
Use the queries below as baseline funnel cuts.
1) Daily impression -> pricing CTA conversion (MySQL)
SELECT
DATE(created_at) AS d,
COALESCE(cta_variant, 'unknown') AS cta_variant,
COUNT(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 END) AS impressions,
COUNT(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 END) AS pricing_clicks,
ROUND(
COUNT(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 END) * 100.0
/ NULLIF(COUNT(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 END), 0),
2
) AS ctr_pct
FROM forum_track_events
WHERE created_at >= NOW() - INTERVAL 30 DAY
GROUP BY DATE(created_at), COALESCE(cta_variant, 'unknown')
ORDER BY d DESC, cta_variant;
2) Unique visitor funnel by variant (MySQL)
WITH pv AS (
SELECT
COALESCE(NULLIF(visitor_id, ''), CONCAT('u:', user_id)) AS actor_id,
COALESCE(cta_variant, 'unknown') AS cta_variant,
MAX(event_name = 'post_detail_cta_impression') AS seen_impression,
MAX(event_name = 'post_detail_cta_pricing') AS clicked_pricing,
MAX(event_name = 'post_detail_comment_submit') AS submitted_comment
FROM forum_track_events
WHERE created_at >= NOW() - INTERVAL 30 DAY
GROUP BY COALESCE(NULLIF(visitor_id, ''), CONCAT('u:', user_id)), COALESCE(cta_variant, 'unknown')
)
SELECT
cta_variant,
COUNT(*) AS actors,
SUM(seen_impression) AS actors_with_impression,
SUM(clicked_pricing) AS actors_with_pricing_click,
SUM(submitted_comment) AS actors_with_comment,
ROUND(SUM(clicked_pricing) * 100.0 / NULLIF(SUM(seen_impression), 0), 2) AS actor_ctr_pct,
ROUND(SUM(submitted_comment) * 100.0 / NULLIF(SUM(seen_impression), 0), 2) AS actor_comment_rate_pct
FROM pv
GROUP BY cta_variant
ORDER BY cta_variant;
3) Top performing CTA labels (MySQL)
SELECT
label,
COUNT(*) AS clicks
FROM forum_track_events
WHERE event_name IN ('post_detail_cta_pricing', 'post_detail_cta_new_topic', 'post_detail_sidebar_compare')
AND created_at >= NOW() - INTERVAL 30 DAY
GROUP BY label
ORDER BY clicks DESC
LIMIT 20;
4) Daily impression -> pricing CTA conversion (SQLite)
SELECT
DATE(created_at) AS d,
COALESCE(cta_variant, 'unknown') AS cta_variant,
SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END) AS impressions,
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 ELSE 0 END) AS pricing_clicks,
ROUND(
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 ELSE 0 END) * 100.0
/ NULLIF(SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END), 0),
2
) AS ctr_pct
FROM forum_track_events
WHERE created_at >= DATETIME('now', '-30 days')
GROUP BY DATE(created_at), COALESCE(cta_variant, 'unknown')
ORDER BY d DESC, cta_variant;
5) Post-level conversion ranking (SQLite/MySQL compatible style)
SELECT
post_id,
COALESCE(cta_variant, 'unknown') AS cta_variant,
SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END) AS impressions,
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 ELSE 0 END) AS pricing_clicks,
ROUND(
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 ELSE 0 END) * 100.0
/ NULLIF(SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END), 0),
2
) AS ctr_pct
FROM forum_track_events
WHERE post_id IS NOT NULL
GROUP BY post_id, COALESCE(cta_variant, 'unknown')
HAVING impressions >= 20
ORDER BY ctr_pct DESC, impressions DESC
LIMIT 50;
6) Daily rollup table quick check (SQLite/MySQL compatible style)
SELECT
event_day,
cta_variant,
event_name,
total
FROM forum_track_daily_summary
WHERE event_day >= DATE('now', '-30 day') -- MySQL: CURDATE() - INTERVAL 30 DAY
ORDER BY event_day DESC, cta_variant, event_name;
7) Mobile sticky-bar exposure rate (SQLite/MySQL compatible style)
SELECT
DATE(created_at) AS d,
COALESCE(cta_variant, 'unknown') AS cta_variant,
SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END) AS impressions,
SUM(CASE WHEN event_name = 'post_detail_mobile_bar_impression' THEN 1 ELSE 0 END) AS mobile_bar_impressions,
ROUND(
SUM(CASE WHEN event_name = 'post_detail_mobile_bar_impression' THEN 1 ELSE 0 END) * 100.0
/ NULLIF(SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END), 0),
2
) AS mobile_bar_exposure_pct
FROM forum_track_events
WHERE created_at >= DATETIME('now', '-30 days')
GROUP BY DATE(created_at), COALESCE(cta_variant, 'unknown')
ORDER BY d DESC, cta_variant;
8) Device split performance (SQLite/MySQL compatible style)
SELECT
DATE(created_at) AS d,
COALESCE(device_type, 'unknown') AS device_type,
COALESCE(cta_variant, 'unknown') AS cta_variant,
SUM(CASE WHEN event_name = 'post_detail_cta_impression' THEN 1 ELSE 0 END) AS impressions,
SUM(CASE WHEN event_name = 'post_detail_mobile_bar_impression' THEN 1 ELSE 0 END) AS mobile_bar_impressions,
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' THEN 1 ELSE 0 END) AS pricing_clicks,
SUM(CASE WHEN event_name = 'post_detail_cta_pricing' AND label LIKE 'mobile_%' THEN 1 ELSE 0 END) AS mobile_pricing_clicks
FROM forum_track_events
WHERE created_at >= DATETIME('now', '-30 days')
GROUP BY DATE(created_at), COALESCE(device_type, 'unknown'), COALESCE(cta_variant, 'unknown')
ORDER BY d DESC, device_type, cta_variant;