@@ -164,6 +164,8 @@ export const LoopVideo = ({
164164 * want to pause the video if it has been in view.
165165 */
166166 const [ hasBeenInView , setHasBeenInView ] = useState ( false ) ;
167+ const [ hasBeenPlayed , setHasBeenPlayed ] = useState ( false ) ;
168+ const [ hasTrackedPlay , setHasTrackedPlay ] = useState ( false ) ;
167169
168170 const VISIBILITY_THRESHOLD = 0.5 ;
169171
@@ -185,6 +187,7 @@ export const LoopVideo = ({
185187 . then ( ( ) => {
186188 // Autoplay succeeded
187189 dispatchOphanAttentionEvent ( 'videoPlaying' ) ;
190+ setHasBeenPlayed ( true ) ;
188191 setPlayerState ( 'PLAYING' ) ;
189192 } )
190193 . catch ( ( error : Error ) => {
@@ -392,6 +395,19 @@ export const LoopVideo = ({
392395 }
393396 } , [ isInView , hasBeenInView , atomId , linkTo ] ) ;
394397
398+ /**
399+ * Track the first successful video play in Ophan.
400+ *
401+ * This effect runs only after the video has actually started playing
402+ * for the first time. This is to ensure we don't double-report the event.
403+ */
404+ useEffect ( ( ) => {
405+ if ( ! hasBeenPlayed || hasTrackedPlay ) return ;
406+
407+ ophanTrackerWeb ( atomId , 'loop' ) ( 'play' ) ;
408+ setHasTrackedPlay ( true ) ;
409+ } , [ atomId , hasBeenPlayed , hasTrackedPlay ] ) ;
410+
395411 /**
396412 * Handle play/pause, when instigated by the browser.
397413 */
@@ -421,14 +437,6 @@ export const LoopVideo = ({
421437 playerState === 'PAUSED_BY_INTERSECTION_OBSERVER' ||
422438 ( hasPageBecomeActive && playerState === 'PAUSED_BY_BROWSER' ) )
423439 ) {
424- /**
425- * Check if the video has not been in view before tracking the play.
426- * This is so we only track the first play.
427- */
428- if ( ! hasBeenInView ) {
429- ophanTrackerWeb ( atomId , 'loop' ) ( 'play' ) ;
430- }
431-
432440 setHasPageBecomeActive ( false ) ;
433441 void playVideo ( ) ;
434442 }
0 commit comments