11import { css } from '@emotion/react' ;
22import { isNonNullable } from '@guardian/libs' ;
3+ import type { ComponentEvent } from '@guardian/ophan-tracker-js' ;
4+ import { useEffect , useState } from 'react' ;
5+ import { submitComponentEvent } from '../client/ophan/ophan' ;
36import { ArticleDesign , type ArticleFormat } from '../lib/articleFormat' ;
47import { decideTrail , dedupeTrail } from '../lib/decideTrail' ;
58import { useApi } from '../lib/useApi' ;
69import { addDiscussionIds } from '../lib/useCommentCount' ;
10+ import { useIsInView } from '../lib/useIsInView' ;
711import { palette } from '../palette' ;
812import type { OnwardsSource } from '../types/onwards' ;
913import type { RenderingTarget } from '../types/renderingTarget' ;
@@ -20,6 +24,7 @@ type Props = {
2024 absoluteServerTimes : boolean ;
2125 renderingTarget : RenderingTarget ;
2226 isAdFreeUser : boolean ;
27+ containerPosition : string ;
2328 webURL : string ;
2429} ;
2530
@@ -59,8 +64,35 @@ export const FetchOnwardsData = ({
5964 absoluteServerTimes,
6065 renderingTarget,
6166 isAdFreeUser,
67+ containerPosition,
6268 webURL,
6369} : Props ) => {
70+ const [ hasBeenSeen , setIsInViewRef ] = useIsInView ( { rootMargin : `-100px` } ) ;
71+
72+ const [ hasTrackedView , setHasTrackedView ] = useState ( false ) ;
73+
74+ useEffect ( ( ) => {
75+ if ( hasBeenSeen && ! hasTrackedView ) {
76+ const ophanComponentEvent : ComponentEvent = {
77+ component : {
78+ componentType : 'CONTAINER' ,
79+ id : `onwards-${ onwardsSource } -${ containerPosition } ` ,
80+ } ,
81+ action : 'VIEW' ,
82+ } ;
83+
84+ void submitComponentEvent ( ophanComponentEvent , renderingTarget ) ;
85+
86+ setHasTrackedView ( true ) ;
87+ }
88+ } , [
89+ hasBeenSeen ,
90+ hasTrackedView ,
91+ renderingTarget ,
92+ onwardsSource ,
93+ containerPosition ,
94+ ] ) ;
95+
6496 const { data, error } = useApi < OnwardsResponse > ( url ) ;
6597
6698 if ( error ) {
@@ -88,7 +120,7 @@ export const FetchOnwardsData = ({
88120 const trails = buildTrails ( data . trails , limit , isAdFreeUser , webURL ) ;
89121
90122 return (
91- < div css = { minHeight } >
123+ < div ref = { setIsInViewRef } css = { minHeight } >
92124 < Carousel
93125 heading = { data . heading || data . displayname } // Sometimes the api returns heading as 'displayName'
94126 trails = { trails }
0 commit comments