Track video clicks as engagement signals
- stats: started_count now includes any video opened (last_watched_at set) not just ones with saved progress seconds - VideoPlayer: fires updateProgress immediately on open so even a click-and-back sets last_watched_at and counts as a started video Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -140,7 +140,7 @@ def get_stats(
|
|||||||
text("""
|
text("""
|
||||||
SELECT COUNT(*) AS n FROM user_videos
|
SELECT COUNT(*) AS n FROM user_videos
|
||||||
WHERE user_id = :uid AND watched = 0
|
WHERE user_id = :uid AND watched = 0
|
||||||
AND watch_progress_seconds > 0
|
AND (watch_progress_seconds > 0 OR last_watched_at IS NOT NULL)
|
||||||
"""),
|
"""),
|
||||||
{"uid": uid},
|
{"uid": uid},
|
||||||
).mappings().first()
|
).mappings().first()
|
||||||
|
|||||||
@@ -126,6 +126,16 @@ export default function VideoPlayer() {
|
|||||||
}
|
}
|
||||||
}, [dlStatus?.status]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [dlStatus?.status]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
// Record a "clicked" impression as soon as we have the video id — even if the
|
||||||
|
// user closes immediately before playback starts.
|
||||||
|
const clickedRef = useRef(false);
|
||||||
|
useEffect(() => {
|
||||||
|
if (video?.id && !clickedRef.current && !video.is_watched) {
|
||||||
|
clickedRef.current = true;
|
||||||
|
updateProgress(video.id, { watch_progress_seconds: video.watch_progress_seconds ?? 0 });
|
||||||
|
}
|
||||||
|
}, [video?.id]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
// ── Trigger download on open ──────────────────────────────────────────────
|
// ── Trigger download on open ──────────────────────────────────────────────
|
||||||
const downloadMut = useMutation({
|
const downloadMut = useMutation({
|
||||||
mutationFn: (ytId) => createDownload(ytId),
|
mutationFn: (ytId) => createDownload(ytId),
|
||||||
|
|||||||
Reference in New Issue
Block a user