From 590bcfb74c461520eea10439cde0bde53ea24850 Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Thu, 5 Mar 2026 14:23:58 +0000 Subject: [PATCH 1/2] Add an apps autoplay check --- dotcom-rendering/package.json | 2 +- .../components/SelfHostedVideo.importable.tsx | 60 ++++++++++++------- pnpm-lock.yaml | 26 ++++---- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/dotcom-rendering/package.json b/dotcom-rendering/package.json index 513c7fb3897..9b16eca0cf4 100644 --- a/dotcom-rendering/package.json +++ b/dotcom-rendering/package.json @@ -29,7 +29,7 @@ "@guardian/ab-core": "8.0.0", "@guardian/ab-testing-config": "workspace:ab-testing-config", "@guardian/braze-components": "22.2.0", - "@guardian/bridget": "8.7.0", + "@guardian/bridget": "8.8.0-2026-03-05", "@guardian/browserslist-config": "6.1.0", "@guardian/cdk": "62.3.5", "@guardian/commercial-core": "29.0.0", diff --git a/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx b/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx index 0be269000b8..ee5b778d72e 100644 --- a/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx +++ b/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx @@ -9,6 +9,7 @@ import { submitComponentEvent, } from '../client/ophan/ophan'; import type { ArticleFormat } from '../lib/articleFormat'; +import { getVideoClient } from '../lib/bridgetApi'; import { getZIndex } from '../lib/getZIndex'; import { generateImageURL } from '../lib/image'; import { useIsInView } from '../lib/useIsInView'; @@ -266,6 +267,30 @@ type Props = { role?: RoleType; }; +const doesUserPermitAutoplayOnWeb = (): boolean => { + /** + * The user indicates a preference for reduced motion: https://web.dev/articles/prefers-reduced-motion + */ + const userPrefersReducedMotion = window.matchMedia( + '(prefers-reduced-motion: reduce)', + ).matches; + + /** + * The user can set this on their Accessibility Settings page. + * Explicitly `false` when the user has said they don't want autoplay video. + */ + const autoplayPreference = storage.local.get( + 'gu.prefs.accessibility.autoplay-video', + ); + + return !userPrefersReducedMotion && autoplayPreference !== false; +}; + +const doesUserPermitAutoplayOnApps = async (): Promise => { + const videoClient = getVideoClient(); + return videoClient.isAutoplayEnabled(); +}; + export const SelfHostedVideo = ({ sources, atomId, @@ -397,25 +422,6 @@ export const SelfHostedVideo = ({ /> ); - const doesUserPermitAutoplay = (): boolean => { - /** - * The user indicates a preference for reduced motion: https://web.dev/articles/prefers-reduced-motion - */ - const userPrefersReducedMotion = window.matchMedia( - '(prefers-reduced-motion: reduce)', - ).matches; - - /** - * The user can set this on their Accessibility Settings page. - * Explicitly `false` when the user has said they don't want autoplay video. - */ - const autoplayPreference = storage.local.get( - 'gu.prefs.accessibility.autoplay-video', - ); - - return !userPrefersReducedMotion && autoplayPreference !== false; - }; - /** * Setup. * @@ -424,7 +430,11 @@ export const SelfHostedVideo = ({ * 3. Creates event listeners to control playback when there are multiple videos. */ useEffect(() => { - setIsAutoplayAllowed(doesUserPermitAutoplay()); + if (renderingTarget === 'Apps') { + void doesUserPermitAutoplayOnApps().then(setIsAutoplayAllowed); + } else { + setIsAutoplayAllowed(doesUserPermitAutoplayOnWeb()); + } /** * Initialise Ophan attention tracking @@ -464,7 +474,13 @@ export const SelfHostedVideo = ({ */ const handleRestoreFromCache = (event: PageTransitionEvent) => { if (event.persisted) { - setIsAutoplayAllowed(doesUserPermitAutoplay()); + if (renderingTarget === 'Apps') { + void doesUserPermitAutoplayOnApps().then( + setIsAutoplayAllowed, + ); + } else { + setIsAutoplayAllowed(doesUserPermitAutoplayOnWeb()); + } setHasPageBecomeActive(true); } else { setHasPageBecomeActive(false); @@ -513,7 +529,7 @@ export const SelfHostedVideo = ({ handlePageBecomesVisible(); }); }; - }, [uniqueId, atomId]); + }, [uniqueId, atomId, renderingTarget]); /** * Track the first time the video comes into view. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2b28ca418d9..5934f130bfa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -299,8 +299,8 @@ importers: specifier: 22.2.0 version: 22.2.0(@emotion/react@11.14.0(@types/react@18.3.1)(react@18.3.1))(@guardian/libs@28.0.0(@guardian/ophan-tracker-js@2.8.0)(tslib@2.6.2)(typescript@5.5.3))(@guardian/source@11.3.0(@emotion/react@11.14.0(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3))(react@18.3.1) '@guardian/bridget': - specifier: 8.7.0 - version: 8.7.0 + specifier: 8.8.0-2026-03-05 + version: 8.8.0-2026-03-05 '@guardian/browserslist-config': specifier: 6.1.0 version: 6.1.0(browserslist@4.24.4)(tslib@2.6.2) @@ -2535,8 +2535,8 @@ packages: '@guardian/source': ^9.0.0 react: 17.0.2 || 18.2.0 - '@guardian/bridget@8.7.0': - resolution: {integrity: sha512-tqOHEDGfMz+UnDndwrmmatuvElgguaxjYNopvDBZ7W6DCxswvEvhCZfZZ56Q2msF+jr042XNpVPcKMsrHF8VJw==} + '@guardian/bridget@8.8.0-2026-03-05': + resolution: {integrity: sha512-bIyPIbWCPONZm3wL6MnIzocTRnRkpQc2rFoBY9q42uB5caIRF7R1gi8zglgBGeT842Sfn39dF3t0pKh/iFg9XA==} '@guardian/browserslist-config@6.1.0': resolution: {integrity: sha512-qM0QxAv6E5IHXny5Okli6AZXEio0mpXzzEzz38qrb4IwO91R6eWVKyihdj0qW2k7TVxMFVOSfNmBZ1H5EiJhgw==} @@ -12461,7 +12461,7 @@ snapshots: '@guardian/source': 11.3.0(@emotion/react@11.14.0(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3) react: 18.3.1 - '@guardian/bridget@8.7.0': {} + '@guardian/bridget@8.8.0-2026-03-05': {} '@guardian/browserslist-config@6.1.0(browserslist@4.24.4)(tslib@2.6.2)': dependencies: @@ -12502,12 +12502,12 @@ snapshots: '@guardian/eslint-config-typescript@12.0.0(eslint@8.57.1)(tslib@2.6.2)(typescript@5.5.3)': dependencies: - '@guardian/eslint-config': 9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)(tslib@2.6.2) + '@guardian/eslint-config': 9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)(tslib@2.6.2) '@stylistic/eslint-plugin': 2.6.2(eslint@8.57.1)(typescript@5.5.3) '@typescript-eslint/eslint-plugin': 8.1.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1)(typescript@5.5.3) '@typescript-eslint/parser': 8.1.0(eslint@8.57.1)(typescript@5.5.3) eslint: 8.57.1 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) tslib: 2.6.2 typescript: 5.5.3 @@ -12537,7 +12537,7 @@ snapshots: - supports-color - typescript - '@guardian/eslint-config@9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)(tslib@2.6.2)': + '@guardian/eslint-config@9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)(tslib@2.6.2)': dependencies: eslint: 8.57.1 eslint-config-prettier: 9.1.0(eslint@8.57.1) @@ -16546,12 +16546,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.1): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 4.4.3(supports-color@8.1.1) enhanced-resolve: 5.19.0 eslint: 8.57.1 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) fast-glob: 3.3.3 get-tsconfig: 4.7.2 @@ -16580,14 +16580,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.1.0(eslint@8.57.1)(typescript@5.5.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -16642,7 +16642,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 From 8ee265baf83703b04c9a2f92635b87741440b781 Mon Sep 17 00:00:00 2001 From: Anna Beddow Date: Wed, 11 Mar 2026 10:49:52 +0000 Subject: [PATCH 2/2] Use correct tracker for the provided rendering target --- .../src/components/SelfHostedVideo.importable.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx b/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx index ee5b778d72e..28312a161d5 100644 --- a/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx +++ b/dotcom-rendering/src/components/SelfHostedVideo.importable.tsx @@ -33,7 +33,7 @@ import type { SubtitleSize, } from './SelfHostedVideoPlayer'; import { SelfHostedVideoPlayer } from './SelfHostedVideoPlayer'; -import { ophanTrackerWeb } from './YoutubeAtom/eventEmitters'; +import { ophanTrackerApps, ophanTrackerWeb } from './YoutubeAtom/eventEmitters'; const VISIBILITY_THRESHOLD = 0.5; @@ -617,7 +617,11 @@ export const SelfHostedVideo = ({ const handlePlaying = () => { if (hasTrackedPlay) return; - ophanTrackerWeb(atomId, 'loop')('play'); + if (renderingTarget === 'Apps') { + ophanTrackerApps(atomId)('play'); + } else { + ophanTrackerWeb(atomId, 'loop')('play'); + } setHasTrackedPlay(true); };