diff --git a/docs/.vitepress/theme/components/TutorialPlayer.vue b/docs/.vitepress/theme/components/TutorialPlayer.vue index a67f901..4673fe2 100644 --- a/docs/.vitepress/theme/components/TutorialPlayer.vue +++ b/docs/.vitepress/theme/components/TutorialPlayer.vue @@ -95,16 +95,38 @@ const entry = ref('') const isSheetOpen = ref(false) const isExpanded = ref(false) const isModalOpen = ref(false) +const tutorialCompleted = ref(false) const activeModalImage = ref<{ src: string; alt: string } | null>(null) function openModal() { isModalOpen.value = true + // Reaching the end-of-tutorial modal means the player finished, so a later Exit + // click should not be counted as an early exit. + tutorialCompleted.value = true } function closeModal() { isModalOpen.value = false } +// Fire a GA4 event when a player leaves the tutorial early (exit_tutorial) or +// finishes and heads to the game (tutorial_complete_play). GA is already set up in +// the theme; this only sends a named signal with the chapter they were on. +function trackTutorial(name: string) { + try { + ;(window as any).gtag?.('event', name, { event_category: 'tutorial', chapter: chapterNum.value }) + } catch (err) { + // Analytics is best-effort and must never block navigation; surface it quietly. + console.debug('tutorial analytics event failed', name, err) + } +} + +// The Exit control is always visible, including after completion, so only count a +// click as an early exit when the player has not reached the end-of-tutorial screen. +function trackExit() { + if (!tutorialCompleted.value) trackTutorial('exit_tutorial') +} + function openImageModal(src: string, alt = '') { activeModalImage.value = { src, alt } } @@ -610,6 +632,9 @@ function submit() { } watch(() => route.path, () => { + // Navigation here is SPA, so this component is not remounted between chapters. + // Clear the completion flag on each chapter so a retake-then-exit is counted. + tutorialCompleted.value = false renderStepLog() }, { immediate: true }) @@ -699,7 +724,7 @@ onUnmounted(() => { {{ isExpanded ? 'Shrink' : 'Full' }} - + Exit @@ -879,7 +904,7 @@ onUnmounted(() => {