@guardian/commercial-core 0.0.0-beta-20251113115216 → 0.0.0-beta-20260121172637
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/dist/cjs/email-hash.d.ts +5 -1
- package/dist/cjs/email-hash.js +27 -6
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/targeting/build-page-targeting.d.ts +14 -2
- package/dist/cjs/targeting/build-page-targeting.js +2 -1
- package/dist/cjs/targeting/session.d.ts +11 -1
- package/dist/cjs/targeting/session.js +5 -1
- package/dist/cjs/targeting/teads-eligibility.js +3 -1
- package/dist/cjs/types.d.ts +2 -1
- package/dist/cjs/types.js +1 -1
- package/dist/esm/email-hash.d.ts +5 -1
- package/dist/esm/email-hash.js +26 -5
- package/dist/esm/global.js +0 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/targeting/build-page-targeting.d.ts +14 -2
- package/dist/esm/targeting/build-page-targeting.js +2 -1
- package/dist/esm/targeting/session.d.ts +11 -1
- package/dist/esm/targeting/session.js +5 -1
- package/dist/esm/targeting/teads-eligibility.js +3 -1
- package/dist/esm/targeting/types.js +0 -1
- package/dist/esm/types.d.ts +2 -1
- package/dist/esm/types.js +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -22,8 +22,16 @@ pnpm build
|
|
|
22
22
|
|
|
23
23
|
This will build the package into the `dist` directory, which is what is published to npm.
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
### Testing
|
|
26
|
+
|
|
27
|
+
To run the unit tests:
|
|
28
|
+
|
|
29
|
+
`pnpm test`
|
|
30
|
+
|
|
31
|
+
This might fail if the base test coverage hasn't been met. This is set in jest.config.js. Ensure you add sufficient tests to meet the threshold if you can. If this is not possible for whatever reason, you can decrease the set thresholds but this should be considered a last resort
|
|
26
32
|
|
|
33
|
+
|
|
34
|
+
#### Beta Releases
|
|
27
35
|
You can add the [beta] @guardian/commercial-core label to your pull request, this will release a beta version of the bundle to NPM, the exact version will be commented on your PR.
|
|
28
36
|
|
|
29
37
|
In order to do this, run `pnpm changeset`. This will create a new changeset file in the .changeset directory. Commit this file with your PR.
|
|
@@ -31,7 +39,6 @@ In order to do this, run `pnpm changeset`. This will create a new changeset file
|
|
|
31
39
|
Note: Once the beta version is released, the label will be removed from the PR, so you will need to add it again if you want to release subsequent new versions.
|
|
32
40
|
|
|
33
41
|
## Releasing to NPM
|
|
34
|
-
|
|
35
42
|
This repository uses changesets for version management.
|
|
36
43
|
|
|
37
44
|
To release a new version with your changes, run:
|
package/dist/cjs/email-hash.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
type HashClient = 'id5' | 'uid2' | 'euid';
|
|
2
|
+
type Email = `${string}@${string}`;
|
|
3
|
+
declare function normaliseEmail(email: string): Email;
|
|
4
|
+
declare function hashEmailForClient(email: string, client: HashClient): Promise<string>;
|
|
5
|
+
export { hashEmailForClient, normaliseEmail };
|
package/dist/cjs/email-hash.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
3
|
+
exports.hashEmailForClient = hashEmailForClient;
|
|
4
|
+
exports.normaliseEmail = normaliseEmail;
|
|
5
|
+
function toHex(hashBuffer) {
|
|
7
6
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
8
7
|
const hashHex = hashArray
|
|
9
8
|
.map((bytes) => bytes.toString(16).padStart(2, '0'))
|
|
10
9
|
.join('');
|
|
11
10
|
return hashHex;
|
|
12
11
|
}
|
|
13
|
-
function
|
|
12
|
+
function toBase64(hashBuffer) {
|
|
13
|
+
const hashBytes = new Uint8Array(hashBuffer);
|
|
14
|
+
const base64Hash = btoa(String.fromCharCode(...hashBytes));
|
|
15
|
+
return base64Hash;
|
|
16
|
+
}
|
|
17
|
+
function normaliseEmail(email) {
|
|
14
18
|
const normalisedEmail = email.trim().toLowerCase();
|
|
15
|
-
|
|
19
|
+
const [name, domain] = normalisedEmail.split('@');
|
|
20
|
+
if (domain !== 'gmail.com') {
|
|
21
|
+
return `${name}@${domain}`;
|
|
22
|
+
}
|
|
23
|
+
const strippedLocal = name?.replaceAll('.', '');
|
|
24
|
+
return `${strippedLocal}@${domain}`;
|
|
25
|
+
}
|
|
26
|
+
async function hashEmailForClient(email, client) {
|
|
27
|
+
const normalisedEmail = normaliseEmail(email);
|
|
28
|
+
const utf8 = new TextEncoder().encode(normalisedEmail);
|
|
29
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
30
|
+
switch (client) {
|
|
31
|
+
case 'id5':
|
|
32
|
+
return toHex(hashBuffer);
|
|
33
|
+
case 'uid2':
|
|
34
|
+
case 'euid':
|
|
35
|
+
return toBase64(hashBuffer);
|
|
36
|
+
}
|
|
16
37
|
}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { postMessage } from './messenger/post-message.js';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima.js';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive.js';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility.js';
|
|
11
|
-
export {
|
|
11
|
+
export { hashEmailForClient } from './email-hash.js';
|
|
12
12
|
export type { AdSize, SizeMapping, SlotName } from './ad-sizes.js';
|
|
13
13
|
export type { PageTargeting } from './targeting/build-page-targeting.js';
|
|
14
14
|
export type { AdsConfigDisabled, AdsConfigUSNATorAus, AdsConfigTCFV2, } from './types.js';
|
package/dist/cjs/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.hashEmailForClient = exports.isEligibleForTeads = exports.getPermutivePFPSegments = exports.buildImaAdTagUrl = exports.buildPageTargeting = exports.initCommercialMetrics = exports.bypassCommercialMetricsSampling = exports.constants = exports.adSizes = exports.EventTimer = exports.isAdBlockInUse = void 0;
|
|
37
37
|
var detect_ad_blocker_1 = require("./detect-ad-blocker.js");
|
|
38
38
|
Object.defineProperty(exports, "isAdBlockInUse", { enumerable: true, get: function () { return detect_ad_blocker_1.isAdBlockInUse; } });
|
|
39
39
|
var event_timer_1 = require("./event-timer.js");
|
|
@@ -55,4 +55,4 @@ Object.defineProperty(exports, "getPermutivePFPSegments", { enumerable: true, ge
|
|
|
55
55
|
var teads_eligibility_1 = require("./targeting/teads-eligibility.js");
|
|
56
56
|
Object.defineProperty(exports, "isEligibleForTeads", { enumerable: true, get: function () { return teads_eligibility_1.isEligibleForTeads; } });
|
|
57
57
|
var email_hash_1 = require("./email-hash.js");
|
|
58
|
-
Object.defineProperty(exports, "
|
|
58
|
+
Object.defineProperty(exports, "hashEmailForClient", { enumerable: true, get: function () { return email_hash_1.hashEmailForClient; } });
|
|
@@ -30,6 +30,7 @@ type PageTargeting = PartialWithNulls<{
|
|
|
30
30
|
s: string;
|
|
31
31
|
sens: TrueOrFalse;
|
|
32
32
|
si: TrueOrFalse;
|
|
33
|
+
idp: string[];
|
|
33
34
|
skinsize: 'l' | 's';
|
|
34
35
|
urlkw: string[];
|
|
35
36
|
vl: string;
|
|
@@ -37,13 +38,24 @@ type PageTargeting = PartialWithNulls<{
|
|
|
37
38
|
[_: string]: string | string[];
|
|
38
39
|
} & SharedTargeting>;
|
|
39
40
|
declare const filterValues: (pageTargets: Record<string, unknown>) => Record<string, string | string[]>;
|
|
41
|
+
type UserId = {
|
|
42
|
+
name: string;
|
|
43
|
+
params?: Record<string, string | number>;
|
|
44
|
+
storage?: {
|
|
45
|
+
type: 'cookie' | 'html5';
|
|
46
|
+
name: string;
|
|
47
|
+
expires: number;
|
|
48
|
+
refreshInSeconds?: number;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
40
51
|
type BuildPageTargetingParams = {
|
|
41
52
|
adFree: boolean;
|
|
42
53
|
clientSideParticipations: Participations;
|
|
43
54
|
consentState: ConsentState;
|
|
44
55
|
isSignedIn?: boolean;
|
|
45
56
|
youtube?: boolean;
|
|
57
|
+
idProviders?: UserId[];
|
|
46
58
|
};
|
|
47
|
-
declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, isSignedIn, youtube, }: BuildPageTargetingParams) => Record<string, string | string[]>;
|
|
59
|
+
declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, isSignedIn, youtube, idProviders, }: BuildPageTargetingParams) => Record<string, string | string[]>;
|
|
48
60
|
export { buildPageTargeting, filterValues, getLocalHour };
|
|
49
|
-
export type { PageTargeting };
|
|
61
|
+
export type { UserId, PageTargeting };
|
|
@@ -49,7 +49,7 @@ const isFirstVisit = (referrer) => {
|
|
|
49
49
|
}
|
|
50
50
|
return !referrerMatchesHost(referrer);
|
|
51
51
|
};
|
|
52
|
-
const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, }) => {
|
|
52
|
+
const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, idProviders = [], }) => {
|
|
53
53
|
const { page, isDotcomRendering } = window.guardian.config;
|
|
54
54
|
const adFreeTargeting = adFree ? { af: 't' } : {};
|
|
55
55
|
const sharedAdTargeting = page.sharedAdTargeting
|
|
@@ -80,6 +80,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, is
|
|
|
80
80
|
betaAbTestParticipations: window.guardian.modules.abTests?.getParticipations() ?? {},
|
|
81
81
|
},
|
|
82
82
|
referrer,
|
|
83
|
+
idProviders,
|
|
83
84
|
});
|
|
84
85
|
const getViewport = () => {
|
|
85
86
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Participations } from '@guardian/ab-core';
|
|
2
2
|
import type { CountryCode } from '@guardian/libs';
|
|
3
|
+
import type { UserId } from '../targeting/build-page-targeting.js';
|
|
3
4
|
import type { False, True } from './types.js';
|
|
4
5
|
declare const referrers: readonly [{
|
|
5
6
|
readonly id: "facebook";
|
|
@@ -97,6 +98,14 @@ type SessionTargeting = {
|
|
|
97
98
|
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=215727
|
|
98
99
|
*/
|
|
99
100
|
si: True | False;
|
|
101
|
+
/**
|
|
102
|
+
* **I**d **P**roviders – [see on Ad Manager][gam]
|
|
103
|
+
*
|
|
104
|
+
* Denote which id providers have been integrated.
|
|
105
|
+
*
|
|
106
|
+
* [gam]: To be added
|
|
107
|
+
*/
|
|
108
|
+
idp: string[] | null;
|
|
100
109
|
};
|
|
101
110
|
type AllParticipations = {
|
|
102
111
|
clientSideParticipations: Participations;
|
|
@@ -119,7 +128,8 @@ type Session = {
|
|
|
119
128
|
pageViewId: SessionTargeting['pv'];
|
|
120
129
|
participations: AllParticipations;
|
|
121
130
|
referrer: string;
|
|
131
|
+
idProviders: UserId[];
|
|
122
132
|
};
|
|
123
|
-
declare const getSessionTargeting: ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, }: Session) => SessionTargeting;
|
|
133
|
+
declare const getSessionTargeting: ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, idProviders, }: Session) => SessionTargeting;
|
|
124
134
|
export type { SessionTargeting, AllParticipations };
|
|
125
135
|
export { getSessionTargeting, experimentsTargeting };
|
|
@@ -63,7 +63,10 @@ const experimentsTargeting = ({ clientSideParticipations, serverSideParticipatio
|
|
|
63
63
|
return [...clientSideExperiment, ...serverSideExperiments, ...betaAbTests];
|
|
64
64
|
};
|
|
65
65
|
exports.experimentsTargeting = experimentsTargeting;
|
|
66
|
-
const
|
|
66
|
+
const getIdProviders = (userIds) => {
|
|
67
|
+
return userIds.map((id) => id.name);
|
|
68
|
+
};
|
|
69
|
+
const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, idProviders, }) => ({
|
|
67
70
|
ab: experimentsTargeting(participations),
|
|
68
71
|
at: adTest,
|
|
69
72
|
cc: countryCode,
|
|
@@ -71,5 +74,6 @@ const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageV
|
|
|
71
74
|
pv: pageViewId,
|
|
72
75
|
ref: getReferrer(referrer),
|
|
73
76
|
si: isSignedIn ? 't' : 'f',
|
|
77
|
+
idp: getIdProviders(idProviders),
|
|
74
78
|
});
|
|
75
79
|
exports.getSessionTargeting = getSessionTargeting;
|
|
@@ -5,7 +5,9 @@ const allowedContentTypes = ['Article', 'LiveBlog'];
|
|
|
5
5
|
const isEligibleForTeads = (slotId) => {
|
|
6
6
|
const { contentType, isSensitive } = window.guardian.config.page;
|
|
7
7
|
// This IAS value is returned when a page is thought to contain content which is not brand safe
|
|
8
|
-
const iasKw =
|
|
8
|
+
const iasKw =
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- the googletag.getConfig function may not exist if googletag has been shimmed by an adblocker
|
|
10
|
+
window.googletag.getConfig?.('targeting').targeting?.['ias-kw'];
|
|
9
11
|
const iasKwArray = Array.isArray(iasKw) ? iasKw : iasKw ? [iasKw] : [];
|
|
10
12
|
const isBrandSafe = !iasKwArray.includes('IAS_16425_KW');
|
|
11
13
|
if (slotId === 'dfp-ad--inline1' &&
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EventPayload } from '@guardian/ophan-tracker-js';
|
|
2
2
|
import type { AdSize, SizeMapping } from './ad-sizes.js';
|
|
3
3
|
import type { PageTargeting } from './targeting/build-page-targeting.js';
|
|
4
|
-
import '
|
|
4
|
+
import '@types/google-publisher-tag';
|
|
5
5
|
type HeaderBiddingSize = AdSize;
|
|
6
6
|
interface Advert {
|
|
7
7
|
id: string;
|
|
@@ -326,6 +326,7 @@ type ApstagInitConfig = {
|
|
|
326
326
|
adServer?: string;
|
|
327
327
|
bidTimeout?: number;
|
|
328
328
|
blockedBidders?: string[];
|
|
329
|
+
useSafeFrames?: boolean;
|
|
329
330
|
};
|
|
330
331
|
interface A9AdUnitInterface {
|
|
331
332
|
slotID: string;
|
package/dist/cjs/types.js
CHANGED
package/dist/esm/email-hash.d.ts
CHANGED
|
@@ -1 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
type HashClient = 'id5' | 'uid2' | 'euid';
|
|
2
|
+
type Email = `${string}@${string}`;
|
|
3
|
+
declare function normaliseEmail(email: string): Email;
|
|
4
|
+
declare function hashEmailForClient(email: string, client: HashClient): Promise<string>;
|
|
5
|
+
export { hashEmailForClient, normaliseEmail };
|
package/dist/esm/email-hash.js
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
const utf8 = new TextEncoder().encode(string);
|
|
3
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
1
|
+
function toHex(hashBuffer) {
|
|
4
2
|
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
5
3
|
const hashHex = hashArray
|
|
6
4
|
.map((bytes) => bytes.toString(16).padStart(2, '0'))
|
|
7
5
|
.join('');
|
|
8
6
|
return hashHex;
|
|
9
7
|
}
|
|
10
|
-
|
|
8
|
+
function toBase64(hashBuffer) {
|
|
9
|
+
const hashBytes = new Uint8Array(hashBuffer);
|
|
10
|
+
const base64Hash = btoa(String.fromCharCode(...hashBytes));
|
|
11
|
+
return base64Hash;
|
|
12
|
+
}
|
|
13
|
+
function normaliseEmail(email) {
|
|
11
14
|
const normalisedEmail = email.trim().toLowerCase();
|
|
12
|
-
|
|
15
|
+
const [name, domain] = normalisedEmail.split('@');
|
|
16
|
+
if (domain !== 'gmail.com') {
|
|
17
|
+
return `${name}@${domain}`;
|
|
18
|
+
}
|
|
19
|
+
const strippedLocal = name?.replaceAll('.', '');
|
|
20
|
+
return `${strippedLocal}@${domain}`;
|
|
21
|
+
}
|
|
22
|
+
async function hashEmailForClient(email, client) {
|
|
23
|
+
const normalisedEmail = normaliseEmail(email);
|
|
24
|
+
const utf8 = new TextEncoder().encode(normalisedEmail);
|
|
25
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
26
|
+
switch (client) {
|
|
27
|
+
case 'id5':
|
|
28
|
+
return toHex(hashBuffer);
|
|
29
|
+
case 'uid2':
|
|
30
|
+
case 'euid':
|
|
31
|
+
return toBase64(hashBuffer);
|
|
32
|
+
}
|
|
13
33
|
}
|
|
34
|
+
export { hashEmailForClient, normaliseEmail };
|
package/dist/esm/global.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { postMessage } from './messenger/post-message.js';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima.js';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive.js';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility.js';
|
|
11
|
-
export {
|
|
11
|
+
export { hashEmailForClient } from './email-hash.js';
|
|
12
12
|
export type { AdSize, SizeMapping, SlotName } from './ad-sizes.js';
|
|
13
13
|
export type { PageTargeting } from './targeting/build-page-targeting.js';
|
|
14
14
|
export type { AdsConfigDisabled, AdsConfigUSNATorAus, AdsConfigTCFV2, } from './types.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -8,4 +8,4 @@ export { postMessage } from './messenger/post-message.js';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima.js';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive.js';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility.js';
|
|
11
|
-
export {
|
|
11
|
+
export { hashEmailForClient } from './email-hash.js';
|
|
@@ -30,6 +30,7 @@ type PageTargeting = PartialWithNulls<{
|
|
|
30
30
|
s: string;
|
|
31
31
|
sens: TrueOrFalse;
|
|
32
32
|
si: TrueOrFalse;
|
|
33
|
+
idp: string[];
|
|
33
34
|
skinsize: 'l' | 's';
|
|
34
35
|
urlkw: string[];
|
|
35
36
|
vl: string;
|
|
@@ -37,13 +38,24 @@ type PageTargeting = PartialWithNulls<{
|
|
|
37
38
|
[_: string]: string | string[];
|
|
38
39
|
} & SharedTargeting>;
|
|
39
40
|
declare const filterValues: (pageTargets: Record<string, unknown>) => Record<string, string | string[]>;
|
|
41
|
+
type UserId = {
|
|
42
|
+
name: string;
|
|
43
|
+
params?: Record<string, string | number>;
|
|
44
|
+
storage?: {
|
|
45
|
+
type: 'cookie' | 'html5';
|
|
46
|
+
name: string;
|
|
47
|
+
expires: number;
|
|
48
|
+
refreshInSeconds?: number;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
40
51
|
type BuildPageTargetingParams = {
|
|
41
52
|
adFree: boolean;
|
|
42
53
|
clientSideParticipations: Participations;
|
|
43
54
|
consentState: ConsentState;
|
|
44
55
|
isSignedIn?: boolean;
|
|
45
56
|
youtube?: boolean;
|
|
57
|
+
idProviders?: UserId[];
|
|
46
58
|
};
|
|
47
|
-
declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, isSignedIn, youtube, }: BuildPageTargetingParams) => Record<string, string | string[]>;
|
|
59
|
+
declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, isSignedIn, youtube, idProviders, }: BuildPageTargetingParams) => Record<string, string | string[]>;
|
|
48
60
|
export { buildPageTargeting, filterValues, getLocalHour };
|
|
49
|
-
export type { PageTargeting };
|
|
61
|
+
export type { UserId, PageTargeting };
|
|
@@ -44,7 +44,7 @@ const isFirstVisit = (referrer) => {
|
|
|
44
44
|
}
|
|
45
45
|
return !referrerMatchesHost(referrer);
|
|
46
46
|
};
|
|
47
|
-
const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, }) => {
|
|
47
|
+
const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, idProviders = [], }) => {
|
|
48
48
|
const { page, isDotcomRendering } = window.guardian.config;
|
|
49
49
|
const adFreeTargeting = adFree ? { af: 't' } : {};
|
|
50
50
|
const sharedAdTargeting = page.sharedAdTargeting
|
|
@@ -75,6 +75,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, is
|
|
|
75
75
|
betaAbTestParticipations: window.guardian.modules.abTests?.getParticipations() ?? {},
|
|
76
76
|
},
|
|
77
77
|
referrer,
|
|
78
|
+
idProviders,
|
|
78
79
|
});
|
|
79
80
|
const getViewport = () => {
|
|
80
81
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Participations } from '@guardian/ab-core';
|
|
2
2
|
import type { CountryCode } from '@guardian/libs';
|
|
3
|
+
import type { UserId } from '../targeting/build-page-targeting.js';
|
|
3
4
|
import type { False, True } from './types.js';
|
|
4
5
|
declare const referrers: readonly [{
|
|
5
6
|
readonly id: "facebook";
|
|
@@ -97,6 +98,14 @@ type SessionTargeting = {
|
|
|
97
98
|
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=215727
|
|
98
99
|
*/
|
|
99
100
|
si: True | False;
|
|
101
|
+
/**
|
|
102
|
+
* **I**d **P**roviders – [see on Ad Manager][gam]
|
|
103
|
+
*
|
|
104
|
+
* Denote which id providers have been integrated.
|
|
105
|
+
*
|
|
106
|
+
* [gam]: To be added
|
|
107
|
+
*/
|
|
108
|
+
idp: string[] | null;
|
|
100
109
|
};
|
|
101
110
|
type AllParticipations = {
|
|
102
111
|
clientSideParticipations: Participations;
|
|
@@ -119,7 +128,8 @@ type Session = {
|
|
|
119
128
|
pageViewId: SessionTargeting['pv'];
|
|
120
129
|
participations: AllParticipations;
|
|
121
130
|
referrer: string;
|
|
131
|
+
idProviders: UserId[];
|
|
122
132
|
};
|
|
123
|
-
declare const getSessionTargeting: ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, }: Session) => SessionTargeting;
|
|
133
|
+
declare const getSessionTargeting: ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, idProviders, }: Session) => SessionTargeting;
|
|
124
134
|
export type { SessionTargeting, AllParticipations };
|
|
125
135
|
export { getSessionTargeting, experimentsTargeting };
|
|
@@ -59,7 +59,10 @@ const experimentsTargeting = ({ clientSideParticipations, serverSideParticipatio
|
|
|
59
59
|
}
|
|
60
60
|
return [...clientSideExperiment, ...serverSideExperiments, ...betaAbTests];
|
|
61
61
|
};
|
|
62
|
-
const
|
|
62
|
+
const getIdProviders = (userIds) => {
|
|
63
|
+
return userIds.map((id) => id.name);
|
|
64
|
+
};
|
|
65
|
+
const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, idProviders, }) => ({
|
|
63
66
|
ab: experimentsTargeting(participations),
|
|
64
67
|
at: adTest,
|
|
65
68
|
cc: countryCode,
|
|
@@ -67,5 +70,6 @@ const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageV
|
|
|
67
70
|
pv: pageViewId,
|
|
68
71
|
ref: getReferrer(referrer),
|
|
69
72
|
si: isSignedIn ? 't' : 'f',
|
|
73
|
+
idp: getIdProviders(idProviders),
|
|
70
74
|
});
|
|
71
75
|
export { getSessionTargeting, experimentsTargeting };
|
|
@@ -2,7 +2,9 @@ const allowedContentTypes = ['Article', 'LiveBlog'];
|
|
|
2
2
|
const isEligibleForTeads = (slotId) => {
|
|
3
3
|
const { contentType, isSensitive } = window.guardian.config.page;
|
|
4
4
|
// This IAS value is returned when a page is thought to contain content which is not brand safe
|
|
5
|
-
const iasKw =
|
|
5
|
+
const iasKw =
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- the googletag.getConfig function may not exist if googletag has been shimmed by an adblocker
|
|
7
|
+
window.googletag.getConfig?.('targeting').targeting?.['ias-kw'];
|
|
6
8
|
const iasKwArray = Array.isArray(iasKw) ? iasKw : iasKw ? [iasKw] : [];
|
|
7
9
|
const isBrandSafe = !iasKwArray.includes('IAS_16425_KW');
|
|
8
10
|
if (slotId === 'dfp-ad--inline1' &&
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EventPayload } from '@guardian/ophan-tracker-js';
|
|
2
2
|
import type { AdSize, SizeMapping } from './ad-sizes.js';
|
|
3
3
|
import type { PageTargeting } from './targeting/build-page-targeting.js';
|
|
4
|
-
import '
|
|
4
|
+
import '@types/google-publisher-tag';
|
|
5
5
|
type HeaderBiddingSize = AdSize;
|
|
6
6
|
interface Advert {
|
|
7
7
|
id: string;
|
|
@@ -326,6 +326,7 @@ type ApstagInitConfig = {
|
|
|
326
326
|
adServer?: string;
|
|
327
327
|
bidTimeout?: number;
|
|
328
328
|
blockedBidders?: string[];
|
|
329
|
+
useSafeFrames?: boolean;
|
|
329
330
|
};
|
|
330
331
|
interface A9AdUnitInterface {
|
|
331
332
|
slotID: string;
|
package/dist/esm/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guardian/commercial-core",
|
|
3
|
-
"version": "0.0.0-beta-
|
|
3
|
+
"version": "0.0.0-beta-20260121172637",
|
|
4
4
|
"description": "Guardian advertising business logic",
|
|
5
5
|
"homepage": "https://github.com/guardian/commercial#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -32,22 +32,22 @@
|
|
|
32
32
|
"./package.json": "./package.json"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@guardian/ab-core": "^
|
|
36
|
-
"@guardian/libs": "^
|
|
35
|
+
"@guardian/ab-core": "^9.0.0",
|
|
36
|
+
"@guardian/libs": "^27.0.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@guardian/ab-core": "
|
|
40
|
-
"@guardian/libs": "
|
|
39
|
+
"@guardian/ab-core": "9.0.0",
|
|
40
|
+
"@guardian/libs": "27.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@guardian/ophan-tracker-js": "2.6.
|
|
44
|
-
"@types/google-publisher-tag": "~1.
|
|
43
|
+
"@guardian/ophan-tracker-js": "2.6.3",
|
|
44
|
+
"@types/google-publisher-tag": "~1.20251117.0",
|
|
45
45
|
"@types/jest": "30.0.0",
|
|
46
|
-
"@types/node": "24.
|
|
46
|
+
"@types/node": "24.10.1",
|
|
47
47
|
"jest": "^30.2.0",
|
|
48
48
|
"jest-environment-jsdom": "^30.2.0",
|
|
49
49
|
"jest-environment-jsdom-global": "~4.0.0",
|
|
50
|
-
"ts-jest": "^29.4.
|
|
50
|
+
"ts-jest": "^29.4.6",
|
|
51
51
|
"tsc-alias": "1.8.16",
|
|
52
52
|
"type-fest": "^4.41.0",
|
|
53
53
|
"typescript": "5.9.3"
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"prettier:check": "prettier . --check --cache",
|
|
65
65
|
"prettier:fix": "prettier . --write --cache",
|
|
66
66
|
"test": "jest",
|
|
67
|
+
"test-cov": "jest --coverage",
|
|
67
68
|
"tsc": "tsc --noEmit"
|
|
68
69
|
}
|
|
69
70
|
}
|