Skip to content

Commit c7cf083

Browse files
authored
Choice cards tracking (#14477)
* Track choice cards events * fix type
1 parent 1bcc3f8 commit c7cf083

File tree

3 files changed

+129
-82
lines changed

3 files changed

+129
-82
lines changed

dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBanner.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ const DesignableBanner: ReactComponent<BannerRenderProps> = ({
479479
}
480480
choices={choiceCards}
481481
id={'banner'}
482+
submitComponentEvent={submitComponentEvent}
482483
/>
483484
)}
484485
<div css={styles.ctaContainer(isCollapsed)}>

dotcom-rendering/src/components/marketing/epics/ctas/ContributionsEpicCtasContainer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const ContributionsEpicCtasContainer: ReactComponent<Props> = ({
5555
setSelectedChoiceCard={setSelectedChoiceCard}
5656
choices={choiceCards}
5757
id={'epic'}
58+
submitComponentEvent={submitComponentEvent}
5859
/>
5960
)}
6061
<ContributionsEpicButtons

dotcom-rendering/src/components/marketing/shared/ThreeTierChoiceCards.tsx

Lines changed: 127 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { css } from '@emotion/react';
2+
import type { ComponentEvent } from '@guardian/ophan-tracker-js';
23
import {
34
palette,
45
space,
@@ -19,7 +20,9 @@ import { hexColourToString } from '@guardian/support-dotcom-components';
1920
import type { HexColour } from '@guardian/support-dotcom-components/dist/shared/types';
2021
import type { ChoiceCard } from '@guardian/support-dotcom-components/dist/shared/types/props/choiceCards';
2122
import type { Dispatch, SetStateAction } from 'react';
23+
import { useEffect } from 'react';
2224
import sanitise from 'sanitize-html';
25+
import { useIsInView } from '../../../lib/useIsInView';
2326

2427
const supportTierChoiceCardStyles = (selected: boolean) => css`
2528
display: block;
@@ -151,102 +154,144 @@ type ThreeTierChoiceCardsProps = {
151154
selectedChoiceCard: ChoiceCard;
152155
setSelectedChoiceCard: Dispatch<SetStateAction<ChoiceCard | undefined>>;
153156
choices: ChoiceCard[];
154-
id: string; // uniquely identify this choice cards component to avoid conflicting with others
157+
id: 'epic' | 'banner'; // uniquely identify this choice cards component to avoid conflicting with others
158+
submitComponentEvent?: (componentEvent: ComponentEvent) => void;
155159
};
156160

157161
export const ThreeTierChoiceCards = ({
158162
selectedChoiceCard,
159163
setSelectedChoiceCard,
160164
choices,
161165
id,
166+
submitComponentEvent,
162167
}: ThreeTierChoiceCardsProps) => {
168+
const [hasBeenSeen, setNode] = useIsInView({
169+
debounce: true,
170+
threshold: 0,
171+
});
172+
173+
useEffect(() => {
174+
if (submitComponentEvent) {
175+
void submitComponentEvent({
176+
component: {
177+
componentType: 'ACQUISITIONS_OTHER',
178+
id: `${id}-choice-cards`,
179+
},
180+
action: 'INSERT',
181+
});
182+
}
183+
}, [id, submitComponentEvent]);
184+
185+
useEffect(() => {
186+
if (hasBeenSeen && submitComponentEvent) {
187+
void submitComponentEvent({
188+
component: {
189+
componentType: 'ACQUISITIONS_OTHER',
190+
id: `${id}-choice-cards`,
191+
},
192+
action: 'VIEW',
193+
});
194+
}
195+
}, [hasBeenSeen, id, submitComponentEvent]);
196+
163197
return (
164-
<RadioGroup
165-
cssOverrides={css`
166-
margin-top: ${space[6]}px;
167-
`}
168-
>
169-
<Stack space={3}>
170-
{choices.map((card) => {
171-
const { product, label, benefitsLabel, benefits, pill } =
172-
card;
173-
const { supportTier } = product;
174-
175-
const isSelected = (): boolean => {
176-
if (
177-
product.supportTier ===
178-
selectedChoiceCard.product.supportTier
179-
) {
198+
<div ref={setNode}>
199+
<RadioGroup
200+
cssOverrides={css`
201+
margin-top: ${space[6]}px;
202+
`}
203+
>
204+
<Stack space={3}>
205+
{choices.map((card) => {
206+
const {
207+
product,
208+
label,
209+
benefitsLabel,
210+
benefits,
211+
pill,
212+
} = card;
213+
const { supportTier } = product;
214+
215+
const isSelected = (): boolean => {
180216
if (
181-
product.supportTier !== 'OneOff' &&
182-
selectedChoiceCard.product.supportTier !==
183-
'OneOff'
217+
product.supportTier ===
218+
selectedChoiceCard.product.supportTier
184219
) {
185-
return (
186-
product.ratePlan ===
187-
selectedChoiceCard.product.ratePlan
188-
);
220+
if (
221+
product.supportTier !== 'OneOff' &&
222+
selectedChoiceCard.product.supportTier !==
223+
'OneOff'
224+
) {
225+
return (
226+
product.ratePlan ===
227+
selectedChoiceCard.product.ratePlan
228+
);
229+
} else {
230+
return true;
231+
}
189232
} else {
190-
return true;
233+
return false;
191234
}
192-
} else {
193-
return false;
194-
}
195-
};
196-
const selected = isSelected();
197-
198-
// Each radioId must be unique to the component and choice, e.g. "choicecard-epic-Contribution-Monthly"
199-
const radioId = `choicecard-${id}-${supportTier}${
200-
supportTier !== 'OneOff' ? `-${product.ratePlan}` : ''
201-
}`;
202-
203-
return (
204-
<div
205-
key={supportTier}
206-
css={css`
207-
position: relative;
208-
background-color: inherit;
209-
`}
210-
>
211-
{pill && <ChoiceCardPill pill={pill} />}
212-
<label
213-
css={supportTierChoiceCardStyles(selected)}
214-
htmlFor={radioId}
235+
};
236+
const selected = isSelected();
237+
238+
// Each radioId must be unique to the component and choice, e.g. "choicecard-epic-Contribution-Monthly"
239+
const radioId = `choicecard-${id}-${supportTier}${
240+
supportTier !== 'OneOff'
241+
? `-${product.ratePlan}`
242+
: ''
243+
}`;
244+
245+
return (
246+
<div
247+
key={supportTier}
248+
css={css`
249+
position: relative;
250+
background-color: inherit;
251+
`}
215252
>
216-
<Radio
217-
label={
218-
<span
219-
dangerouslySetInnerHTML={{
220-
__html: sanitise(label),
221-
}}
222-
/>
223-
}
224-
id={radioId}
225-
value={radioId}
226-
cssOverrides={labelOverrideStyles(selected)}
227-
supporting={
228-
selected && (
229-
<SupportingBenefits
230-
benefitsLabel={
231-
benefitsLabel as
232-
| string
233-
| undefined
234-
}
235-
benefits={benefits}
253+
{pill && <ChoiceCardPill pill={pill} />}
254+
<label
255+
css={supportTierChoiceCardStyles(selected)}
256+
htmlFor={radioId}
257+
>
258+
<Radio
259+
label={
260+
<span
261+
dangerouslySetInnerHTML={{
262+
__html: sanitise(label),
263+
}}
236264
/>
237-
)
238-
}
239-
checked={selected}
240-
onChange={() => {
241-
setSelectedChoiceCard(card);
242-
}}
243-
theme={customRadioTheme}
244-
/>
245-
</label>
246-
</div>
247-
);
248-
})}
249-
</Stack>
250-
</RadioGroup>
265+
}
266+
id={radioId}
267+
value={radioId}
268+
cssOverrides={labelOverrideStyles(
269+
selected,
270+
)}
271+
supporting={
272+
selected && (
273+
<SupportingBenefits
274+
benefitsLabel={
275+
benefitsLabel as
276+
| string
277+
| undefined
278+
}
279+
benefits={benefits}
280+
/>
281+
)
282+
}
283+
checked={selected}
284+
onChange={() => {
285+
setSelectedChoiceCard(card);
286+
}}
287+
theme={customRadioTheme}
288+
/>
289+
</label>
290+
</div>
291+
);
292+
})}
293+
</Stack>
294+
</RadioGroup>
295+
</div>
251296
);
252297
};

0 commit comments

Comments
 (0)