diff --git a/dotcom-rendering/src/components/EnhanceAffiliateLinks.importable.tsx b/dotcom-rendering/src/components/EnhanceAffiliateLinks.importable.tsx index 40e3cc5ac37..f443f1f4bf0 100644 --- a/dotcom-rendering/src/components/EnhanceAffiliateLinks.importable.tsx +++ b/dotcom-rendering/src/components/EnhanceAffiliateLinks.importable.tsx @@ -1,10 +1,12 @@ import { useEffect } from 'react'; import { getSkimlinksAccountId, isSkimlink } from '../lib/affiliateLinksUtils'; +import { useBetaAB } from '../lib/useAB'; /** * Add custom parameters to skimlink URLs: - * - referrer + * - Referrer * - Skimlinks account ID + * - AB test participations * * ## Why does this need to be an Island? * @@ -15,6 +17,18 @@ import { getSkimlinksAccountId, isSkimlink } from '../lib/affiliateLinksUtils'; * (No visual story exists as this does not render anything) */ export const EnhanceAffiliateLinks = () => { + const abTests = useBetaAB(); + + // Get users server/client-side AB test participations + const abTestParticipations = abTests?.getParticipations(); + + // Reduce abTestParticipations to a comma-separated string + const abTestString = abTestParticipations + ? Object.entries(abTestParticipations) + .map(([key, value]) => `${key}:${value}`) + .join(',') + : ''; + useEffect(() => { const allLinksOnPage = [...document.querySelectorAll('a')]; @@ -28,7 +42,9 @@ export const EnhanceAffiliateLinks = () => { const skimlinksAccountId = getSkimlinksAccountId(link.href); // Skimlinks treats xcust as one long string, so we use | to separate values - const xcustValue = `referrer|${referrerDomain}|accountId|${skimlinksAccountId}`; + const xcustValue = `referrer|${referrerDomain}|accountId|${skimlinksAccountId}${ + abTestString ? `|abTestParticipations|${abTestString}` : '' + }`; link.href = `${link.href}&xcust=${encodeURIComponent( xcustValue, diff --git a/dotcom-rendering/src/components/EnhanceAffiliateLinks.test.tsx b/dotcom-rendering/src/components/EnhanceAffiliateLinks.test.tsx new file mode 100644 index 00000000000..cb74d50bdc1 --- /dev/null +++ b/dotcom-rendering/src/components/EnhanceAffiliateLinks.test.tsx @@ -0,0 +1,84 @@ +import '@testing-library/jest-dom'; +import { render } from '@testing-library/react'; +import { useBetaAB } from '../lib/useAB'; +import { EnhanceAffiliateLinks } from './EnhanceAffiliateLinks.importable'; + +// Mock the useAB module +jest.mock('../lib/useAB', () => ({ + useBetaAB: jest.fn(), +})); + +describe('EnhanceAffiliateLinks', () => { + beforeEach(() => { + // Clear the DOM before each test + document.body.innerHTML = ''; + jest.restoreAllMocks(); + }); + + it('should not modify links if no Skimlinks are present', () => { + document.body.innerHTML = ` + Not a Skimlink + `; + + render(); + + const link = document.querySelector('a'); + expect(link?.href).toBe('https://example.com/'); + }); + + it('should append xcust parameter to Skimlinks with refferer set to none if unavailable', () => { + Object.defineProperty(document, 'referrer', { + value: '', + configurable: true, + }); + + document.body.innerHTML = ` + Skimlink + `; + + render(); + + const link = document.querySelector('a'); + expect(link?.href).toContain( + 'xcust=referrer%7Cnone%7CaccountId%7C12345', + ); + }); + + it('should append xcust parameter to Skimlinks with refferer set if available', () => { + Object.defineProperty(document, 'referrer', { + value: 'https://foo.com', + configurable: true, + }); + + document.body.innerHTML = ` + Skimlink + `; + + render(); + + const link = document.querySelector('a'); + expect(link?.href).toContain( + 'xcust=referrer%7Cfoo.com%7CaccountId%7C12345', + ); + }); + + it('should include AB test participations in xcust if present', () => { + document.body.innerHTML = ` + Skimlink + `; + + (useBetaAB as jest.Mock).mockReturnValue({ + getParticipations: () => ({ + test1: 'variantA', + test2: 'variantB', + }), + }); + + render(); + + const link = document.querySelector('a'); + expect(link?.href).toContain( + 'xcust=referrer%7Cfoo.com%7CaccountId%7C12345%7CabTestParticipations%7Ctest1%3AvariantA%2Ctest2%3AvariantB', + ); + }); +});