Skip to content

Commit

Permalink
WORLDSERVICE-379: Add view tracking (#12447)
Browse files Browse the repository at this point in the history
* WORLDSERVICE-379: Add view tracking

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: UpdatE

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* Add E2E tests for related topics on lite article pages

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

* WORLDSERVICE-379: Update

---------

Co-authored-by: Karina Thomas <[email protected]>
  • Loading branch information
shayneahchoon and karinathomasbbc authored Mar 7, 2025
1 parent c911463 commit e0b2921
Show file tree
Hide file tree
Showing 19 changed files with 355 additions and 191 deletions.
1 change: 1 addition & 0 deletions cypress/e2e/specialFeatures/atiAnalytics/index.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ const liteTestSuites = canonicalTestSuites
switch (testSuite.contentType) {
case 'article':
liteSiteTests.push(assertLiteSiteCTAComponentClick);
liteSiteTests.push(assertRelatedTopicsComponentView);
break;
case 'index-home':
liteSiteTests.push(assertMostReadComponentClick);
Expand Down
2 changes: 1 addition & 1 deletion scripts/bundleSize/bundleSizeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
* We are allowing a variance of -5 on `MIN_SIZE` and +5 on `MAX_SIZE` to avoid the need for frequent changes, as bundle sizes can fluctuate
*/

export const MIN_SIZE = 673 - 5;
export const MIN_SIZE = 759 - 5;
export const MAX_SIZE = 1213 + 5;
20 changes: 13 additions & 7 deletions src/app/hooks/useClickTrackerHandler/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { sendEventBeacon } from '../../components/ATIAnalytics/beacon/index';
import { ServiceContext } from '../../contexts/ServiceContext';
import { isValidClick } from './clickTypes';

const EVENT_TYPE = 'click';
const CLICK_EVENT = 'click';
export const LITE_ATI_TRACKING = 'data-lite-ati-tracking';

const extractTrackingProps = (props = {}) => {
const extractTrackingProps = (props = {}, eventType = null) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const eventTrackingContext = useContext(EventTrackingContext);

Expand All @@ -35,7 +35,7 @@ const extractTrackingProps = (props = {}) => {
componentName,
campaignID,
format,
type: EVENT_TYPE,
type: eventType,
advertiserID,
url,
detailedPlacement,
Expand Down Expand Up @@ -115,7 +115,7 @@ const useClickTrackerHandler = (props = {}) => {

try {
await sendEventBeacon({
type: EVENT_TYPE,
type: CLICK_EVENT,
campaignID,
componentName,
format,
Expand Down Expand Up @@ -168,15 +168,21 @@ const useClickTrackerHandler = (props = {}) => {
);
};

export const useConstructLiteSiteATIEventTrackUrl = (props = {}) => {
const atiTrackingParams = extractTrackingProps(props);
export const useConstructLiteSiteATIEventTrackUrl = ({
props = {},
eventType = null,
}) => {
const atiTrackingParams = extractTrackingProps(props, eventType);
return buildATIEventTrackUrl(atiTrackingParams);
};

export const useATIClickTrackerHandler = (props = {}) => {
const { isLite } = useContext(RequestContext);
const clickTrackerHandler = useClickTrackerHandler(props);
const liteHandler = useConstructLiteSiteATIEventTrackUrl(props);
const liteHandler = useConstructLiteSiteATIEventTrackUrl({
props,
eventType: CLICK_EVENT,
});

return isLite
? { [LITE_ATI_TRACKING]: liteHandler }
Expand Down
7 changes: 5 additions & 2 deletions src/app/hooks/useClickTrackerHandler/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,11 @@ describe('Lite Site - Click tracking', () => {
const { result } = renderHook(
() =>
useConstructLiteSiteATIEventTrackUrl({
...defaultProps,
campaignID: 'custom-campaign',
props: {
...defaultProps,
campaignID: 'custom-campaign',
},
eventType: 'click',
}),
{
wrapper,
Expand Down
17 changes: 15 additions & 2 deletions src/app/hooks/useViewTracker/index.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { useContext, useEffect, useState, useRef } from 'react';
import prop from 'ramda/src/prop';

import { RequestContext } from '#app/contexts/RequestContext';
import { sendEventBeacon } from '../../components/ATIAnalytics/beacon';
import { EventTrackingContext } from '../../contexts/EventTrackingContext';
import useTrackingToggle from '../useTrackingToggle';
import OPTIMIZELY_CONFIG from '../../lib/config/optimizely';
import { ServiceContext } from '../../contexts/ServiceContext';
import { useConstructLiteSiteATIEventTrackUrl } from '../useClickTrackerHandler';

const EVENT_TYPE = 'view';
const VIEW_EVENT = 'view';
const VIEWED_DURATION_MS = 1000;
const MIN_VIEWED_PERCENT = 0.5;
export const LITE_ATI_VIEW_TRACKING = 'data-lite-ati-view-tracking';

/**
*
Expand Down Expand Up @@ -110,7 +113,7 @@ const useViewTracker = (props = {}) => {
producerName,
service,
statsDestination,
type: EVENT_TYPE,
type: VIEW_EVENT,
advertiserID,
url,
detailedPlacement,
Expand Down Expand Up @@ -167,4 +170,14 @@ const useViewTracker = (props = {}) => {
};
};

export const useLiteViewTracker = (props = {}) => {
const { isLite } = useContext(RequestContext);
const liteHandler = useConstructLiteSiteATIEventTrackUrl({
props,
eventType: VIEW_EVENT,
});

return isLite ? { [LITE_ATI_VIEW_TRACKING]: liteHandler } : null;
};

export default useViewTracker;
5 changes: 4 additions & 1 deletion src/app/legacy/containers/RelatedTopics/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '#psammead/gel-foundations/src/breakpoints';
import { RequestContext } from '#app/contexts/RequestContext';
import useClickTrackerHandler from '#hooks/useClickTrackerHandler';
import useViewTracker from '#hooks/useViewTracker';
import useViewTracker, { useLiteViewTracker } from '#hooks/useViewTracker';
import { ServiceContext } from '../../../contexts/ServiceContext';

const eventTrackingData = {
Expand Down Expand Up @@ -41,6 +41,7 @@ const RelatedTopics = ({
const { variant } = useContext(RequestContext);
const clickTrackerHandler = useClickTrackerHandler(eventTrackingData);
const viewRef = useViewTracker(eventTrackingData);
const liteViewTrack = useLiteViewTracker(eventTrackingData);
const heading = pathOr('Related Topics', ['relatedTopics'], translations);
const topicsPath = pathOr('topics', ['topicsPath'], translations);

Expand Down Expand Up @@ -85,6 +86,7 @@ const RelatedTopics = ({
link={getTopicPageUrl(topics[0].topicId)}
onClick={clickTrackerHandler}
ref={viewRef}
liteViewTracker={liteViewTrack}
key={topics[0].topicId}
/>
) : (
Expand All @@ -94,6 +96,7 @@ const RelatedTopics = ({
link={getTopicPageUrl(topicId)}
onClick={clickTrackerHandler}
ref={viewRef}
liteViewTracker={liteViewTrack}
key={topicId}
/>
))
Expand Down
13 changes: 7 additions & 6 deletions src/app/legacy/psammead/psammead-topic-tags/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ const SingleTopicTagItem = styled.div`
}
`;

export const TopicTag = forwardRef(({ name, link, onClick = null }, ref) => (
<a href={link} onClick={onClick} ref={ref}>
{name}
</a>
));
export const TopicTag = forwardRef(
({ name, link, onClick = null, liteViewTracker = null }, ref) => (
<a href={link} onClick={onClick} ref={ref} {...liteViewTracker}>
{name}
</a>
),
);

export const TopicTags = ({
children = [],
Expand All @@ -78,7 +80,6 @@ export const TopicTags = ({
<TopicsList role="list" service={service} script={script}>
{children.map((child, index) => {
if (child.type !== TopicTag) return null;

return (
<SingleTopicTagItem
as="li"
Expand Down
1 change: 1 addition & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ declare global {
cmd: { push: () => void };
};
sendBeaconLite: (url: string, data?: BodyInit | null) => boolean;
processClientDeviceAndSendLite: (url: string) => void;
}
}

Expand Down
14 changes: 12 additions & 2 deletions src/server/Document/Renderers/LiteRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
/* eslint-disable react/no-danger */
import React, { ReactElement, PropsWithChildren } from 'react';
import liteATIClickTracking from '#src/server/utilities/liteATIClickTracking';
import processClientDeviceAndSendLite from '#src/server/utilities/liteATITracking';
import clickTracking from '#src/server/utilities/liteATITracking/clickTracking';
import viewTracking from '#src/server/utilities/liteATITracking/viewTracking';
import { BaseRendererProps } from './types';

interface Props extends BaseRendererProps {
bodyContent: ReactElement;
}

const trackingScripts = () => `
window.addEventListener('load', function (){
(${processClientDeviceAndSendLite.toString()})();
(${clickTracking.toString()})();
(${viewTracking.toString()})();
});
`;

export default function LitePageRenderer({
bodyContent,
helmetMetaTags,
Expand All @@ -27,7 +37,7 @@ export default function LitePageRenderer({
<style dangerouslySetInnerHTML={{ __html: styles }} />
<script
dangerouslySetInnerHTML={{
__html: `(${liteATIClickTracking.toString()})()`,
__html: `${trackingScripts()}`,
}}
/>
</head>
Expand Down
14 changes: 12 additions & 2 deletions src/server/Document/__snapshots__/component.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,19 @@ exports[`Document Component should render LITE version correctly 1`] = `
.css-7prgni-StyledLink{display:inline-block;}
</style>
<script>
(function liteATIClickTracking() {
window.addEventListener('load', function (){
(function liteATIClickTracking() {
return 'Tracking script placeholder';
})()
})();
(function liteATIClickTracking() {
return 'Click script placeholder';
})();
(function liteATIClickTracking() {
return 'View script placeholder';
})();
});
</script>
</head>
<body>
Expand Down
14 changes: 13 additions & 1 deletion src/server/Document/component.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@ import DocumentComponent from './component';

Helmet.canUseDOM = false;

jest.mock('#src/server/utilities/liteATIClickTracking', () =>
jest.mock('#src/server/utilities/liteATITracking', () =>
function liteATIClickTracking() {
return 'Tracking script placeholder';
}.toString(),
);

jest.mock('#src/server/utilities/liteATITracking/clickTracking', () =>
function liteATIClickTracking() {
return 'Click script placeholder';
}.toString(),
);

jest.mock('#src/server/utilities/liteATITracking/viewTracking', () =>
function liteATIClickTracking() {
return 'View script placeholder';
}.toString(),
);

describe('Document Component', () => {
const originalProcessEnv = process.env;

Expand Down
98 changes: 0 additions & 98 deletions src/server/utilities/liteATIClickTracking/index.ts

This file was deleted.

Loading

0 comments on commit e0b2921

Please sign in to comment.