Skip to content

Commit 0d94b2f

Browse files
authored
Add ophan attention tracking to looping video (#14174)
* Bump "@guardian/ophan-tracker-js" to "2.3.2", * Extend internal ophan api to expect video tracking prop on component attention tracking * Add attention tracking to looping video
1 parent 909e3ac commit 0d94b2f

File tree

4 files changed

+9737
-3436
lines changed

4 files changed

+9737
-3436
lines changed

dotcom-rendering/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@guardian/identity-auth": "6.0.1",
3939
"@guardian/identity-auth-frontend": "8.1.0",
4040
"@guardian/libs": "25.2.0",
41-
"@guardian/ophan-tracker-js": "2.3.0",
41+
"@guardian/ophan-tracker-js": "2.3.2",
4242
"@guardian/react-crossword": "6.3.0",
4343
"@guardian/shimport": "1.0.2",
4444
"@guardian/source": "10.2.0",

dotcom-rendering/src/client/ophan/ophan.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,18 @@ export const getOphan = async (
6161
name,
6262
el,
6363
visibilityThreshold,
64+
isTrackingVideo = false,
6465
) => {
65-
ophan.trackComponentAttention(name, el, visibilityThreshold);
66+
ophan.trackComponentAttention(
67+
name,
68+
el,
69+
visibilityThreshold,
70+
isTrackingVideo,
71+
);
6672
log('dotcom', '🧿 Ophan tracking component attention:', name, {
6773
el,
6874
visibilityThreshold,
75+
isTrackingVideo,
6976
});
7077
};
7178

dotcom-rendering/src/components/LoopVideo.importable.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { log, storage } from '@guardian/libs';
33
import { SvgAudio, SvgAudioMute } from '@guardian/source/react-components';
44
import { useCallback, useEffect, useRef, useState } from 'react';
55
import {
6+
getOphan,
67
submitClickComponentEvent,
78
submitComponentEvent,
89
} from '../client/ophan/ophan';
@@ -52,6 +53,13 @@ const logAndReportError = (src: string, error: Error) => {
5253
log('dotcom', message);
5354
};
5455

56+
const dispatchOphanAttentionEvent = (
57+
eventType: 'videoPlaying' | 'videoPause',
58+
) => {
59+
const event = new Event(eventType, { bubbles: true });
60+
document.dispatchEvent(event);
61+
};
62+
5563
type Props = {
5664
src: string;
5765
atomId: string;
@@ -103,9 +111,11 @@ export const LoopVideo = ({
103111
*/
104112
const [hasBeenInView, setHasBeenInView] = useState(false);
105113

114+
const VISIBILITY_THRESHOLD = 0.5;
115+
106116
const [isInView, setNode] = useIsInView({
107117
repeat: true,
108-
threshold: 0.5,
118+
threshold: VISIBILITY_THRESHOLD,
109119
});
110120

111121
const playVideo = useCallback(async () => {
@@ -119,6 +129,7 @@ export const LoopVideo = ({
119129
await startPlayPromise
120130
.then(() => {
121131
// Autoplay succeeded
132+
dispatchOphanAttentionEvent('videoPlaying');
122133
setPlayerState('PLAYING');
123134
})
124135
.catch((error: Error) => {
@@ -145,6 +156,7 @@ export const LoopVideo = ({
145156
}
146157

147158
setPlayerState(reason);
159+
dispatchOphanAttentionEvent('videoPause');
148160
void vidRef.current.pause();
149161
};
150162

@@ -239,6 +251,29 @@ export const LoopVideo = ({
239251
};
240252
}, [uniqueId]);
241253

254+
/**
255+
* Initiates attention tracking for ophan
256+
*/
257+
useEffect(() => {
258+
const video = vidRef.current;
259+
if (!video) return;
260+
const trackAttention = async () => {
261+
try {
262+
const ophan = await getOphan('Web');
263+
ophan.trackComponentAttention(
264+
`gu-video-loop-${atomId}`,
265+
video,
266+
VISIBILITY_THRESHOLD,
267+
true,
268+
);
269+
} catch (error) {
270+
console.error('Failed to track video attention:', error);
271+
}
272+
};
273+
274+
void trackAttention();
275+
}, [atomId]);
276+
242277
/**
243278
* Keeps track of whether the video has been in view or not.
244279
*/

0 commit comments

Comments
 (0)