@guardian/commercial-core 0.0.0-beta-20250716121613
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/LICENSE +201 -0
- package/README.md +45 -0
- package/dist/cjs/ad-sizes.d.ts +202 -0
- package/dist/cjs/ad-sizes.js +400 -0
- package/dist/cjs/breakpoint.d.ts +8 -0
- package/dist/cjs/breakpoint.js +10 -0
- package/dist/cjs/constants/ad-label-height.d.ts +4 -0
- package/dist/cjs/constants/ad-label-height.js +7 -0
- package/dist/cjs/constants/index.d.ts +3 -0
- package/dist/cjs/constants/index.js +9 -0
- package/dist/cjs/constants/prebid-timeout.d.ts +4 -0
- package/dist/cjs/constants/prebid-timeout.js +7 -0
- package/dist/cjs/constants/top-above-nav-height.d.ts +10 -0
- package/dist/cjs/constants/top-above-nav-height.js +48 -0
- package/dist/cjs/detect-ad-blocker.d.ts +12 -0
- package/dist/cjs/detect-ad-blocker.js +61 -0
- package/dist/cjs/event-timer.d.ts +103 -0
- package/dist/cjs/event-timer.js +204 -0
- package/dist/cjs/geo/country-code.d.ts +3 -0
- package/dist/cjs/geo/country-code.js +34 -0
- package/dist/cjs/geo/geo-utils.d.ts +11 -0
- package/dist/cjs/geo/geo-utils.js +31 -0
- package/dist/cjs/geo/get-locale.d.ts +8 -0
- package/dist/cjs/geo/get-locale.js +43 -0
- package/dist/cjs/global.d.ts +71 -0
- package/dist/cjs/global.js +2 -0
- package/dist/cjs/index.d.ts +13 -0
- package/dist/cjs/index.js +46 -0
- package/dist/cjs/messenger/post-message.d.ts +1 -0
- package/dist/cjs/messenger/post-message.js +7 -0
- package/dist/cjs/permutive.d.ts +9 -0
- package/dist/cjs/permutive.js +38 -0
- package/dist/cjs/send-commercial-metrics.d.ts +58 -0
- package/dist/cjs/send-commercial-metrics.js +209 -0
- package/dist/cjs/targeting/build-page-targeting.d.ts +47 -0
- package/dist/cjs/targeting/build-page-targeting.js +112 -0
- package/dist/cjs/targeting/content.d.ts +87 -0
- package/dist/cjs/targeting/content.js +76 -0
- package/dist/cjs/targeting/personalised.d.ts +83 -0
- package/dist/cjs/targeting/personalised.js +140 -0
- package/dist/cjs/targeting/pick-targeting-values.d.ts +25 -0
- package/dist/cjs/targeting/pick-targeting-values.js +47 -0
- package/dist/cjs/targeting/session.d.ts +111 -0
- package/dist/cjs/targeting/session.js +61 -0
- package/dist/cjs/targeting/shared.d.ts +156 -0
- package/dist/cjs/targeting/shared.js +28 -0
- package/dist/cjs/targeting/teads-eligibility.d.ts +2 -0
- package/dist/cjs/targeting/teads-eligibility.js +20 -0
- package/dist/cjs/targeting/types.d.ts +6 -0
- package/dist/cjs/targeting/types.js +2 -0
- package/dist/cjs/targeting/viewport.d.ts +48 -0
- package/dist/cjs/targeting/viewport.js +22 -0
- package/dist/cjs/targeting/youtube-ima.d.ts +12 -0
- package/dist/cjs/targeting/youtube-ima.js +76 -0
- package/dist/cjs/types.d.ts +426 -0
- package/dist/cjs/types.js +12 -0
- package/dist/esm/ad-sizes.d.ts +202 -0
- package/dist/esm/ad-sizes.js +390 -0
- package/dist/esm/breakpoint.d.ts +8 -0
- package/dist/esm/breakpoint.js +6 -0
- package/dist/esm/constants/ad-label-height.d.ts +4 -0
- package/dist/esm/constants/ad-label-height.js +4 -0
- package/dist/esm/constants/index.d.ts +3 -0
- package/dist/esm/constants/index.js +3 -0
- package/dist/esm/constants/prebid-timeout.d.ts +4 -0
- package/dist/esm/constants/prebid-timeout.js +4 -0
- package/dist/esm/constants/top-above-nav-height.d.ts +10 -0
- package/dist/esm/constants/top-above-nav-height.js +45 -0
- package/dist/esm/detect-ad-blocker.d.ts +12 -0
- package/dist/esm/detect-ad-blocker.js +58 -0
- package/dist/esm/event-timer.d.ts +103 -0
- package/dist/esm/event-timer.js +199 -0
- package/dist/esm/geo/country-code.d.ts +3 -0
- package/dist/esm/geo/country-code.js +31 -0
- package/dist/esm/geo/geo-utils.d.ts +11 -0
- package/dist/esm/geo/geo-utils.js +20 -0
- package/dist/esm/geo/get-locale.d.ts +8 -0
- package/dist/esm/geo/get-locale.js +38 -0
- package/dist/esm/global.d.ts +71 -0
- package/dist/esm/global.js +0 -0
- package/dist/esm/index.d.ts +13 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/messenger/post-message.d.ts +1 -0
- package/dist/esm/messenger/post-message.js +3 -0
- package/dist/esm/permutive.d.ts +9 -0
- package/dist/esm/permutive.js +33 -0
- package/dist/esm/send-commercial-metrics.d.ts +58 -0
- package/dist/esm/send-commercial-metrics.js +204 -0
- package/dist/esm/targeting/build-page-targeting.d.ts +47 -0
- package/dist/esm/targeting/build-page-targeting.js +108 -0
- package/dist/esm/targeting/content.d.ts +87 -0
- package/dist/esm/targeting/content.js +73 -0
- package/dist/esm/targeting/personalised.d.ts +83 -0
- package/dist/esm/targeting/personalised.js +137 -0
- package/dist/esm/targeting/pick-targeting-values.d.ts +25 -0
- package/dist/esm/targeting/pick-targeting-values.js +43 -0
- package/dist/esm/targeting/session.d.ts +111 -0
- package/dist/esm/targeting/session.js +57 -0
- package/dist/esm/targeting/shared.d.ts +156 -0
- package/dist/esm/targeting/shared.js +25 -0
- package/dist/esm/targeting/teads-eligibility.d.ts +2 -0
- package/dist/esm/targeting/teads-eligibility.js +17 -0
- package/dist/esm/targeting/types.d.ts +6 -0
- package/dist/esm/targeting/types.js +0 -0
- package/dist/esm/targeting/viewport.d.ts +48 -0
- package/dist/esm/targeting/viewport.js +19 -0
- package/dist/esm/targeting/youtube-ima.d.ts +12 -0
- package/dist/esm/targeting/youtube-ima.js +73 -0
- package/dist/esm/types.d.ts +426 -0
- package/dist/esm/types.js +10 -0
- package/package.json +65 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPersonalisedTargeting = void 0;
|
|
4
|
+
const libs_1 = require("@guardian/libs");
|
|
5
|
+
const permutive_1 = require("../permutive");
|
|
6
|
+
/* -- Types -- */
|
|
7
|
+
const frequency = [
|
|
8
|
+
'0',
|
|
9
|
+
'1',
|
|
10
|
+
'2',
|
|
11
|
+
'3',
|
|
12
|
+
'4',
|
|
13
|
+
'5',
|
|
14
|
+
'6-9',
|
|
15
|
+
'10-15',
|
|
16
|
+
'16-19',
|
|
17
|
+
'20-29',
|
|
18
|
+
'30plus',
|
|
19
|
+
];
|
|
20
|
+
const AMTGRP_STORAGE_KEY = 'gu.adManagerGroup';
|
|
21
|
+
const adManagerGroups = [
|
|
22
|
+
'1',
|
|
23
|
+
'2',
|
|
24
|
+
'3',
|
|
25
|
+
'4',
|
|
26
|
+
'5',
|
|
27
|
+
'6',
|
|
28
|
+
'7',
|
|
29
|
+
'8',
|
|
30
|
+
'9',
|
|
31
|
+
'10',
|
|
32
|
+
'11',
|
|
33
|
+
'12',
|
|
34
|
+
];
|
|
35
|
+
/* -- Methods -- */
|
|
36
|
+
const getRawWithConsent = (key, state) => {
|
|
37
|
+
if (state.tcfv2) {
|
|
38
|
+
if (state.tcfv2.consents['1'])
|
|
39
|
+
return libs_1.storage.local.getRaw(key);
|
|
40
|
+
}
|
|
41
|
+
if (state.usnat) {
|
|
42
|
+
if (!state.usnat.doNotSell)
|
|
43
|
+
return libs_1.storage.local.getRaw(key);
|
|
44
|
+
}
|
|
45
|
+
if (state.aus) {
|
|
46
|
+
if (state.aus.personalisedAdvertising)
|
|
47
|
+
return libs_1.storage.local.getRaw(key);
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
const getFrequencyValue = (state) => {
|
|
52
|
+
const rawValue = getRawWithConsent('gu.alreadyVisited', state);
|
|
53
|
+
if (!rawValue)
|
|
54
|
+
return '0';
|
|
55
|
+
const visitCount = parseInt(rawValue, 10);
|
|
56
|
+
if (visitCount <= 5) {
|
|
57
|
+
return frequency[visitCount] ?? '0';
|
|
58
|
+
}
|
|
59
|
+
else if (visitCount >= 6 && visitCount <= 9) {
|
|
60
|
+
return '6-9';
|
|
61
|
+
}
|
|
62
|
+
else if (visitCount >= 10 && visitCount <= 15) {
|
|
63
|
+
return '10-15';
|
|
64
|
+
}
|
|
65
|
+
else if (visitCount >= 16 && visitCount <= 19) {
|
|
66
|
+
return '16-19';
|
|
67
|
+
}
|
|
68
|
+
else if (visitCount >= 20 && visitCount <= 29) {
|
|
69
|
+
return '20-29';
|
|
70
|
+
}
|
|
71
|
+
else if (visitCount >= 30) {
|
|
72
|
+
return '30plus';
|
|
73
|
+
}
|
|
74
|
+
return '0';
|
|
75
|
+
};
|
|
76
|
+
const getCMPTargeting = (state) => {
|
|
77
|
+
if (state.tcfv2) {
|
|
78
|
+
return {
|
|
79
|
+
cmp_interaction: state.tcfv2.eventStatus,
|
|
80
|
+
pa: state.canTarget ? 't' : 'f',
|
|
81
|
+
consent_tcfv2: state.canTarget ? 't' : 'f',
|
|
82
|
+
rdp: 'na',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (state.usnat) {
|
|
86
|
+
return {
|
|
87
|
+
consent_tcfv2: 'na',
|
|
88
|
+
rdp: !state.canTarget ? 't' : 'f',
|
|
89
|
+
pa: state.canTarget ? 't' : 'f',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (state.aus) {
|
|
93
|
+
return {
|
|
94
|
+
consent_tcfv2: 'na',
|
|
95
|
+
rdp: 'na',
|
|
96
|
+
pa: state.canTarget ? 't' : 'f',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
cmp_interaction: 'na',
|
|
101
|
+
consent_tcfv2: 'na',
|
|
102
|
+
rdp: 'na',
|
|
103
|
+
pa: 'f',
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
const isAdManagerGroup = (s) => adManagerGroups.some((g) => g === s);
|
|
107
|
+
const createAdManagerGroup = () => {
|
|
108
|
+
const index = Math.floor(Math.random() * adManagerGroups.length);
|
|
109
|
+
const group = adManagerGroups[index] ?? '12';
|
|
110
|
+
libs_1.storage.local.setRaw(AMTGRP_STORAGE_KEY, group);
|
|
111
|
+
return group;
|
|
112
|
+
};
|
|
113
|
+
const getAdManagerGroup = (state) => {
|
|
114
|
+
if (!state.framework) {
|
|
115
|
+
libs_1.storage.local.remove(AMTGRP_STORAGE_KEY);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (state.tcfv2 && !state.canTarget) {
|
|
119
|
+
libs_1.storage.local.remove(AMTGRP_STORAGE_KEY);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
const existingGroup = libs_1.storage.local.getRaw(AMTGRP_STORAGE_KEY);
|
|
123
|
+
return isAdManagerGroup(existingGroup)
|
|
124
|
+
? existingGroup
|
|
125
|
+
: createAdManagerGroup();
|
|
126
|
+
};
|
|
127
|
+
const getPermutiveWithState = (state, youtube) => {
|
|
128
|
+
if (state.canTarget) {
|
|
129
|
+
return youtube ? (0, permutive_1.getPermutivePFPSegments)() : (0, permutive_1.getPermutiveSegments)();
|
|
130
|
+
}
|
|
131
|
+
(0, permutive_1.clearPermutiveSegments)();
|
|
132
|
+
return [];
|
|
133
|
+
};
|
|
134
|
+
const getPersonalisedTargeting = ({ state, youtube, }) => ({
|
|
135
|
+
amtgrp: getAdManagerGroup(state),
|
|
136
|
+
fr: getFrequencyValue(state),
|
|
137
|
+
permutive: getPermutiveWithState(state, youtube),
|
|
138
|
+
...getCMPTargeting(state),
|
|
139
|
+
});
|
|
140
|
+
exports.getPersonalisedTargeting = getPersonalisedTargeting;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ConditionalExcept } from 'type-fest';
|
|
2
|
+
type ValidTargetingObject<Base> = ConditionalExcept<Base, null | undefined | '' | readonly [] | readonly [''] | never[] | boolean | number>;
|
|
3
|
+
/**
|
|
4
|
+
* Picks only keys with targeting values from an object.
|
|
5
|
+
* A targeting values is defined as either:
|
|
6
|
+
* - a non-empty string
|
|
7
|
+
* - an array of non-empty strings
|
|
8
|
+
*
|
|
9
|
+
* If you object is read-only, you can safely access properties on the result.
|
|
10
|
+
* For example:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* dirty = {
|
|
14
|
+
* valid: 'real',
|
|
15
|
+
* invalid: undefined,
|
|
16
|
+
* } as const;
|
|
17
|
+
*
|
|
18
|
+
* clean = pickDefinedValues(dirty);
|
|
19
|
+
*
|
|
20
|
+
* // @ts-expect-error -- you can’t access this property
|
|
21
|
+
* clean.invalid
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare const pickTargetingValues: <T extends Record<string, string | readonly string[] | undefined>>(obj: T) => ValidTargetingObject<T>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pickTargetingValues = void 0;
|
|
4
|
+
const libs_1 = require("@guardian/libs");
|
|
5
|
+
const isTargetingString = (string) => (0, libs_1.isString)(string) && string !== '';
|
|
6
|
+
const isTargetingArray = (array) => Array.isArray(array) && array.filter(isTargetingString).length > 0;
|
|
7
|
+
const isValidTargeting = (value) => {
|
|
8
|
+
if (isTargetingString(value))
|
|
9
|
+
return true;
|
|
10
|
+
if (isTargetingArray(value))
|
|
11
|
+
return true;
|
|
12
|
+
return false;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Picks only keys with targeting values from an object.
|
|
16
|
+
* A targeting values is defined as either:
|
|
17
|
+
* - a non-empty string
|
|
18
|
+
* - an array of non-empty strings
|
|
19
|
+
*
|
|
20
|
+
* If you object is read-only, you can safely access properties on the result.
|
|
21
|
+
* For example:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* dirty = {
|
|
25
|
+
* valid: 'real',
|
|
26
|
+
* invalid: undefined,
|
|
27
|
+
* } as const;
|
|
28
|
+
*
|
|
29
|
+
* clean = pickDefinedValues(dirty);
|
|
30
|
+
*
|
|
31
|
+
* // @ts-expect-error -- you can’t access this property
|
|
32
|
+
* clean.invalid
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
const pickTargetingValues = (obj) => {
|
|
36
|
+
const initialValue = {};
|
|
37
|
+
return Object.entries(obj).reduce((valid, [key, value]) => {
|
|
38
|
+
if (isValidTargeting(value)) {
|
|
39
|
+
// @ts-expect-error -- isValidTargeting checks this
|
|
40
|
+
valid[key] = Array.isArray(value)
|
|
41
|
+
? value.filter(isTargetingString)
|
|
42
|
+
: value;
|
|
43
|
+
}
|
|
44
|
+
return valid;
|
|
45
|
+
}, initialValue);
|
|
46
|
+
};
|
|
47
|
+
exports.pickTargetingValues = pickTargetingValues;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { Participations } from '@guardian/ab-core';
|
|
2
|
+
import type { CountryCode } from '@guardian/libs';
|
|
3
|
+
import type { False, True } from './types';
|
|
4
|
+
declare const referrers: readonly [{
|
|
5
|
+
readonly id: "facebook";
|
|
6
|
+
readonly match: "facebook.com";
|
|
7
|
+
}, {
|
|
8
|
+
readonly id: "google";
|
|
9
|
+
readonly match: "www.google";
|
|
10
|
+
}, {
|
|
11
|
+
readonly id: "twitter";
|
|
12
|
+
readonly match: "/t.co/";
|
|
13
|
+
}, {
|
|
14
|
+
readonly id: "reddit";
|
|
15
|
+
readonly match: "reddit.com";
|
|
16
|
+
}];
|
|
17
|
+
/**
|
|
18
|
+
* Session Targeting is based on the browser session
|
|
19
|
+
*
|
|
20
|
+
* Includes information such as the country of origin, referrer, page view ID.
|
|
21
|
+
*
|
|
22
|
+
* These values identify a browser session are either generated client-side,
|
|
23
|
+
* read from a cookie or passed down from the server.
|
|
24
|
+
*/
|
|
25
|
+
type SessionTargeting = {
|
|
26
|
+
/**
|
|
27
|
+
* **AB** Tests – [see on Ad Manager][gam]
|
|
28
|
+
*
|
|
29
|
+
* Type: _Dynamic_
|
|
30
|
+
*
|
|
31
|
+
* Values: typically start with `ab`
|
|
32
|
+
*
|
|
33
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=186327
|
|
34
|
+
*/
|
|
35
|
+
ab: string[] | null;
|
|
36
|
+
/**
|
|
37
|
+
* **A**d **T**est – [see on Ad Manager][gam]
|
|
38
|
+
*
|
|
39
|
+
* Used for testing purposes, based on query param and/or cookie.
|
|
40
|
+
*
|
|
41
|
+
* Type: _Dynamic_
|
|
42
|
+
*
|
|
43
|
+
* [See Current values](https://frontend.gutools.co.uk/commercial/adtests)
|
|
44
|
+
*
|
|
45
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=177567
|
|
46
|
+
*/
|
|
47
|
+
at: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* **C**ountry **C**ode – [see on Ad Manager][gam]
|
|
50
|
+
*
|
|
51
|
+
* Type: _Dynamic_
|
|
52
|
+
*
|
|
53
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=11703293
|
|
54
|
+
*/
|
|
55
|
+
cc: CountryCode;
|
|
56
|
+
/**
|
|
57
|
+
* Ophan **P**age **V**iew id – [see on Ad Manager][gam]
|
|
58
|
+
*
|
|
59
|
+
* ID Generated client-side, usually available on
|
|
60
|
+
* `guardian.config.ophan.pageViewId`
|
|
61
|
+
*
|
|
62
|
+
* Used mainly for internal reporting
|
|
63
|
+
*
|
|
64
|
+
* Type: _Dynamic_
|
|
65
|
+
*
|
|
66
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=206127
|
|
67
|
+
*/
|
|
68
|
+
pv: string;
|
|
69
|
+
/**
|
|
70
|
+
* **Ref**errer – [see on Ad Manager][gam]
|
|
71
|
+
*
|
|
72
|
+
* Type: _Dynamic_
|
|
73
|
+
*
|
|
74
|
+
* Sample values:
|
|
75
|
+
* - `facebook`
|
|
76
|
+
* - `google`
|
|
77
|
+
* - `googleplus`
|
|
78
|
+
* - `reddit`
|
|
79
|
+
* - `twitter`
|
|
80
|
+
*
|
|
81
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=228567
|
|
82
|
+
*/
|
|
83
|
+
ref: (typeof referrers)[number]['id'] | null;
|
|
84
|
+
/**
|
|
85
|
+
* **S**igned **I**n – [see on Ad Manager][gam]
|
|
86
|
+
*
|
|
87
|
+
*Whether a user is signed in. Based on presence of a cookie.
|
|
88
|
+
*
|
|
89
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=215727
|
|
90
|
+
*/
|
|
91
|
+
si: True | False;
|
|
92
|
+
};
|
|
93
|
+
type AllParticipations = {
|
|
94
|
+
clientSideParticipations: Participations;
|
|
95
|
+
serverSideParticipations: {
|
|
96
|
+
[key: `${string}Control`]: 'control';
|
|
97
|
+
[key: `${string}Variant`]: 'variant';
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
declare const experimentsTargeting: ({ clientSideParticipations, serverSideParticipations, }: AllParticipations) => SessionTargeting["ab"];
|
|
101
|
+
type Session = {
|
|
102
|
+
adTest: SessionTargeting['at'];
|
|
103
|
+
countryCode: CountryCode;
|
|
104
|
+
isSignedIn: boolean;
|
|
105
|
+
pageViewId: SessionTargeting['pv'];
|
|
106
|
+
participations: AllParticipations;
|
|
107
|
+
referrer: string;
|
|
108
|
+
};
|
|
109
|
+
declare const getSessionTargeting: ({ adTest, countryCode, isSignedIn, pageViewId, participations, referrer, }: Session) => SessionTargeting;
|
|
110
|
+
export type { SessionTargeting, AllParticipations };
|
|
111
|
+
export { getSessionTargeting, experimentsTargeting };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.experimentsTargeting = exports.getSessionTargeting = void 0;
|
|
4
|
+
const libs_1 = require("@guardian/libs");
|
|
5
|
+
/* -- Types -- */
|
|
6
|
+
const referrers = [
|
|
7
|
+
{
|
|
8
|
+
id: 'facebook',
|
|
9
|
+
match: 'facebook.com',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: 'google',
|
|
13
|
+
match: 'www.google',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
id: 'twitter',
|
|
17
|
+
match: '/t.co/',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'reddit',
|
|
21
|
+
match: 'reddit.com',
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
/* -- Methods -- */
|
|
25
|
+
const getReferrer = (referrer) => {
|
|
26
|
+
if (referrer === '')
|
|
27
|
+
return null;
|
|
28
|
+
const matchedRef = referrers.find((referrerType) => referrer.includes(referrerType.match)) ?? null;
|
|
29
|
+
return matchedRef ? matchedRef.id : null;
|
|
30
|
+
};
|
|
31
|
+
const experimentsTargeting = ({ clientSideParticipations, serverSideParticipations, }) => {
|
|
32
|
+
const testToParams = (testName, variant) => {
|
|
33
|
+
if (variant === 'notintest')
|
|
34
|
+
return null;
|
|
35
|
+
// GAM key-value pairs accept value strings up to 40 characters long
|
|
36
|
+
return `${testName}-${variant}`.substring(0, 40);
|
|
37
|
+
};
|
|
38
|
+
const clientSideExperiment = Object.entries(clientSideParticipations)
|
|
39
|
+
.map((test) => {
|
|
40
|
+
const [name, variant] = test;
|
|
41
|
+
return testToParams(name, variant.variant);
|
|
42
|
+
})
|
|
43
|
+
.filter(libs_1.isString);
|
|
44
|
+
const serverSideExperiments = Object.entries(serverSideParticipations)
|
|
45
|
+
.map((test) => testToParams(...test))
|
|
46
|
+
.filter(libs_1.isString);
|
|
47
|
+
if (clientSideExperiment.length + serverSideExperiments.length === 0) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return [...clientSideExperiment, ...serverSideExperiments];
|
|
51
|
+
};
|
|
52
|
+
exports.experimentsTargeting = experimentsTargeting;
|
|
53
|
+
const getSessionTargeting = ({ adTest, countryCode, isSignedIn, pageViewId, participations, referrer, }) => ({
|
|
54
|
+
ab: experimentsTargeting(participations),
|
|
55
|
+
at: adTest,
|
|
56
|
+
cc: countryCode,
|
|
57
|
+
pv: pageViewId,
|
|
58
|
+
ref: getReferrer(referrer),
|
|
59
|
+
si: isSignedIn ? 't' : 'f',
|
|
60
|
+
});
|
|
61
|
+
exports.getSessionTargeting = getSessionTargeting;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
type Brands = {
|
|
2
|
+
Foundation: 'f';
|
|
3
|
+
Paid: 'p';
|
|
4
|
+
Sponsored: 's';
|
|
5
|
+
};
|
|
6
|
+
type ContentTypes = [
|
|
7
|
+
'article',
|
|
8
|
+
'audio',
|
|
9
|
+
'crossword',
|
|
10
|
+
'gallery',
|
|
11
|
+
'interactive',
|
|
12
|
+
'liveblog',
|
|
13
|
+
'network-front',
|
|
14
|
+
'section',
|
|
15
|
+
'tag',
|
|
16
|
+
'video'
|
|
17
|
+
];
|
|
18
|
+
type Editions = {
|
|
19
|
+
UnitedKingdom: 'uk';
|
|
20
|
+
UnitedStates: 'us';
|
|
21
|
+
Australia: 'au';
|
|
22
|
+
International: 'int';
|
|
23
|
+
};
|
|
24
|
+
type Platforms = {
|
|
25
|
+
R2: 'r2';
|
|
26
|
+
NextGen: 'ng';
|
|
27
|
+
MobileApp: 'app';
|
|
28
|
+
AcceleratedMobilePages: 'amp';
|
|
29
|
+
};
|
|
30
|
+
declare const surges: {
|
|
31
|
+
readonly 0: "0";
|
|
32
|
+
readonly 50: "5";
|
|
33
|
+
readonly 100: "4";
|
|
34
|
+
readonly 200: "3";
|
|
35
|
+
readonly 300: "2";
|
|
36
|
+
readonly 400: "1";
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Shared Targeting is passed by `frontend`:
|
|
40
|
+
* https://github.com/guardian/frontend/blob/5b970cd7308175cfc1bcae2d4fb8c06ee13c5fa0/common/app/common/commercial/EditionAdTargeting.scala
|
|
41
|
+
*
|
|
42
|
+
* It is generated in `commercial-shared`:
|
|
43
|
+
* https://github.com/guardian/commercial-shared/blob/a692e8b2eba6e79eeeb666e5594f2193663f6514/src/main/scala/com/gu/commercial/display/AdTargetParam.scala
|
|
44
|
+
*
|
|
45
|
+
*
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
type SharedTargeting = {
|
|
49
|
+
/**
|
|
50
|
+
* **Bl**og tags – [see on Ad Manager][gam]
|
|
51
|
+
*
|
|
52
|
+
* Type: _Dynamic_
|
|
53
|
+
*
|
|
54
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=186687
|
|
55
|
+
*/
|
|
56
|
+
bl: string[];
|
|
57
|
+
/**
|
|
58
|
+
* **Br**anding - [see on Ad Manager][gam]
|
|
59
|
+
*
|
|
60
|
+
* Type: _Predefined_
|
|
61
|
+
*
|
|
62
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=259767
|
|
63
|
+
*/
|
|
64
|
+
br: Brands[keyof Brands];
|
|
65
|
+
/**
|
|
66
|
+
* **Co**ntributors and Authors - [see on Ad Manager][gam]
|
|
67
|
+
*
|
|
68
|
+
* Array of all contributors to the content on the page
|
|
69
|
+
*
|
|
70
|
+
* Type: _Dynamic_
|
|
71
|
+
*
|
|
72
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=186207
|
|
73
|
+
*/
|
|
74
|
+
co: string[];
|
|
75
|
+
/**
|
|
76
|
+
* **C**ontent **T**ype - [see on Ad Manager][gam]
|
|
77
|
+
*
|
|
78
|
+
* Type: _Predefined_
|
|
79
|
+
*
|
|
80
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=177807
|
|
81
|
+
*/
|
|
82
|
+
ct: ContentTypes[number];
|
|
83
|
+
/**
|
|
84
|
+
* **Edition** - [see on Ad Manager][gam]
|
|
85
|
+
*
|
|
86
|
+
* Type: _Predefined_
|
|
87
|
+
*
|
|
88
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=174207
|
|
89
|
+
*/
|
|
90
|
+
edition: Editions[keyof Editions];
|
|
91
|
+
/**
|
|
92
|
+
* **K**eywords - [see on Ad Manager][gam]
|
|
93
|
+
*
|
|
94
|
+
* Type: _Dynamic_
|
|
95
|
+
*
|
|
96
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=177687
|
|
97
|
+
*/
|
|
98
|
+
k: string[];
|
|
99
|
+
/**
|
|
100
|
+
* **Ob**server Content - [see on Ad Manager][gam]
|
|
101
|
+
*
|
|
102
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=256887
|
|
103
|
+
*/
|
|
104
|
+
ob: 't';
|
|
105
|
+
/**
|
|
106
|
+
* **P**latform - [see on Ad Manager][gam]
|
|
107
|
+
*
|
|
108
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=180207
|
|
109
|
+
*/
|
|
110
|
+
p: Platforms[keyof Platforms];
|
|
111
|
+
/**
|
|
112
|
+
* **Se**ries - [see on Ad Manager][gam]
|
|
113
|
+
*
|
|
114
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=180447
|
|
115
|
+
*/
|
|
116
|
+
se: string[];
|
|
117
|
+
/**
|
|
118
|
+
* **Sh**ort URL - [see on Ad Manager][gam]
|
|
119
|
+
*
|
|
120
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=286047
|
|
121
|
+
*/
|
|
122
|
+
sh: `https://www.theguardian.com/p/${string}`;
|
|
123
|
+
/**
|
|
124
|
+
* **Su**rging Article - [see on Ad Manager][gam]
|
|
125
|
+
*
|
|
126
|
+
* Type: _Predefined_
|
|
127
|
+
*
|
|
128
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=185007
|
|
129
|
+
*/
|
|
130
|
+
su: Array<(typeof surges)[keyof typeof surges]>;
|
|
131
|
+
/**
|
|
132
|
+
* **T**o**n**es - [see on Ad Manager][gam]
|
|
133
|
+
*
|
|
134
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=191487
|
|
135
|
+
*/
|
|
136
|
+
tn: string[];
|
|
137
|
+
/**
|
|
138
|
+
* **U**niform **R**esource **L**ocator - [see on Ad Manager][gam]
|
|
139
|
+
*
|
|
140
|
+
* Relative to `www.theguardian.com`, starts with `/`
|
|
141
|
+
*
|
|
142
|
+
* Type: _Dynamic_
|
|
143
|
+
*
|
|
144
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=174327
|
|
145
|
+
*/
|
|
146
|
+
url: `/${string}`;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* What goes in comes out
|
|
150
|
+
*/
|
|
151
|
+
declare const getSharedTargeting: (shared: Partial<SharedTargeting>) => Partial<SharedTargeting>;
|
|
152
|
+
export declare const _: {
|
|
153
|
+
getSurgingParam: (surging: number) => SharedTargeting["su"];
|
|
154
|
+
};
|
|
155
|
+
export type { SharedTargeting };
|
|
156
|
+
export { getSharedTargeting };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSharedTargeting = exports._ = void 0;
|
|
4
|
+
const pick_targeting_values_1 = require("./pick-targeting-values");
|
|
5
|
+
const surges = {
|
|
6
|
+
0: '0',
|
|
7
|
+
50: '5',
|
|
8
|
+
100: '4',
|
|
9
|
+
200: '3',
|
|
10
|
+
300: '2',
|
|
11
|
+
400: '1',
|
|
12
|
+
};
|
|
13
|
+
/* -- Methods -- */
|
|
14
|
+
const getSurgingParam = (surging) => {
|
|
15
|
+
if (surging < 50 || isNaN(surging))
|
|
16
|
+
return ['0'];
|
|
17
|
+
const thresholds = [400, 300, 200, 100, 50];
|
|
18
|
+
return thresholds.filter((n) => n <= surging).map((s) => surges[s]);
|
|
19
|
+
};
|
|
20
|
+
/* -- Targeting -- */
|
|
21
|
+
/**
|
|
22
|
+
* What goes in comes out
|
|
23
|
+
*/
|
|
24
|
+
const getSharedTargeting = (shared) => (0, pick_targeting_values_1.pickTargetingValues)(shared);
|
|
25
|
+
exports.getSharedTargeting = getSharedTargeting;
|
|
26
|
+
exports._ = {
|
|
27
|
+
getSurgingParam,
|
|
28
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isEligibleForTeads = void 0;
|
|
4
|
+
const allowedContentTypes = ['Article', 'LiveBlog'];
|
|
5
|
+
const isEligibleForTeads = (slotId) => {
|
|
6
|
+
const { contentType, isSensitive } = window.guardian.config.page;
|
|
7
|
+
// This IAS value is returned when a page is thought to contain content which is not brand safe
|
|
8
|
+
const isBrandSafe = !window.googletag
|
|
9
|
+
.pubads()
|
|
10
|
+
.getTargeting('ias-kw')
|
|
11
|
+
.includes('IAS_16425_KW');
|
|
12
|
+
if (slotId === 'dfp-ad--inline1' &&
|
|
13
|
+
allowedContentTypes.includes(contentType) &&
|
|
14
|
+
!isSensitive &&
|
|
15
|
+
isBrandSafe) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
};
|
|
20
|
+
exports.isEligibleForTeads = isEligibleForTeads;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { False, True } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Viewport Targeting
|
|
4
|
+
*
|
|
5
|
+
* Includes values related to the viewport:
|
|
6
|
+
* - breakpoint (deprecated?)
|
|
7
|
+
* - whether a CMP banner will show
|
|
8
|
+
* - size of page skin
|
|
9
|
+
*/
|
|
10
|
+
type ViewportTargeting = {
|
|
11
|
+
/**
|
|
12
|
+
* **B**reak**p**oint – [see on Ad Manager][gam]
|
|
13
|
+
*
|
|
14
|
+
* Type: _Predefined_
|
|
15
|
+
*
|
|
16
|
+
* TODO: remove 'wide'
|
|
17
|
+
*
|
|
18
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=180327
|
|
19
|
+
*/
|
|
20
|
+
bp: 'mobile' | 'tablet' | 'desktop';
|
|
21
|
+
/**
|
|
22
|
+
* InSkin (CMP Banner shown) – [see on Ad Manager][gam]
|
|
23
|
+
*
|
|
24
|
+
* Australia-specific (via Bonzai?)
|
|
25
|
+
*
|
|
26
|
+
* Type: _Predefined_
|
|
27
|
+
*
|
|
28
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=11916570
|
|
29
|
+
* */
|
|
30
|
+
inskin: True | False;
|
|
31
|
+
/**
|
|
32
|
+
* **Skin size** – [see on Ad Manager][gam]
|
|
33
|
+
*
|
|
34
|
+
* Large or Small. Used for InSkin page skins
|
|
35
|
+
*
|
|
36
|
+
* Type: _Predefined_
|
|
37
|
+
*
|
|
38
|
+
* [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=12312030
|
|
39
|
+
*/
|
|
40
|
+
skinsize: 'l' | 's';
|
|
41
|
+
};
|
|
42
|
+
type Viewport = {
|
|
43
|
+
viewPortWidth: number;
|
|
44
|
+
cmpBannerWillShow: boolean;
|
|
45
|
+
};
|
|
46
|
+
declare const getViewportTargeting: ({ viewPortWidth, cmpBannerWillShow, }: Viewport) => ViewportTargeting;
|
|
47
|
+
export type { ViewportTargeting };
|
|
48
|
+
export { getViewportTargeting };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getViewportTargeting = void 0;
|
|
4
|
+
/* -- Methods -- */
|
|
5
|
+
const findBreakpoint = (width) => {
|
|
6
|
+
if (width >= 980)
|
|
7
|
+
return 'desktop';
|
|
8
|
+
if (width >= 660)
|
|
9
|
+
return 'tablet';
|
|
10
|
+
return 'mobile';
|
|
11
|
+
};
|
|
12
|
+
const getViewportTargeting = ({ viewPortWidth, cmpBannerWillShow, }) => {
|
|
13
|
+
// Don’t show inskin if if a privacy message will be shown or on preview
|
|
14
|
+
const isPreview = window.guardian.config.page.isPreview;
|
|
15
|
+
const inskin = cmpBannerWillShow || isPreview ? 'f' : 't';
|
|
16
|
+
return {
|
|
17
|
+
bp: findBreakpoint(viewPortWidth),
|
|
18
|
+
skinsize: viewPortWidth >= 1560 ? 'l' : 's',
|
|
19
|
+
inskin,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
exports.getViewportTargeting = getViewportTargeting;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Participations } from '@guardian/ab-core';
|
|
2
|
+
import type { ConsentState } from '@guardian/libs';
|
|
3
|
+
import type { CustomParams } from './types';
|
|
4
|
+
type BuildImaAdTagUrl = {
|
|
5
|
+
adUnit: string;
|
|
6
|
+
customParams: CustomParams;
|
|
7
|
+
consentState: ConsentState;
|
|
8
|
+
clientSideParticipations: Participations;
|
|
9
|
+
isSignedIn: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const buildImaAdTagUrl: ({ adUnit, clientSideParticipations, consentState, customParams, isSignedIn, }: BuildImaAdTagUrl) => string;
|
|
12
|
+
export { buildImaAdTagUrl };
|