@@ -155,6 +155,8 @@ export const LoopVideo = ({
155155 * want to pause the video if it has been in view.
156156 */
157157 const [ hasBeenInView , setHasBeenInView ] = useState ( false ) ;
158+ const [ hasBeenPlayed , setHasBeenPlayed ] = useState ( false ) ;
159+ const [ hasTrackedPlay , setHasTrackedPlay ] = useState ( false ) ;
158160
159161 const VISIBILITY_THRESHOLD = 0.5 ;
160162
@@ -176,6 +178,7 @@ export const LoopVideo = ({
176178 . then ( ( ) => {
177179 // Autoplay succeeded
178180 dispatchOphanAttentionEvent ( 'videoPlaying' ) ;
181+ setHasBeenPlayed ( true ) ;
179182 setPlayerState ( 'PLAYING' ) ;
180183 } )
181184 . catch ( ( error : Error ) => {
@@ -383,6 +386,19 @@ export const LoopVideo = ({
383386 }
384387 } , [ isInView , hasBeenInView , atomId , linkTo ] ) ;
385388
389+ /**
390+ * Track the first successful video play in Ophan.
391+ *
392+ * This effect runs only after the video has actually started playing
393+ * for the first time. This is to ensure we don't double-report the event.
394+ */
395+ useEffect ( ( ) => {
396+ if ( ! hasBeenPlayed || hasTrackedPlay ) return ;
397+
398+ ophanTrackerWeb ( atomId , 'loop' ) ( 'play' ) ;
399+ setHasTrackedPlay ( true ) ;
400+ } , [ atomId , hasBeenPlayed , hasTrackedPlay ] ) ;
401+
386402 /**
387403 * Handle play/pause, when instigated by the browser.
388404 */
@@ -412,14 +428,6 @@ export const LoopVideo = ({
412428 playerState === 'PAUSED_BY_INTERSECTION_OBSERVER' ||
413429 ( hasPageBecomeActive && playerState === 'PAUSED_BY_BROWSER' ) )
414430 ) {
415- /**
416- * Check if the video has not been in view before tracking the play.
417- * This is so we only track the first play.
418- */
419- if ( ! hasBeenInView ) {
420- ophanTrackerWeb ( atomId , 'loop' ) ( 'play' ) ;
421- }
422-
423431 setHasPageBecomeActive ( false ) ;
424432 void playVideo ( ) ;
425433 }
0 commit comments