Skip to content

Commit

Permalink
Show ads on mobile discussion (#1239)
Browse files Browse the repository at this point in the history
* Insert ad into comments

* Insert unique ids for comments-expanded mobile ads

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Fix imports

* Use setTimeout to load elements in the DOM

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Added a function that removes dynamically inserted ads in comments

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Remove existing slots on page change custom event

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Remove ad slots from dfp

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Resize label and center discussion ads

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Add destroySlots and timeout to wait for updated ul element

* Separate and tidy logic

Co-authored-by: Dina Hafez <dina.hafez@guardian.co.uk>

* Post rebase tidy up

* Don't use fastdom for getCommentsColumn()

* Remove unnecessary void

* Get comments-expanded ads working after rebase

* Remove setTimeout as no longer needed

Co-authored-by: Dina Hafez <dina.hafez@guardian.co.uk>

* Check if user is in variant

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Add changeset

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Add comments-expanded to slot config

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Reserve space for the mobile comments expanded

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Add check so that comments section never ends in an ad

* Don't insert slots if there are already some present on the page

* Replace comments-column class with data-attribute

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>

* Add adSizes.empty to mobile comments-expanded slot

* Use switch instead of AB test

---------

Co-authored-by: Emma Imber <108270776+emma-imber@users.noreply.github.com>
Co-authored-by: Emma Imber <emma-jo.imber@guardian.co.uk>
  • Loading branch information
3 people committed Feb 21, 2024
1 parent d1445e6 commit d285016
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/old-geese-applaud.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@guardian/commercial': minor
---

Add AB test to insert ads in mobile discussion
3 changes: 2 additions & 1 deletion src/core/ad-sizes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ const slotSizeMappings = {
],
},
'comments-expanded': {
mobile: [
mobile: [adSizes.mpu, adSizes.empty],
desktop: [
adSizes.outOfPage,
adSizes.empty,
adSizes.mpu,
Expand Down
2 changes: 2 additions & 0 deletions src/define/Advert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ const getSlotSizeMapping = (name: string): SizeMapping => {
slotName = 'fronts-banner';
} else if (name.includes('external')) {
slotName = 'external';
} else if (name.includes('comments-expanded')) {
slotName = 'comments-expanded';
} else {
slotName = name;
}
Expand Down
112 changes: 109 additions & 3 deletions src/insert/comments-expanded-advert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { adSizes } from 'core/ad-sizes';
import { AD_LABEL_HEIGHT } from 'core/constants/ad-label-height';
import { createAdSlot } from 'core/create-ad-slot';
import { commercialFeatures } from 'lib/commercial-features';
import { getBreakpoint } from 'lib/detect/detect-breakpoint';
import { getViewport } from 'lib/detect/detect-viewport';
import { dfpEnv } from 'lib/dfp/dfp-env';
import { getAdvertById } from 'lib/dfp/get-advert-by-id';
import fastdom from '../utils/fastdom-promise';
import { fillDynamicAdSlot } from './fill-dynamic-advert-slot';

Expand Down Expand Up @@ -32,6 +36,27 @@ const insertAd = (anchor: HTMLElement) => {
.then(() => fillDynamicAdSlot(slot, false));
};

const insertAdMobile = (anchor: HTMLElement, id: number) => {
log('commercial', `Inserting mobile comments-expanded-${id} advert`);
const slot = createAdSlot('comments-expanded', {
name: `comments-expanded-${id}`,
classes: 'comments-expanded',
});

const adSlotContainer = document.createElement('div');
adSlotContainer.className = 'ad-slot-container';
adSlotContainer.style.width = '300px';
adSlotContainer.style.height = `${adSizes.mpu.height + AD_LABEL_HEIGHT}px`;
adSlotContainer.style.margin = '20px auto';
adSlotContainer.appendChild(slot);

return fastdom
.mutate(() => {
anchor.appendChild(adSlotContainer);
})
.then(() => fillDynamicAdSlot(slot, false));
};

const getRightColumn = (): HTMLElement => {
const selector = window.guardian.config.isDotcomRendering
? '.commentsRightColumn'
Expand All @@ -43,6 +68,17 @@ const getRightColumn = (): HTMLElement => {
return rightColumn;
};

const getCommentsColumn = async (): Promise<HTMLElement> => {
return fastdom.measure(() => {
const commentsColumn: HTMLElement | null = document.querySelector(
'[data-commercial-id="comments-column"]',
);
if (!commentsColumn) throw new Error('Comments are not expanded.');

return commentsColumn;
});
};

const isEnoughSpaceForAd = (rightColumnNode: HTMLElement): boolean => {
// Only insert a second advert into the right-hand rail if there is enough space.
// There is enough space if the right-hand rail is larger than:
Expand All @@ -53,6 +89,16 @@ const isEnoughSpaceForAd = (rightColumnNode: HTMLElement): boolean => {
return rightColumnNode.offsetHeight >= minHeightToPlaceAd;
};

const isEnoughCommentsForAd = (commentsColumn: HTMLElement): boolean =>
commentsColumn.childElementCount >= 5;

const commentsExpandedAdsAlreadyExist = (): boolean => {
const commentsExpandedAds = document.querySelectorAll(
'.ad-slot--comments-expanded',
);
return commentsExpandedAds.length > 0 ? true : false;
};

const createResizeObserver = (rightColumnNode: HTMLElement) => {
// When the comments load and are rendered, the height of the right column
// will expand and there might be enough space to insert the ad.
Expand All @@ -67,6 +113,30 @@ const createResizeObserver = (rightColumnNode: HTMLElement) => {
resizeObserver.observe(rightColumnNode);
};

const removeMobileCommentsExpandedAds = (): Promise<void> => {
const currentBreakpoint = getBreakpoint(getViewport().width);
if (currentBreakpoint === 'mobile') {
const commentsExpandedAds = document.querySelectorAll(
'.ad-slot--comments-expanded',
);
return fastdom.mutate(() =>
commentsExpandedAds.forEach((node) => {
log('commercial', `Removing ad slot: ${node.id}`);
const advert = getAdvertById(node.id);
if (advert) {
window.googletag.destroySlots([advert.slot]);
}
node.remove();
dfpEnv.adverts.delete(node.id);
dfpEnv.advertsToLoad = dfpEnv.advertsToLoad.filter(
(_) => _ !== advert,
);
}),
);
}
return Promise.resolve();
};

/**
* Create a comments-expanded ad immediately if there is enough space for it. If not, then it
* is possible that we are still waiting for the Discussion API to load the comments, so we
Expand All @@ -92,10 +162,46 @@ const handleCommentsExpandedEvent = (): void => {
createResizeObserver(rightColumnNode);
};

const handleCommentsExpandedMobileEvent = async (): Promise<void> => {
const commentsColumn = await getCommentsColumn();
const currentBreakpoint = getBreakpoint(getViewport().width);

if (
currentBreakpoint === 'mobile' &&
isEnoughCommentsForAd(commentsColumn) &&
!commentsExpandedAdsAlreadyExist()
) {
let counter = 0;
for (let i = 0; i < commentsColumn.childElementCount; i++) {
if (
commentsColumn.childNodes[i] &&
(i - 3) % 5 === 0 &&
i + 1 < commentsColumn.childElementCount
) {
counter++;
const childElement = commentsColumn.childNodes[
i
] as HTMLElement;
void insertAdMobile(childElement, counter);
}
}
}
};

export const initCommentsExpandedAdverts = (): Promise<void> => {
document.addEventListener('comments-expanded', () =>
handleCommentsExpandedEvent(),
);
document.addEventListener('comments-expanded', () => {
handleCommentsExpandedEvent();
});

if (window.guardian.config.switches.mobileDiscussionAds) {
document.addEventListener('comments-state-change', () => {
void removeMobileCommentsExpandedAds();
});

document.addEventListener('comments-loaded', () => {
void handleCommentsExpandedMobileEvent();
});
}

return Promise.resolve();
};
3 changes: 2 additions & 1 deletion src/lib/header-bidding/prebid-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export type HeaderBiddingSlotName =
export type HeaderBiddingSizeKey =
| HeaderBiddingSlotName
| 'inline'
| 'fronts-banner';
| 'fronts-banner'
| 'comments-expanded';

export type HeaderBiddingSlot = {
key: HeaderBiddingSizeKey;
Expand Down
7 changes: 7 additions & 0 deletions src/lib/header-bidding/slot-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const getHeaderBiddingKey = (
return 'fronts-banner';
}

if (name?.includes('comments-expanded')) {
return 'comments-expanded';
}

return undefined;
};

Expand Down Expand Up @@ -207,6 +211,9 @@ const getSlots = (): HeaderBiddingSizeMapping => {
tablet: isInUk() ? [adSizes.mpu] : [],
desktop: isInUk() ? [adSizes.mpu] : [],
},
'comments-expanded': {
mobile: [adSizes.mpu],
},
};
};

Expand Down

0 comments on commit d285016

Please sign in to comment.