Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions ab-testing/config/abTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,19 @@ const ABTests: ABTest[] = [
],
shouldForceMetricsCollection: true,
},
{
name: "commercial-article-end-header-bidding",
description:
"Test opening up the article-end ad slot in the US region for HeaderBidding",
owners: ["commercial.dev@guardian.co.uk"],
expirationDate: "2026-10-01",
type: "client",
status: "ON",
audienceSize: 0 / 100,
audienceSpace: "B",
groups: ["control", "variant"],
shouldForceMetricsCollection: true,
},
];

const activeABtests = ABTests.filter((test) => test.status === "ON");
Expand Down
17 changes: 15 additions & 2 deletions dotcom-rendering/src/components/SlotBodyEnd.island.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { render, waitFor } from '@testing-library/react';
import { pickMessage } from '../lib/messagePicker';
import { useAB } from '../lib/useAB';
import { useCountryCode } from '../lib/useCountryCode';
import { ConfigProvider } from './ConfigContext';
import { SlotBodyEnd } from './SlotBodyEnd.island';
Expand Down Expand Up @@ -34,7 +35,9 @@ jest.mock('../lib/useBraze', () => ({
}));

jest.mock('../lib/useAB', () => ({
useAB: jest.fn().mockReturnValue(null),
useAB: jest.fn().mockReturnValue({
isUserInTestGroup: jest.fn().mockReturnValue(false),
}),
}));

jest.mock('../lib/braze/BrazeBannersSystem', () => ({
Expand Down Expand Up @@ -95,6 +98,15 @@ const renderSlotBodyEnd = (props: Partial<typeof defaultProps> = {}) =>

const mockPickMessage = jest.mocked(pickMessage);
const mockUseCountryCode = jest.mocked(useCountryCode);
const mockUseAB = jest.mocked(useAB);

const mockInArticleEndHeaderBiddingTest = () => {
mockUseAB.mockReturnValue({
isUserInTestGroup: (testId: string, groupId: string) =>
testId === 'commercial-article-end-header-bidding' &&
groupId === 'variant',
} as ReturnType<typeof useAB>);
};

describe('SlotBodyEnd', () => {
afterEach(() => {
Expand Down Expand Up @@ -134,8 +146,8 @@ describe('SlotBodyEnd', () => {
type: 'NoMessageSelected',
});

// showPublicGood requires countryCode === 'US'
mockUseCountryCode.mockReturnValue('US');
mockInArticleEndHeaderBiddingTest();

const { findByTestId } = renderSlotBodyEnd({
renderAds: true,
Expand All @@ -151,6 +163,7 @@ describe('SlotBodyEnd', () => {
});

mockUseCountryCode.mockReturnValue('US');
mockInArticleEndHeaderBiddingTest();

const dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');

Expand Down
17 changes: 14 additions & 3 deletions dotcom-rendering/src/components/SlotBodyEnd.island.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type Props = {

const slotStyles = css`
color: ${palette.neutral[7]};
margin: 12px auto;
`;

const buildReaderRevenueEpicConfig = (
Expand Down Expand Up @@ -130,10 +131,18 @@ export const SlotBodyEnd = ({
const [asyncArticleCount, setAsyncArticleCount] =
useState<Promise<WeeklyArticleHistory | undefined>>();

const showPublicGood = countryCode === 'US';
const isInUS = countryCode === 'US';
const isInArticleEndHeaderBiddingTest = abTests?.isUserInTestGroup(
'commercial-article-end-header-bidding',
'variant',
);

const showArticleEndSlot =
renderAds && !isLabs && showPublicGood && articleEndSlot;
renderAds &&
!isLabs &&
isInUS &&
articleEndSlot &&
isInArticleEndHeaderBiddingTest;

useEffect(() => {
setAsyncArticleCount(
Expand Down Expand Up @@ -238,7 +247,9 @@ export const SlotBodyEnd = ({
new CustomEvent('gu.commercial.slot.fill', {
detail: {
slotId: 'dfp-ad--article-end',
additionalSizes: { mobile: [adSizes.fluid] }, // Public Good additional ad slot sizes
additionalSizes: {
mobile: [adSizes.mpu],
},
},
}),
);
Expand Down
Loading