Skip to content

Commit

Permalink
Add The Trade Desk to prebid (#1773)
Browse files Browse the repository at this point in the history
Co-authored-by: Emma Imber <[email protected]>
  • Loading branch information
Jakeii and emma-imber authored Jan 31, 2025
1 parent 0b8e15f commit ef12548
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-chairs-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@guardian/commercial': minor
---

Add The Trade Desk behind 0% test
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"webpack-merge": "^6.0.1"
},
"dependencies": {
"@guardian/prebid.js": "8.52.0-12",
"@guardian/prebid.js": "8.52.0-13",
"fastdom": "^1.0.12",
"lodash-es": "^4.17.21",
"process": "^0.11.10",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/experiments/ab-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ABTest } from '@guardian/ab-core';
import { mpuWhenNoEpic } from './tests/mpu-when-no-epic';
import { optOutFrequencyCap } from './tests/opt-out-frequency-cap';
import { prebidKeywords } from './tests/prebid-keywords';
import { ttdPrebidBidder } from './tests/ttd-prebid';

/**
* You only need to add tests to this file if the code you are testing is here in
Expand All @@ -13,4 +14,5 @@ export const concurrentTests: ABTest[] = [
mpuWhenNoEpic,
optOutFrequencyCap,
prebidKeywords,
ttdPrebidBidder,
];
28 changes: 28 additions & 0 deletions src/experiments/tests/ttd-prebid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { ABTest } from '@guardian/ab-core';

export const ttdPrebidBidder: ABTest = {
id: 'TheTradeDesk',
author: '@commercial-dev',
start: '2025-01-30',
expiry: '2025-02-28',
audience: 0 / 100,
audienceOffset: 0 / 100,
audienceCriteria: '',
successMeasure: 'Verify The Trade Desk bidder is added to Prebid.js',
description: 'Verify The Trade Desk bidder is added to Prebid.js',
variants: [
{
id: 'control',
test: (): void => {
/* no-op */
},
},
{
id: 'variant',
test: (): void => {
/* no-op */
},
},
],
canRun: () => true,
};
12 changes: 10 additions & 2 deletions src/lib/header-bidding/prebid-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ export type PrebidMagniteParams = {
keywords: string[];
};

export type PrebidTheTradeDeskParams = {
supplySourceId: number;
publisherId: number;
placementId: string;
};

export type BidderCode =
| 'adyoulike'
| 'and'
Expand All @@ -127,7 +133,8 @@ export type BidderCode =
| 'pubmatic'
| 'triplelift'
| 'trustx'
| 'xhb';
| 'xhb'
| 'ttd';

export type PrebidParams =
| PrebidAdYouLikeParams
Expand All @@ -142,7 +149,8 @@ export type PrebidParams =
| PrebidPubmaticParams
| PrebidTripleLiftParams
| PrebidTrustXParams
| PrebidXaxisParams;
| PrebidXaxisParams
| PrebidTheTradeDeskParams;

export type PrebidBidder = {
name: BidderCode;
Expand Down
13 changes: 13 additions & 0 deletions src/lib/header-bidding/prebid/bid-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const getBidders = () =>
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
).map((bid) => bid.bidder);

const {
Expand Down Expand Up @@ -289,6 +290,7 @@ describe('bids', () => {
'dfp-right',
[createAdSize(300, 600), createAdSize(300, 250)],
mockPageTargeting,
'gpid',
).map((bid) => bid.bidder);
expect(rightSlotBidders()).toEqual(['ix', 'ix', 'criteo', 'adyoulike']);
});
Expand Down Expand Up @@ -332,6 +334,7 @@ describe('bids', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[3];
expect(openXBid?.params).toEqual({
customParams: 'someAppNexusTargetingObject',
Expand All @@ -347,6 +350,7 @@ describe('bids', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[3];
expect(openXBid?.params).toEqual({
customParams: 'someAppNexusTargetingObject',
Expand All @@ -362,6 +366,7 @@ describe('bids', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[3];
expect(openXBid?.params).toEqual({
customParams: 'someAppNexusTargetingObject',
Expand All @@ -377,6 +382,7 @@ describe('bids', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[3];
expect(openXBid?.params).toEqual({
customParams: 'someAppNexusTargetingObject',
Expand All @@ -392,6 +398,7 @@ describe('bids', () => {
'dfp-ad--mobile-sticky',
[createAdSize(320, 50)],
mockPageTargeting,
'gpid',
)[3];
expect(openXBid?.params).toEqual({
customParams: 'someAppNexusTargetingObject',
Expand Down Expand Up @@ -431,6 +438,7 @@ describe('triplelift adapter', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_topbanner_728x90_prebid',
Expand All @@ -447,6 +455,7 @@ describe('triplelift adapter', () => {
'dfp-ad--top-above-nav',
[createAdSize(728, 90)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_topbanner_728x90_prebid_AU',
Expand All @@ -464,6 +473,7 @@ describe('triplelift adapter', () => {
'dfp-ad--inline1',
[createAdSize(300, 250)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_sectionfront_300x250_prebid',
Expand All @@ -481,6 +491,7 @@ describe('triplelift adapter', () => {
'dfp-ad--inline1',
[createAdSize(300, 250)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_sectionfront_300x250_prebid_AU',
Expand All @@ -498,6 +509,7 @@ describe('triplelift adapter', () => {
'dfp-ad--top-above-nav',
[createAdSize(320, 50)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_320x50_HDX',
Expand All @@ -515,6 +527,7 @@ describe('triplelift adapter', () => {
'dfp-ad--top-above-nav',
[createAdSize(320, 50)],
mockPageTargeting,
'gpid',
)[2]?.params;
expect(tripleLiftBids).toEqual({
inventoryCode: 'theguardian_320x50_HDX_AU',
Expand Down
24 changes: 20 additions & 4 deletions src/lib/header-bidding/prebid/bid-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
shouldIncludeKargo,
shouldIncludeMagnite,
shouldIncludeOpenx,
shouldIncludeTheTradeDesk,
shouldIncludeTripleLift,
shouldIncludeTrustX,
shouldIncludeXaxis,
Expand Down Expand Up @@ -629,6 +630,16 @@ const magniteBidder: PrebidBidder = {
}),
};

const theTradeDeskBidder = (gpid: string): PrebidBidder => ({
name: 'ttd',
switchName: 'prebidTheTradeDesk',
bidParams: () => ({
supplySourceId: 'theguardian',
publisherId: '1',
placementId: gpid,
}),
});

// There's an IX bidder for every size that the slot can take
const indexExchangeBidders = (
slotSizes: HeaderBiddingSize[],
Expand Down Expand Up @@ -657,6 +668,7 @@ const biddersSwitchedOn = (allBidders: PrebidBidder[]): PrebidBidder[] => {
const currentBidders = (
slotSizes: HeaderBiddingSize[],
pageTargeting: PageTargeting,
gpid: string,
): PrebidBidder[] => {
const biddersToCheck: Array<[boolean, PrebidBidder]> = [
[true, criteoBidder(slotSizes)],
Expand All @@ -672,6 +684,7 @@ const currentBidders = (
[shouldIncludeOpenx(), openxClientSideBidder(pageTargeting)],
[shouldIncludeKargo(), kargoBidder],
[shouldIncludeMagnite(), magniteBidder],
[shouldIncludeTheTradeDesk(), theTradeDeskBidder(gpid)],
];

const otherBidders = biddersToCheck
Expand All @@ -688,11 +701,14 @@ export const bids = (
slotId: string,
slotSizes: HeaderBiddingSize[],
pageTargeting: PageTargeting,
gpid: string,
): PrebidBid[] =>
currentBidders(slotSizes, pageTargeting).map((bidder: PrebidBidder) => ({
bidder: bidder.name,
params: bidder.bidParams(slotId, slotSizes),
}));
currentBidders(slotSizes, pageTargeting, gpid).map(
(bidder: PrebidBidder) => ({
bidder: bidder.name,
params: bidder.bidParams(slotId, slotSizes),
}),
);

export const _ = {
getIndexSiteIdFromConfig,
Expand Down
3 changes: 2 additions & 1 deletion src/lib/header-bidding/prebid/prebid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ class PrebidAdUnit {
pageTargeting: PageTargeting,
) {
this.code = advert.id;
this.bids = bids(advert.id, slot.sizes, pageTargeting);
this.mediaTypes = { banner: { sizes: slot.sizes } };
this.gpid = this.generateGpid(advert, slot);
this.ortb2Imp = {
Expand All @@ -203,6 +202,8 @@ class PrebidAdUnit {
},
};

this.bids = bids(advert.id, slot.sizes, pageTargeting, this.gpid);

advert.headerBiddingSizes = slot.sizes;
log('commercial', `PrebidAdUnit ${this.code}`, this.bids);
}
Expand Down
5 changes: 5 additions & 0 deletions src/lib/header-bidding/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { isString } from '@guardian/libs';
import { once } from 'lodash-es';
import { isUserInVariant } from '../../experiments/ab';
import { ttdPrebidBidder } from '../../experiments/tests/ttd-prebid';
import { createAdSize } from '../../lib/ad-sizes';
import {
isInAuOrNz,
Expand Down Expand Up @@ -189,6 +191,9 @@ export const shouldIncludeKargo = (): boolean => isInUsa();
export const shouldIncludeMagnite = (): boolean =>
!!window.guardian.config.switches.prebidMagnite;

export const shouldIncludeTheTradeDesk = (): boolean =>
isUserInVariant(ttdPrebidBidder, 'variant');

export const shouldIncludeMobileSticky = once(
(): boolean =>
window.location.hash.includes('#mobile-sticky') ||
Expand Down

0 comments on commit ef12548

Please sign in to comment.