@guardian/commercial-core 0.0.0-beta-20250926083815 → 0.0.0-beta-20251030174934
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/dist/cjs/ad-sizes.d.ts +1 -4
- package/dist/cjs/ad-sizes.js +0 -3
- package/dist/cjs/email-hash.d.ts +1 -0
- package/dist/cjs/email-hash.js +16 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/targeting/build-page-targeting.js +1 -0
- package/dist/cjs/targeting/session.d.ts +6 -1
- package/dist/cjs/targeting/session.js +16 -3
- package/dist/cjs/targeting/teads-eligibility.js +3 -4
- package/dist/cjs/types.d.ts +1 -0
- package/dist/esm/ad-sizes.d.ts +1 -4
- package/dist/esm/ad-sizes.js +0 -3
- package/dist/esm/email-hash.d.ts +1 -0
- package/dist/esm/email-hash.js +13 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/targeting/build-page-targeting.js +1 -0
- package/dist/esm/targeting/session.d.ts +6 -1
- package/dist/esm/targeting/session.js +16 -3
- package/dist/esm/targeting/teads-eligibility.js +3 -4
- package/dist/esm/types.d.ts +1 -0
- package/package.json +13 -12
package/dist/cjs/ad-sizes.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ declare class AdSize extends Array<number> {
|
|
|
28
28
|
get height(): number;
|
|
29
29
|
}
|
|
30
30
|
type SizeKeys = '160x600' | '300x1050' | '300x250' | '300x600' | '728x90' | '970x250' | 'billboard' | 'cascade' | 'empty' | 'fabric' | 'fluid' | 'googleCard' | 'halfPage' | 'leaderboard' | 'merchandising' | 'merchandisingHigh' | 'merchandisingHighAdFeature' | 'mobilesticky' | 'mpu' | 'outOfPage' | 'outstreamDesktop' | 'outstreamGoogleDesktop' | 'outstreamMobile' | 'portrait' | 'portraitInterstitial' | 'pubmaticInterscroller' | 'skyscraper' | 'sponsorLogo';
|
|
31
|
-
type SlotName = 'article-end' | '
|
|
31
|
+
type SlotName = 'article-end' | 'comments-expanded' | 'comments' | 'crossword-banner-mobile' | 'exclusion' | 'external' | 'fronts-banner' | 'inline' | 'liveblog-top' | 'merchandising-high' | 'merchandising' | 'mobile-sticky' | 'football-right' | 'mostpop' | 'right' | 'sponsor-logo' | 'survey' | 'top-above-nav' | 'interactive';
|
|
32
32
|
type SizeMapping = Partial<Record<Breakpoint, readonly AdSize[]>>;
|
|
33
33
|
type SlotSizeMappings = Record<SlotName, SizeMapping>;
|
|
34
34
|
declare const createAdSize: (width: number, height: number) => AdSize;
|
|
@@ -139,9 +139,6 @@ declare const slotSizeMappings: {
|
|
|
139
139
|
readonly survey: {
|
|
140
140
|
readonly desktop: readonly [AdSize];
|
|
141
141
|
};
|
|
142
|
-
readonly carrot: {
|
|
143
|
-
readonly mobile: readonly [AdSize];
|
|
144
|
-
};
|
|
145
142
|
readonly 'mobile-sticky': {
|
|
146
143
|
readonly mobile: readonly [AdSize, AdSize, AdSize];
|
|
147
144
|
};
|
package/dist/cjs/ad-sizes.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hashEmail(email: string): Promise<string>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hashEmail = hashEmail;
|
|
4
|
+
async function sha256(string) {
|
|
5
|
+
const utf8 = new TextEncoder().encode(string);
|
|
6
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
7
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
8
|
+
const hashHex = hashArray
|
|
9
|
+
.map((bytes) => bytes.toString(16).padStart(2, '0'))
|
|
10
|
+
.join('');
|
|
11
|
+
return hashHex;
|
|
12
|
+
}
|
|
13
|
+
function hashEmail(email) {
|
|
14
|
+
const normalisedEmail = email.trim().toLowerCase();
|
|
15
|
+
return sha256(normalisedEmail);
|
|
16
|
+
}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { postMessage } from './messenger/post-message';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility';
|
|
11
|
+
export { hashEmail } from './email-hash';
|
|
11
12
|
export type { AdSize, SizeMapping, SlotName } from './ad-sizes';
|
|
12
13
|
export type { PageTargeting } from './targeting/build-page-targeting';
|
|
13
14
|
export type { AdsConfigDisabled, AdsConfigUSNATorAus, AdsConfigTCFV2, } from './types';
|
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.isEligibleForTeads = exports.getPermutivePFPSegments = exports.buildImaAdTagUrl = exports.buildPageTargeting = exports.initCommercialMetrics = exports.bypassCommercialMetricsSampling = exports.constants = exports.adSizes = exports.EventTimer = exports.isAdBlockInUse = void 0;
|
|
36
|
+
exports.hashEmail = 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");
|
|
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");
|
|
@@ -54,3 +54,5 @@ var permutive_1 = require("./permutive");
|
|
|
54
54
|
Object.defineProperty(exports, "getPermutivePFPSegments", { enumerable: true, get: function () { return permutive_1.getPermutivePFPSegments; } });
|
|
55
55
|
var teads_eligibility_1 = require("./targeting/teads-eligibility");
|
|
56
56
|
Object.defineProperty(exports, "isEligibleForTeads", { enumerable: true, get: function () { return teads_eligibility_1.isEligibleForTeads; } });
|
|
57
|
+
var email_hash_1 = require("./email-hash");
|
|
58
|
+
Object.defineProperty(exports, "hashEmail", { enumerable: true, get: function () { return email_hash_1.hashEmail; } });
|
|
@@ -77,6 +77,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, is
|
|
|
77
77
|
participations: {
|
|
78
78
|
clientSideParticipations,
|
|
79
79
|
serverSideParticipations: window.guardian.config.tests ?? {},
|
|
80
|
+
betaAbTestParticipations: window.guardian.modules.abTests?.getParticipations() ?? {},
|
|
80
81
|
},
|
|
81
82
|
referrer,
|
|
82
83
|
});
|
|
@@ -104,8 +104,13 @@ type AllParticipations = {
|
|
|
104
104
|
[key: `${string}Control`]: 'control';
|
|
105
105
|
[key: `${string}Variant`]: 'variant';
|
|
106
106
|
};
|
|
107
|
+
betaAbTestParticipations: Record<string, string>;
|
|
107
108
|
};
|
|
108
|
-
|
|
109
|
+
/**
|
|
110
|
+
* @todo drop old client/server side participations and rename to just `abTestsParticipations` once
|
|
111
|
+
* all tests have been migrated to the new AB testing platform
|
|
112
|
+
*/
|
|
113
|
+
declare const experimentsTargeting: ({ clientSideParticipations, serverSideParticipations, betaAbTestParticipations, }: AllParticipations) => SessionTargeting["ab"];
|
|
109
114
|
type Session = {
|
|
110
115
|
adTest: SessionTargeting['at'];
|
|
111
116
|
countryCode: CountryCode;
|
|
@@ -28,7 +28,11 @@ const getReferrer = (referrer) => {
|
|
|
28
28
|
const matchedRef = referrers.find((referrerType) => referrer.includes(referrerType.match)) ?? null;
|
|
29
29
|
return matchedRef ? matchedRef.id : null;
|
|
30
30
|
};
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* @todo drop old client/server side participations and rename to just `abTestsParticipations` once
|
|
33
|
+
* all tests have been migrated to the new AB testing platform
|
|
34
|
+
*/
|
|
35
|
+
const experimentsTargeting = ({ clientSideParticipations, serverSideParticipations, betaAbTestParticipations, }) => {
|
|
32
36
|
const testToParams = (testName, variant) => {
|
|
33
37
|
if (variant === 'notintest')
|
|
34
38
|
return null;
|
|
@@ -44,10 +48,19 @@ const experimentsTargeting = ({ clientSideParticipations, serverSideParticipatio
|
|
|
44
48
|
const serverSideExperiments = Object.entries(serverSideParticipations)
|
|
45
49
|
.map((test) => testToParams(...test))
|
|
46
50
|
.filter(libs_1.isString);
|
|
47
|
-
|
|
51
|
+
const betaAbTests = Object.entries(betaAbTestParticipations)
|
|
52
|
+
.map((test) => {
|
|
53
|
+
const [name, variant] = test;
|
|
54
|
+
return testToParams(name, variant);
|
|
55
|
+
})
|
|
56
|
+
.filter(libs_1.isString);
|
|
57
|
+
if (clientSideExperiment.length +
|
|
58
|
+
serverSideExperiments.length +
|
|
59
|
+
betaAbTests.length ===
|
|
60
|
+
0) {
|
|
48
61
|
return null;
|
|
49
62
|
}
|
|
50
|
-
return [...clientSideExperiment, ...serverSideExperiments];
|
|
63
|
+
return [...clientSideExperiment, ...serverSideExperiments, ...betaAbTests];
|
|
51
64
|
};
|
|
52
65
|
exports.experimentsTargeting = experimentsTargeting;
|
|
53
66
|
const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, }) => ({
|
|
@@ -5,10 +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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
.includes('IAS_16425_KW');
|
|
8
|
+
const iasKw = window.googletag.getConfig('targeting').targeting?.['ias-kw'];
|
|
9
|
+
const iasKwArray = Array.isArray(iasKw) ? iasKw : iasKw ? [iasKw] : [];
|
|
10
|
+
const isBrandSafe = !iasKwArray.includes('IAS_16425_KW');
|
|
12
11
|
if (slotId === 'dfp-ad--inline1' &&
|
|
13
12
|
allowedContentTypes.includes(contentType) &&
|
|
14
13
|
!isSensitive &&
|
package/dist/cjs/types.d.ts
CHANGED
package/dist/esm/ad-sizes.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ declare class AdSize extends Array<number> {
|
|
|
28
28
|
get height(): number;
|
|
29
29
|
}
|
|
30
30
|
type SizeKeys = '160x600' | '300x1050' | '300x250' | '300x600' | '728x90' | '970x250' | 'billboard' | 'cascade' | 'empty' | 'fabric' | 'fluid' | 'googleCard' | 'halfPage' | 'leaderboard' | 'merchandising' | 'merchandisingHigh' | 'merchandisingHighAdFeature' | 'mobilesticky' | 'mpu' | 'outOfPage' | 'outstreamDesktop' | 'outstreamGoogleDesktop' | 'outstreamMobile' | 'portrait' | 'portraitInterstitial' | 'pubmaticInterscroller' | 'skyscraper' | 'sponsorLogo';
|
|
31
|
-
type SlotName = 'article-end' | '
|
|
31
|
+
type SlotName = 'article-end' | 'comments-expanded' | 'comments' | 'crossword-banner-mobile' | 'exclusion' | 'external' | 'fronts-banner' | 'inline' | 'liveblog-top' | 'merchandising-high' | 'merchandising' | 'mobile-sticky' | 'football-right' | 'mostpop' | 'right' | 'sponsor-logo' | 'survey' | 'top-above-nav' | 'interactive';
|
|
32
32
|
type SizeMapping = Partial<Record<Breakpoint, readonly AdSize[]>>;
|
|
33
33
|
type SlotSizeMappings = Record<SlotName, SizeMapping>;
|
|
34
34
|
declare const createAdSize: (width: number, height: number) => AdSize;
|
|
@@ -139,9 +139,6 @@ declare const slotSizeMappings: {
|
|
|
139
139
|
readonly survey: {
|
|
140
140
|
readonly desktop: readonly [AdSize];
|
|
141
141
|
};
|
|
142
|
-
readonly carrot: {
|
|
143
|
-
readonly mobile: readonly [AdSize];
|
|
144
|
-
};
|
|
145
142
|
readonly 'mobile-sticky': {
|
|
146
143
|
readonly mobile: readonly [AdSize, AdSize, AdSize];
|
|
147
144
|
};
|
package/dist/esm/ad-sizes.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hashEmail(email: string): Promise<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
async function sha256(string) {
|
|
2
|
+
const utf8 = new TextEncoder().encode(string);
|
|
3
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', utf8);
|
|
4
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
5
|
+
const hashHex = hashArray
|
|
6
|
+
.map((bytes) => bytes.toString(16).padStart(2, '0'))
|
|
7
|
+
.join('');
|
|
8
|
+
return hashHex;
|
|
9
|
+
}
|
|
10
|
+
export function hashEmail(email) {
|
|
11
|
+
const normalisedEmail = email.trim().toLowerCase();
|
|
12
|
+
return sha256(normalisedEmail);
|
|
13
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { postMessage } from './messenger/post-message';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility';
|
|
11
|
+
export { hashEmail } from './email-hash';
|
|
11
12
|
export type { AdSize, SizeMapping, SlotName } from './ad-sizes';
|
|
12
13
|
export type { PageTargeting } from './targeting/build-page-targeting';
|
|
13
14
|
export type { AdsConfigDisabled, AdsConfigUSNATorAus, AdsConfigTCFV2, } from './types';
|
package/dist/esm/index.js
CHANGED
|
@@ -8,3 +8,4 @@ export { postMessage } from './messenger/post-message';
|
|
|
8
8
|
export { buildImaAdTagUrl } from './targeting/youtube-ima';
|
|
9
9
|
export { getPermutivePFPSegments } from './permutive';
|
|
10
10
|
export { isEligibleForTeads } from './targeting/teads-eligibility';
|
|
11
|
+
export { hashEmail } from './email-hash';
|
|
@@ -72,6 +72,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, is
|
|
|
72
72
|
participations: {
|
|
73
73
|
clientSideParticipations,
|
|
74
74
|
serverSideParticipations: window.guardian.config.tests ?? {},
|
|
75
|
+
betaAbTestParticipations: window.guardian.modules.abTests?.getParticipations() ?? {},
|
|
75
76
|
},
|
|
76
77
|
referrer,
|
|
77
78
|
});
|
|
@@ -104,8 +104,13 @@ type AllParticipations = {
|
|
|
104
104
|
[key: `${string}Control`]: 'control';
|
|
105
105
|
[key: `${string}Variant`]: 'variant';
|
|
106
106
|
};
|
|
107
|
+
betaAbTestParticipations: Record<string, string>;
|
|
107
108
|
};
|
|
108
|
-
|
|
109
|
+
/**
|
|
110
|
+
* @todo drop old client/server side participations and rename to just `abTestsParticipations` once
|
|
111
|
+
* all tests have been migrated to the new AB testing platform
|
|
112
|
+
*/
|
|
113
|
+
declare const experimentsTargeting: ({ clientSideParticipations, serverSideParticipations, betaAbTestParticipations, }: AllParticipations) => SessionTargeting["ab"];
|
|
109
114
|
type Session = {
|
|
110
115
|
adTest: SessionTargeting['at'];
|
|
111
116
|
countryCode: CountryCode;
|
|
@@ -25,7 +25,11 @@ const getReferrer = (referrer) => {
|
|
|
25
25
|
const matchedRef = referrers.find((referrerType) => referrer.includes(referrerType.match)) ?? null;
|
|
26
26
|
return matchedRef ? matchedRef.id : null;
|
|
27
27
|
};
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* @todo drop old client/server side participations and rename to just `abTestsParticipations` once
|
|
30
|
+
* all tests have been migrated to the new AB testing platform
|
|
31
|
+
*/
|
|
32
|
+
const experimentsTargeting = ({ clientSideParticipations, serverSideParticipations, betaAbTestParticipations, }) => {
|
|
29
33
|
const testToParams = (testName, variant) => {
|
|
30
34
|
if (variant === 'notintest')
|
|
31
35
|
return null;
|
|
@@ -41,10 +45,19 @@ const experimentsTargeting = ({ clientSideParticipations, serverSideParticipatio
|
|
|
41
45
|
const serverSideExperiments = Object.entries(serverSideParticipations)
|
|
42
46
|
.map((test) => testToParams(...test))
|
|
43
47
|
.filter(isString);
|
|
44
|
-
|
|
48
|
+
const betaAbTests = Object.entries(betaAbTestParticipations)
|
|
49
|
+
.map((test) => {
|
|
50
|
+
const [name, variant] = test;
|
|
51
|
+
return testToParams(name, variant);
|
|
52
|
+
})
|
|
53
|
+
.filter(isString);
|
|
54
|
+
if (clientSideExperiment.length +
|
|
55
|
+
serverSideExperiments.length +
|
|
56
|
+
betaAbTests.length ===
|
|
57
|
+
0) {
|
|
45
58
|
return null;
|
|
46
59
|
}
|
|
47
|
-
return [...clientSideExperiment, ...serverSideExperiments];
|
|
60
|
+
return [...clientSideExperiment, ...serverSideExperiments, ...betaAbTests];
|
|
48
61
|
};
|
|
49
62
|
const getSessionTargeting = ({ adTest, countryCode, localHour, isSignedIn, pageViewId, participations, referrer, }) => ({
|
|
50
63
|
ab: experimentsTargeting(participations),
|
|
@@ -2,10 +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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.includes('IAS_16425_KW');
|
|
5
|
+
const iasKw = window.googletag.getConfig('targeting').targeting?.['ias-kw'];
|
|
6
|
+
const iasKwArray = Array.isArray(iasKw) ? iasKw : iasKw ? [iasKw] : [];
|
|
7
|
+
const isBrandSafe = !iasKwArray.includes('IAS_16425_KW');
|
|
9
8
|
if (slotId === 'dfp-ad--inline1' &&
|
|
10
9
|
allowedContentTypes.includes(contentType) &&
|
|
11
10
|
!isSensitive &&
|
package/dist/esm/types.d.ts
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-20251030174934",
|
|
4
4
|
"description": "Guardian advertising business logic",
|
|
5
5
|
"homepage": "https://github.com/guardian/commercial#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/guardian/commercial.git"
|
|
11
|
+
"url": "git+https://github.com/guardian/commercial.git",
|
|
12
|
+
"directory": "core"
|
|
12
13
|
},
|
|
13
14
|
"license": "Apache-2.0",
|
|
14
15
|
"files": [
|
|
@@ -31,23 +32,23 @@
|
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
34
|
"@guardian/ab-core": "^8.0.1",
|
|
34
|
-
"@guardian/libs": "^
|
|
35
|
+
"@guardian/libs": "^26.0.0"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"@guardian/ab-core": "8.0.1",
|
|
38
|
-
"@guardian/libs": "
|
|
39
|
-
"@types/googletag": "~3.3.0"
|
|
39
|
+
"@guardian/libs": "26.0.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@guardian/ophan-tracker-js": "2.
|
|
42
|
+
"@guardian/ophan-tracker-js": "2.6.1",
|
|
43
43
|
"@types/jest": "30.0.0",
|
|
44
|
-
"@types/node": "24.2
|
|
45
|
-
"
|
|
46
|
-
"jest
|
|
44
|
+
"@types/node": "24.7.2",
|
|
45
|
+
"@types/google-publisher-tag": "~1.20250811.1",
|
|
46
|
+
"jest": "^30.2.0",
|
|
47
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
47
48
|
"jest-environment-jsdom-global": "~4.0.0",
|
|
48
|
-
"ts-jest": "^29.4.
|
|
49
|
-
"
|
|
50
|
-
"
|
|
49
|
+
"ts-jest": "^29.4.4",
|
|
50
|
+
"type-fest": "^4.41.0",
|
|
51
|
+
"typescript": "5.9.3"
|
|
51
52
|
},
|
|
52
53
|
"publishConfig": {
|
|
53
54
|
"access": "public"
|