-
Notifications
You must be signed in to change notification settings - Fork 230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WSTEAM1-1514: Add click tracking at top level #12360
base: latest
Are you sure you want to change the base?
Conversation
|
||
return ( | ||
<div css={getItemCss({ dir, size })} dir={dir}> | ||
<a | ||
css={[styles.link, size === 'default' && styles.defaultLink]} | ||
href={href} | ||
onClick={clickTrackerHandler} | ||
{...(isLite && { [LITE_TRACKER_PARAM]: liteUrl })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that in order to add tracking on lite, we would need to add this line to every single component? Is there a way of doing this for all components? I wondered if that should be part of the intercepting of the click
event...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be really hard to do without duplicating a lot of the atiTracking logic in vanilla js.
@@ -9,6 +10,7 @@ import { ServiceContext } from '../../contexts/ServiceContext'; | |||
import { isValidClick } from './clickTypes'; | |||
|
|||
const EVENT_TYPE = 'click'; | |||
export const LITE_TRACKER_PARAM = 'data-ati-tracking'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: Naming things is 🧑🔬 (ignore this for the spike - perhaps when we productionise it, we can rename)
export const LITE_TRACKER_PARAM = 'data-ati-tracking'; | |
export const LITE_ATI_TRACKING = 'data-lite-ati-tracking'; |
@@ -0,0 +1,92 @@ | |||
export default function trackingScript() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there duplication between this and the canonical ATI code, and is there any way of sharing the code / implementing it once in one place? I would be keen to keep this script as small as possible 🤞
e.g. can we use https://github.com/bbc/simorgh/blob/c326deb0c8e9ca4469c471a784e12f6eb0eaac51/src/app/lib/analyticsUtils/index.js and have even more branching logic for platform === 'lite'
? Or is that just a maintenance nightmare, since we already have amp & canonical code in here?
} | ||
} | ||
|
||
if (!atUserIdValue && crypto.randomUUID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to worry about Opera Mini + Lite, or does this work? Or is the point of Opera Mini that all users have the same ID, so it would be impossible for us to detect unique users?
const componentName = props?.componentName; | ||
const url = props?.url; | ||
const advertiserID = props?.advertiserID; | ||
const format = props?.format; | ||
const detailedPlacement = props?.detailedPlacement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use destructuring here?
@@ -1,5 +1,6 @@ | |||
/* eslint-disable react/no-danger */ | |||
import React, { ReactElement, PropsWithChildren } from 'react'; | |||
import trackingScript from '#src/server/utilities/clickTrackingScript/clickTracking'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we rename the folder / file, let's also rename it here
const clickTrackerHandler = isLite | ||
? { | ||
[LITE_TRACKER_PARAM]: useConstructLiteSiteUrl(eventTrackingData), | ||
} | ||
: { | ||
onClick: useClickTrackerHandler(eventTrackingData), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this logic be moved into the useClickTrackerHandler
code, meaning that the only changes we would need to make to the other components which have click tracking would be what you've done in this file on line 68?
|
||
trackingScript(); | ||
|
||
document.cookie = |
Check warning
Code scanning / CodeQL
Clear text transmission of sensitive cookie Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI about 23 hours ago
To fix the problem, we need to ensure that the cookie is transmitted using SSL by setting the secure
attribute on the cookie. This can be done by modifying the document.cookie
assignment to include the secure
attribute. This change should be made in the beforeEach
block where the cookie is being set.
-
Copy modified line R22 -
Copy modified line R54
@@ -21,3 +21,3 @@ | ||
document.cookie = | ||
'atuserid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; | ||
'atuserid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; secure;'; | ||
|
||
@@ -53,3 +53,3 @@ | ||
|
||
expect(document.cookie).toBe('atuserid={"val":"randomUniqueId"}'); | ||
expect(document.cookie).toBe('atuserid={"val":"randomUniqueId"}; secure'); | ||
}); |
'https://logws1363.ati-host.net/?', | ||
); | ||
|
||
document.cookie = 'atuserid={"val":"oldCookieId"}'; |
Check warning
Code scanning / CodeQL
Clear text transmission of sensitive cookie Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix AI about 24 hours ago
To fix the problem, we need to ensure that the cookie is transmitted using SSL by setting the secure
attribute on the cookie. This can be done by appending ; secure
to the cookie string when setting it. This change should be made in the test file where the cookie is being set.
-
Copy modified line R54 -
Copy modified line R64
@@ -53,3 +53,3 @@ | ||
|
||
expect(document.cookie).toBe('atuserid={"val":"randomUniqueId"}'); | ||
expect(document.cookie).toBe('atuserid={"val":"randomUniqueId"}; secure'); | ||
}); | ||
@@ -63,3 +63,3 @@ | ||
|
||
document.cookie = 'atuserid={"val":"oldCookieId"}'; | ||
document.cookie = 'atuserid={"val":"oldCookieId"}; secure'; | ||
randomUUIDMock.mockReturnValueOnce('newCookieId'); |
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be replaced with
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | |
// @ts-ignore | |
// @ts-expect-error Explain why here |
const randomUUIDMock = jest.fn(); | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
jest.useFakeTimers().setSystemTime(new Date(1731515402000)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: Could we use the ISO Date, so that we don't need to calculate what date/time this represents?
jest.useFakeTimers().setSystemTime(new Date(1731515402000)); | |
jest.useFakeTimers().setSystemTime(new Date("2024-11-13T16:30:02.000Z")); |
trackingScript(); | ||
|
||
document.cookie = | ||
'atuserid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we use a more realistic expiry date here?
'atuserid=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; | |
'atuserid=; expires=Wed, 01 Jan 2025 00:00:00 UTC; path=/;'; |
const { isLite } = useContext(RequestContext); | ||
|
||
const clickTrackerHandler = isLite | ||
? { | ||
[LITE_TRACKER_PARAM]: useConstructLiteSiteATIEventTrackUrl(eventTrackingData), | ||
} | ||
: { | ||
onClick: useClickTrackerHandler(eventTrackingData), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for the spike, but I would like to see this extracted into a utility - perhaps somewhere adjacent to, or within the useClickTrackerHandler - which we can reuse for all other components we would like to add click tracking to.
@@ -205,6 +205,77 @@ exports[`Document Component should render LITE version correctly 1`] = ` | |||
<style> | |||
.css-7prgni-StyledLink{display:inline-block;} | |||
</style> | |||
<script> | |||
(function trackingScript() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't expecting this, but was there an existing test which already snapshots the Document component?
Object.defineProperty(global, 'crypto', { | ||
value: { | ||
randomUUID: randomUUIDMock, | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for spike but we should probably move this to the src/testHelpers/jest-setup.js file so that we don't have to keep mocking it in other places
Resolves JIRA WSTEAM1-1514
Overall changes
Implements changes from #12332
Code changes
Testing
Helpful Links
Add Links to useful resources related to this PR if applicable.
Coding Standards
Repository use guidelines