@guardian/commercial-core 7.1.0 → 27.0.0

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.
Files changed (173) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +23 -34
  3. package/dist/cjs/ad-sizes.d.ts +150 -8
  4. package/dist/cjs/ad-sizes.js +129 -38
  5. package/dist/cjs/breakpoint.d.ts +8 -0
  6. package/dist/cjs/breakpoint.js +10 -0
  7. package/dist/cjs/constants/index.d.ts +1 -1
  8. package/dist/cjs/constants/index.js +2 -2
  9. package/dist/cjs/detect-ad-blocker.js +1 -2
  10. package/dist/cjs/event-timer.d.ts +60 -48
  11. package/dist/cjs/event-timer.js +149 -115
  12. package/dist/cjs/geo/country-code.d.ts +3 -0
  13. package/dist/cjs/geo/country-code.js +34 -0
  14. package/dist/cjs/geo/geo-utils.d.ts +11 -0
  15. package/dist/cjs/geo/geo-utils.js +31 -0
  16. package/dist/cjs/global.d.ts +58 -10
  17. package/dist/cjs/index.d.ts +9 -39
  18. package/dist/cjs/index.js +12 -67
  19. package/dist/cjs/send-commercial-metrics.d.ts +8 -2
  20. package/dist/cjs/send-commercial-metrics.js +51 -27
  21. package/dist/cjs/targeting/build-page-targeting.d.ts +4 -5
  22. package/dist/cjs/targeting/build-page-targeting.js +35 -7
  23. package/dist/cjs/targeting/content.d.ts +1 -1
  24. package/dist/cjs/targeting/content.js +1 -1
  25. package/dist/cjs/targeting/personalised.d.ts +2 -3
  26. package/dist/cjs/targeting/personalised.js +3 -3
  27. package/dist/cjs/targeting/pick-targeting-values.d.ts +1 -1
  28. package/dist/cjs/targeting/session.d.ts +2 -2
  29. package/dist/cjs/targeting/shared.d.ts +31 -20
  30. package/dist/cjs/targeting/shared.js +0 -30
  31. package/dist/cjs/targeting/teads-eligibility.d.ts +2 -0
  32. package/dist/cjs/targeting/teads-eligibility.js +20 -0
  33. package/dist/cjs/targeting/types.d.ts +6 -0
  34. package/dist/cjs/targeting/types.js +2 -0
  35. package/dist/cjs/targeting/viewport.d.ts +1 -1
  36. package/dist/cjs/targeting/youtube-ima.d.ts +4 -3
  37. package/dist/cjs/targeting/youtube-ima.js +7 -4
  38. package/dist/cjs/types.d.ts +399 -63
  39. package/dist/cjs/types.js +10 -0
  40. package/dist/esm/ad-sizes.d.ts +150 -8
  41. package/dist/esm/ad-sizes.js +127 -38
  42. package/dist/esm/breakpoint.d.ts +8 -0
  43. package/dist/esm/breakpoint.js +6 -0
  44. package/dist/esm/constants/index.d.ts +1 -1
  45. package/dist/esm/constants/index.js +1 -1
  46. package/dist/esm/event-timer.d.ts +60 -48
  47. package/dist/esm/event-timer.js +147 -115
  48. package/dist/esm/geo/country-code.d.ts +3 -0
  49. package/dist/esm/geo/country-code.js +31 -0
  50. package/dist/esm/geo/geo-utils.d.ts +11 -0
  51. package/dist/esm/geo/geo-utils.js +20 -0
  52. package/dist/esm/global.d.ts +58 -10
  53. package/dist/esm/global.js +0 -1
  54. package/dist/esm/index.d.ts +9 -39
  55. package/dist/esm/index.js +6 -31
  56. package/dist/esm/send-commercial-metrics.d.ts +8 -2
  57. package/dist/esm/send-commercial-metrics.js +48 -25
  58. package/dist/esm/targeting/build-page-targeting.d.ts +4 -5
  59. package/dist/esm/targeting/build-page-targeting.js +35 -7
  60. package/dist/esm/targeting/content.d.ts +1 -1
  61. package/dist/esm/targeting/content.js +1 -1
  62. package/dist/esm/targeting/personalised.d.ts +2 -3
  63. package/dist/esm/targeting/personalised.js +3 -3
  64. package/dist/esm/targeting/pick-targeting-values.d.ts +1 -1
  65. package/dist/esm/targeting/session.d.ts +2 -2
  66. package/dist/esm/targeting/shared.d.ts +31 -20
  67. package/dist/esm/targeting/shared.js +0 -30
  68. package/dist/esm/targeting/teads-eligibility.d.ts +2 -0
  69. package/dist/esm/targeting/teads-eligibility.js +17 -0
  70. package/dist/esm/targeting/types.d.ts +6 -0
  71. package/dist/esm/targeting/types.js +0 -0
  72. package/dist/esm/targeting/viewport.d.ts +1 -1
  73. package/dist/esm/targeting/youtube-ima.d.ts +4 -3
  74. package/dist/esm/targeting/youtube-ima.js +7 -4
  75. package/dist/esm/types.d.ts +399 -63
  76. package/dist/esm/types.js +10 -1
  77. package/package.json +64 -83
  78. package/dist/cjs/__vendor/a9-apstag.d.ts +0 -1
  79. package/dist/cjs/__vendor/a9-apstag.js +0 -34
  80. package/dist/cjs/__vendor/ipsos-mori.d.ts +0 -1
  81. package/dist/cjs/__vendor/ipsos-mori.js +0 -18
  82. package/dist/cjs/__vendor/launchpad.d.ts +0 -1
  83. package/dist/cjs/__vendor/launchpad.js +0 -25
  84. package/dist/cjs/__vendor/pubmatic.d.ts +0 -1
  85. package/dist/cjs/__vendor/pubmatic.js +0 -49
  86. package/dist/cjs/__vendor/twitter-script.d.ts +0 -1
  87. package/dist/cjs/__vendor/twitter-script.js +0 -26
  88. package/dist/cjs/create-ad-slot.d.ts +0 -17
  89. package/dist/cjs/create-ad-slot.js +0 -107
  90. package/dist/cjs/google-analytics.d.ts +0 -1
  91. package/dist/cjs/google-analytics.js +0 -14
  92. package/dist/cjs/lib/ab-localstorage.d.ts +0 -2
  93. package/dist/cjs/lib/ab-localstorage.js +0 -14
  94. package/dist/cjs/lib/breakpoint.d.ts +0 -4
  95. package/dist/cjs/lib/breakpoint.js +0 -5
  96. package/dist/cjs/lib/can-use-dom.d.ts +0 -2
  97. package/dist/cjs/lib/can-use-dom.js +0 -9
  98. package/dist/cjs/lib/construct-query.d.ts +0 -3
  99. package/dist/cjs/lib/construct-query.js +0 -12
  100. package/dist/cjs/messenger.d.ts +0 -97
  101. package/dist/cjs/messenger.js +0 -281
  102. package/dist/cjs/targeting/build-page-targeting-consentless.d.ts +0 -15
  103. package/dist/cjs/targeting/build-page-targeting-consentless.js +0 -46
  104. package/dist/cjs/targeting/youtube.d.ts +0 -13
  105. package/dist/cjs/targeting/youtube.js +0 -64
  106. package/dist/cjs/third-party-tags/ias.d.ts +0 -7
  107. package/dist/cjs/third-party-tags/ias.js +0 -14
  108. package/dist/cjs/third-party-tags/inizio.d.ts +0 -13
  109. package/dist/cjs/third-party-tags/inizio.js +0 -39
  110. package/dist/cjs/third-party-tags/permutive.d.ts +0 -6
  111. package/dist/cjs/third-party-tags/permutive.js +0 -13
  112. package/dist/cjs/third-party-tags/remarketing.d.ts +0 -7
  113. package/dist/cjs/third-party-tags/remarketing.js +0 -22
  114. package/dist/cjs/third-party-tags/twitter-uwt.d.ts +0 -7
  115. package/dist/cjs/third-party-tags/twitter-uwt.js +0 -15
  116. package/dist/cjs/track-gpc-signal.d.ts +0 -7
  117. package/dist/cjs/track-gpc-signal.js +0 -17
  118. package/dist/cjs/track-labs-container.d.ts +0 -7
  119. package/dist/cjs/track-labs-container.js +0 -35
  120. package/dist/cjs/track-scroll-depth.d.ts +0 -8
  121. package/dist/cjs/track-scroll-depth.js +0 -41
  122. package/dist/esm/__vendor/a9-apstag.d.ts +0 -1
  123. package/dist/esm/__vendor/a9-apstag.js +0 -30
  124. package/dist/esm/__vendor/ipsos-mori.d.ts +0 -1
  125. package/dist/esm/__vendor/ipsos-mori.js +0 -14
  126. package/dist/esm/__vendor/launchpad.d.ts +0 -1
  127. package/dist/esm/__vendor/launchpad.js +0 -21
  128. package/dist/esm/__vendor/pubmatic.d.ts +0 -1
  129. package/dist/esm/__vendor/pubmatic.js +0 -45
  130. package/dist/esm/__vendor/twitter-script.d.ts +0 -1
  131. package/dist/esm/__vendor/twitter-script.js +0 -22
  132. package/dist/esm/create-ad-slot.d.ts +0 -17
  133. package/dist/esm/create-ad-slot.js +0 -103
  134. package/dist/esm/google-analytics.d.ts +0 -1
  135. package/dist/esm/google-analytics.js +0 -10
  136. package/dist/esm/lib/ab-localstorage.d.ts +0 -2
  137. package/dist/esm/lib/ab-localstorage.js +0 -10
  138. package/dist/esm/lib/breakpoint.d.ts +0 -4
  139. package/dist/esm/lib/breakpoint.js +0 -2
  140. package/dist/esm/lib/can-use-dom.d.ts +0 -2
  141. package/dist/esm/lib/can-use-dom.js +0 -6
  142. package/dist/esm/lib/construct-query.d.ts +0 -3
  143. package/dist/esm/lib/construct-query.js +0 -9
  144. package/dist/esm/messenger.d.ts +0 -97
  145. package/dist/esm/messenger.js +0 -274
  146. package/dist/esm/targeting/build-page-targeting-consentless.d.ts +0 -15
  147. package/dist/esm/targeting/build-page-targeting-consentless.js +0 -43
  148. package/dist/esm/targeting/youtube.d.ts +0 -13
  149. package/dist/esm/targeting/youtube.js +0 -60
  150. package/dist/esm/third-party-tags/ias.d.ts +0 -7
  151. package/dist/esm/third-party-tags/ias.js +0 -10
  152. package/dist/esm/third-party-tags/inizio.d.ts +0 -13
  153. package/dist/esm/third-party-tags/inizio.js +0 -35
  154. package/dist/esm/third-party-tags/permutive.d.ts +0 -6
  155. package/dist/esm/third-party-tags/permutive.js +0 -9
  156. package/dist/esm/third-party-tags/remarketing.d.ts +0 -7
  157. package/dist/esm/third-party-tags/remarketing.js +0 -18
  158. package/dist/esm/third-party-tags/twitter-uwt.d.ts +0 -7
  159. package/dist/esm/third-party-tags/twitter-uwt.js +0 -11
  160. package/dist/esm/track-gpc-signal.d.ts +0 -7
  161. package/dist/esm/track-gpc-signal.js +0 -14
  162. package/dist/esm/track-labs-container.d.ts +0 -7
  163. package/dist/esm/track-labs-container.js +0 -32
  164. package/dist/esm/track-scroll-depth.d.ts +0 -8
  165. package/dist/esm/track-scroll-depth.js +0 -38
  166. /package/dist/cjs/constants/{adLabelHeight.d.ts → ad-label-height.d.ts} +0 -0
  167. /package/dist/cjs/constants/{adLabelHeight.js → ad-label-height.js} +0 -0
  168. /package/dist/cjs/{lib → geo}/get-locale.d.ts +0 -0
  169. /package/dist/cjs/{lib → geo}/get-locale.js +0 -0
  170. /package/dist/esm/constants/{adLabelHeight.d.ts → ad-label-height.d.ts} +0 -0
  171. /package/dist/esm/constants/{adLabelHeight.js → ad-label-height.js} +0 -0
  172. /package/dist/esm/{lib → geo}/get-locale.d.ts +0 -0
  173. /package/dist/esm/{lib → geo}/get-locale.js +0 -0
@@ -1,5 +1,4 @@
1
- import { onConsent } from '@guardian/consent-management-platform';
2
- import { log } from '@guardian/libs';
1
+ import { getMeasures, isNonNullable, log, onConsent } from '@guardian/libs';
3
2
  import { EventTimer } from './event-timer';
4
3
  var Endpoints;
5
4
  (function (Endpoints) {
@@ -15,7 +14,6 @@ let commercialMetricsPayload = {
15
14
  };
16
15
  let devProperties = [];
17
16
  let adBlockerProperties = [];
18
- let initialised = false;
19
17
  let endpoint;
20
18
  const setEndpoint = (isDev) => (endpoint = isDev ? Endpoints.CODE : Endpoints.PROD);
21
19
  const setDevProperties = (isDev) => (devProperties = isDev
@@ -42,15 +40,26 @@ const mapEventTimerPropertiesToString = (properties) => {
42
40
  value: String(value),
43
41
  }));
44
42
  };
45
- const roundTimeStamp = (events) => {
46
- return events.map(({ name, ts }) => ({
43
+ const roundTimeStamp = (events, measures) => {
44
+ const roundedEvents = events.map(({ name, ts }) => ({
47
45
  name,
48
46
  value: Math.ceil(ts),
49
47
  }));
48
+ const roundedMeasures = measures.map(({ name, duration }) => ({
49
+ name,
50
+ value: Math.ceil(duration),
51
+ }));
52
+ return [...roundedEvents, ...roundedMeasures];
50
53
  };
51
54
  function sendMetrics() {
52
55
  log('commercial', 'About to send commercial metrics', commercialMetricsPayload);
53
- return navigator.sendBeacon(endpoint, JSON.stringify(commercialMetricsPayload));
56
+ void fetch(endpoint, {
57
+ method: 'POST',
58
+ body: JSON.stringify(commercialMetricsPayload),
59
+ keepalive: true,
60
+ cache: 'no-store',
61
+ mode: 'no-cors',
62
+ });
54
63
  }
55
64
  /**
56
65
  * Gather how many times the user has experienced the “offline” event
@@ -69,6 +78,15 @@ const getOfflineCount = () => typeof window.guardian.offlineCount === 'number'
69
78
  },
70
79
  ]
71
80
  : [];
81
+ /**
82
+ * Measures added with @guardian/libs’s `startPerformanceMeasure`
83
+ *
84
+ * Allows for more granular monitoring of web page performance.
85
+ */
86
+ const getPerformanceMeasures = (...teams) => getMeasures(teams).map(({ detail: { subscription, name, action }, duration }) => ({
87
+ name: [subscription, name, action].filter(isNonNullable).join('_'),
88
+ value: duration,
89
+ }));
72
90
  function gatherMetricsOnPageUnload() {
73
91
  // Assemble commercial properties and metrics
74
92
  const eventTimer = EventTimer.get();
@@ -79,20 +97,24 @@ function gatherMetricsOnPageUnload() {
79
97
  .concat(devProperties)
80
98
  .concat(adBlockerProperties);
81
99
  commercialMetricsPayload.properties = properties;
82
- const metrics = roundTimeStamp(eventTimer.events).concat(getOfflineCount());
100
+ const metrics = roundTimeStamp(eventTimer.marks, eventTimer.measures)
101
+ .concat(getOfflineCount())
102
+ .concat(getPerformanceMeasures('dotcom'));
83
103
  commercialMetricsPayload.metrics = metrics;
84
104
  sendMetrics();
85
105
  }
86
106
  const listener = (e) => {
87
- switch (e.type) {
88
- case 'visibilitychange':
89
- if (document.visibilityState === 'hidden') {
107
+ if (window.guardian.config.shouldSendCommercialMetrics) {
108
+ switch (e.type) {
109
+ case 'visibilitychange':
110
+ if (document.visibilityState === 'hidden') {
111
+ gatherMetricsOnPageUnload();
112
+ }
113
+ return;
114
+ case 'pagehide':
90
115
  gatherMetricsOnPageUnload();
91
- }
92
- return;
93
- case 'pagehide':
94
- gatherMetricsOnPageUnload();
95
- return;
116
+ return;
117
+ }
96
118
  }
97
119
  };
98
120
  const addVisibilityListeners = () => {
@@ -116,13 +138,13 @@ const checkConsent = async () => {
116
138
  * A method to asynchronously send metrics after initialization.
117
139
  */
118
140
  async function bypassCommercialMetricsSampling() {
119
- if (!initialised) {
141
+ if (!window.guardian.config.commercialMetricsInitialised) {
120
142
  console.warn('initCommercialMetrics not yet initialised');
121
143
  return;
122
144
  }
123
145
  const consented = await checkConsent();
124
146
  if (consented) {
125
- addVisibilityListeners();
147
+ window.guardian.config.shouldSendCommercialMetrics = true;
126
148
  }
127
149
  else {
128
150
  log('commercial', "Metrics won't be sent because consent wasn't given");
@@ -130,6 +152,7 @@ async function bypassCommercialMetricsSampling() {
130
152
  }
131
153
  /**
132
154
  * A method to initialise metrics.
155
+ * Note: this is initialised in the frontend/DCR bundles, not the commercial bundle.
133
156
  * @param init.pageViewId - identifies the page view. Usually available on `guardian.config.ophan.pageViewId`. Defaults to `null`
134
157
  * @param init.browserId - identifies the browser. Usually available via `getCookie({ name: 'bwid' })`. Defaults to `null`
135
158
  * @param init.isDev - used to determine whether to use CODE or PROD endpoints.
@@ -142,20 +165,19 @@ async function initCommercialMetrics({ pageViewId, browserId, isDev, adBlockerIn
142
165
  setEndpoint(isDev);
143
166
  setDevProperties(isDev);
144
167
  setAdBlockerProperties(adBlockerInUse);
145
- if (initialised) {
168
+ addVisibilityListeners();
169
+ if (window.guardian.config.commercialMetricsInitialised) {
146
170
  return false;
147
171
  }
148
- initialised = true;
172
+ window.guardian.config.commercialMetricsInitialised = true;
149
173
  const userIsInSamplingGroup = Math.random() <= sampling;
150
174
  if (isDev || userIsInSamplingGroup) {
151
175
  const consented = await checkConsent();
152
176
  if (consented) {
153
- addVisibilityListeners();
177
+ window.guardian.config.shouldSendCommercialMetrics = true;
154
178
  return true;
155
179
  }
156
- else {
157
- log('commercial', "Metrics won't be sent because consent wasn't given");
158
- }
180
+ log('commercial', "Metrics won't be sent because consent wasn't given");
159
181
  }
160
182
  return false;
161
183
  }
@@ -166,7 +188,8 @@ export const _ = {
166
188
  roundTimeStamp,
167
189
  transformToObjectEntries,
168
190
  reset: () => {
169
- initialised = false;
191
+ window.guardian.config.commercialMetricsInitialised = false;
192
+ window.guardian.config.shouldSendCommercialMetrics = false;
170
193
  commercialMetricsPayload = {
171
194
  page_view_id: undefined,
172
195
  browser_id: undefined,
@@ -178,4 +201,4 @@ export const _ = {
178
201
  removeEventListener('pagehide', listener);
179
202
  },
180
203
  };
181
- export { bypassCommercialMetricsSampling, initCommercialMetrics };
204
+ export { bypassCommercialMetricsSampling, initCommercialMetrics, checkConsent };
@@ -1,13 +1,11 @@
1
1
  import type { Participations } from '@guardian/ab-core';
2
- import type { ConsentState } from '@guardian/consent-management-platform/dist/types';
3
- import type { CountryCode } from '@guardian/libs';
4
- import type { False, True } from '../types';
2
+ import type { ConsentState, CountryCode } from '@guardian/libs';
5
3
  import type { AdManagerGroup, Frequency } from './personalised';
6
4
  import type { SharedTargeting } from './shared';
5
+ import type { TrueOrFalse } from './types';
7
6
  type PartialWithNulls<T> = {
8
7
  [P in keyof T]?: T[P] | null;
9
8
  };
10
- type TrueOrFalse = True | False;
11
9
  type PageTargeting = PartialWithNulls<{
12
10
  ab: string[];
13
11
  af: 't';
@@ -41,8 +39,9 @@ type BuildPageTargetingParams = {
41
39
  adFree: boolean;
42
40
  clientSideParticipations: Participations;
43
41
  consentState: ConsentState;
42
+ isSignedIn?: boolean;
44
43
  youtube?: boolean;
45
44
  };
46
- declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, youtube, }: BuildPageTargetingParams) => Record<string, string | string[]>;
45
+ declare const buildPageTargeting: ({ adFree, clientSideParticipations, consentState, isSignedIn, youtube, }: BuildPageTargetingParams) => Record<string, string | string[]>;
47
46
  export { buildPageTargeting, filterValues };
48
47
  export type { PageTargeting };
@@ -1,6 +1,6 @@
1
- import { cmp } from '@guardian/consent-management-platform';
2
- import { getCookie, isString } from '@guardian/libs';
3
- import { getLocale } from '../lib/get-locale';
1
+ import { cmp, getConsentFor, getCookie, isString } from '@guardian/libs';
2
+ import { supportsPerformanceAPI } from '../event-timer';
3
+ import { getLocale } from '../geo/get-locale';
4
4
  import { getContentTargeting } from './content';
5
5
  import { getPersonalisedTargeting } from './personalised';
6
6
  import { getSessionTargeting } from './session';
@@ -21,7 +21,30 @@ const filterValues = (pageTargets) => {
21
21
  }
22
22
  return filtered;
23
23
  };
24
- const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, youtube = false, }) => {
24
+ const lastPerformanceEntryIsNavigationType = () => {
25
+ if (!supportsPerformanceAPI()) {
26
+ return false;
27
+ }
28
+ const navigationEvents = performance.getEntriesByType('navigation');
29
+ const lastNavigationEvent = navigationEvents[navigationEvents.length - 1];
30
+ // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType#navigation
31
+ return lastNavigationEvent?.entryType === 'navigation';
32
+ };
33
+ const referrerMatchesHost = (referrer) => {
34
+ if (!referrer) {
35
+ return false;
36
+ }
37
+ const referrerUrl = new URL(referrer);
38
+ return referrerUrl.hostname === window.location.hostname;
39
+ };
40
+ // A consentless friendly way of determining if this is the users first visit to the page
41
+ const isFirstVisit = (referrer) => {
42
+ if (supportsPerformanceAPI() && !lastPerformanceEntryIsNavigationType()) {
43
+ return false;
44
+ }
45
+ return !referrerMatchesHost(referrer);
46
+ };
47
+ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, }) => {
25
48
  const { page, isDotcomRendering } = window.guardian.config;
26
49
  const adFreeTargeting = adFree ? { af: 't' } : {};
27
50
  const sharedAdTargeting = page.sharedAdTargeting
@@ -39,17 +62,17 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
39
62
  videoLength: page.videoDuration,
40
63
  keywords: sharedAdTargeting.k ?? [],
41
64
  });
42
- const getReferrer = () => document.referrer || '';
65
+ const referrer = document.referrer || '';
43
66
  const sessionTargeting = getSessionTargeting({
44
67
  adTest: getCookie({ name: 'adtest', shouldMemoize: true }),
45
68
  countryCode: getLocale(),
46
- isSignedIn: !!getCookie({ name: 'GU_U' }),
69
+ isSignedIn,
47
70
  pageViewId: window.guardian.config.ophan.pageViewId,
48
71
  participations: {
49
72
  clientSideParticipations,
50
73
  serverSideParticipations: window.guardian.config.tests ?? {},
51
74
  },
52
- referrer: getReferrer(),
75
+ referrer,
53
76
  });
54
77
  const getViewport = () => {
55
78
  return {
@@ -65,6 +88,10 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
65
88
  state: consentState,
66
89
  youtube,
67
90
  });
91
+ const consentlessTargeting = {};
92
+ if (!getConsentFor('googletag', consentState)) {
93
+ consentlessTargeting.firstvisit = isFirstVisit(referrer) ? 't' : 'f';
94
+ }
68
95
  const pageTargets = {
69
96
  ...personalisedTargeting,
70
97
  ...sharedAdTargeting,
@@ -72,6 +99,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
72
99
  ...contentTargeting,
73
100
  ...sessionTargeting,
74
101
  ...viewportTargeting,
102
+ ...consentlessTargeting,
75
103
  };
76
104
  // filter !(string | string[]) and empty values
77
105
  const pageTargeting = filterValues(pageTargets);
@@ -1,5 +1,5 @@
1
- import type { False, True } from '../types';
2
1
  import type { SharedTargeting } from './shared';
2
+ import type { False, True } from './types';
3
3
  declare const videoLengths: readonly ["25", "30", "60", "90", "120", "150", "180", "210", "240", "270", "300"];
4
4
  /**
5
5
  * Content Targeting comes from the server
@@ -1,7 +1,7 @@
1
1
  import { isString } from '@guardian/libs';
2
2
  /* -- Types -- */
3
3
  const videoLengths = [
4
- '25',
4
+ '25', // TODO: confirm this is a real value
5
5
  '30',
6
6
  '60',
7
7
  '90',
@@ -1,6 +1,5 @@
1
- import type { ConsentState } from '@guardian/consent-management-platform/dist/types';
2
- import type { TCEventStatusCode } from '@guardian/consent-management-platform/dist/types/tcfv2';
3
- import type { False, NotApplicable, True } from '../types';
1
+ import type { ConsentState, TCEventStatusCode } from '@guardian/libs';
2
+ import type { False, NotApplicable, True } from './types';
4
3
  declare const frequency: readonly ["0", "1", "2", "3", "4", "5", "6-9", "10-15", "16-19", "20-29", "30plus"];
5
4
  type Frequency = (typeof frequency)[number];
6
5
  declare const adManagerGroups: readonly ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
@@ -35,8 +35,8 @@ const getRawWithConsent = (key, state) => {
35
35
  if (state.tcfv2.consents['1'])
36
36
  return storage.local.getRaw(key);
37
37
  }
38
- if (state.ccpa) {
39
- if (!state.ccpa.doNotSell)
38
+ if (state.usnat) {
39
+ if (!state.usnat.doNotSell)
40
40
  return storage.local.getRaw(key);
41
41
  }
42
42
  if (state.aus) {
@@ -79,7 +79,7 @@ const getCMPTargeting = (state) => {
79
79
  rdp: 'na',
80
80
  };
81
81
  }
82
- if (state.ccpa) {
82
+ if (state.usnat) {
83
83
  return {
84
84
  consent_tcfv2: 'na',
85
85
  rdp: !state.canTarget ? 't' : 'f',
@@ -21,5 +21,5 @@ type ValidTargetingObject<Base> = ConditionalExcept<Base, null | undefined | ''
21
21
  * clean.invalid
22
22
  * ```
23
23
  */
24
- export declare const pickTargetingValues: <T extends Record<string, string | readonly string[] | undefined>>(obj: T) => import("type-fest").Except<T, import("type-fest").ConditionalKeys<T, number | boolean | "" | never[] | readonly [] | readonly [""] | null | undefined>>;
24
+ export declare const pickTargetingValues: <T extends Record<string, string | readonly string[] | undefined>>(obj: T) => ValidTargetingObject<T>;
25
25
  export {};
@@ -1,6 +1,6 @@
1
1
  import type { Participations } from '@guardian/ab-core';
2
2
  import type { CountryCode } from '@guardian/libs';
3
- import type { False, True } from '../types';
3
+ import type { False, True } from './types';
4
4
  declare const referrers: readonly [{
5
5
  readonly id: "facebook";
6
6
  readonly match: "facebook.com";
@@ -97,7 +97,7 @@ type AllParticipations = {
97
97
  [key: `${string}Variant`]: 'variant';
98
98
  };
99
99
  };
100
- declare const experimentsTargeting: ({ clientSideParticipations, serverSideParticipations, }: AllParticipations) => SessionTargeting['ab'];
100
+ declare const experimentsTargeting: ({ clientSideParticipations, serverSideParticipations, }: AllParticipations) => SessionTargeting["ab"];
101
101
  type Session = {
102
102
  adTest: SessionTargeting['at'];
103
103
  countryCode: CountryCode;
@@ -1,20 +1,31 @@
1
- declare const brands: {
2
- readonly Foundation: "f";
3
- readonly Paid: "p";
4
- readonly Sponsored: "s";
1
+ type Brands = {
2
+ Foundation: 'f';
3
+ Paid: 'p';
4
+ Sponsored: 's';
5
5
  };
6
- declare const contentTypes: readonly ["article", "audio", "crossword", "gallery", "interactive", "liveblog", "network-front", "section", "tag", "video"];
7
- declare const editions: {
8
- readonly UnitedKingdom: "uk";
9
- readonly UnitedStates: "us";
10
- readonly Australia: "au";
11
- readonly International: "int";
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';
12
23
  };
13
- declare const platforms: {
14
- readonly R2: "r2";
15
- readonly NextGen: "ng";
16
- readonly MobileApp: "app";
17
- readonly AcceleratedMobilePages: "amp";
24
+ type Platforms = {
25
+ R2: 'r2';
26
+ NextGen: 'ng';
27
+ MobileApp: 'app';
28
+ AcceleratedMobilePages: 'amp';
18
29
  };
19
30
  declare const surges: {
20
31
  readonly 0: "0";
@@ -50,7 +61,7 @@ type SharedTargeting = {
50
61
  *
51
62
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=259767
52
63
  */
53
- br: (typeof brands)[keyof typeof brands];
64
+ br: Brands[keyof Brands];
54
65
  /**
55
66
  * **Co**ntributors and Authors - [see on Ad Manager][gam]
56
67
  *
@@ -68,7 +79,7 @@ type SharedTargeting = {
68
79
  *
69
80
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=177807
70
81
  */
71
- ct: (typeof contentTypes)[number];
82
+ ct: ContentTypes[number];
72
83
  /**
73
84
  * **Edition** - [see on Ad Manager][gam]
74
85
  *
@@ -76,7 +87,7 @@ type SharedTargeting = {
76
87
  *
77
88
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=174207
78
89
  */
79
- edition: (typeof editions)[keyof typeof editions];
90
+ edition: Editions[keyof Editions];
80
91
  /**
81
92
  * **K**eywords - [see on Ad Manager][gam]
82
93
  *
@@ -96,7 +107,7 @@ type SharedTargeting = {
96
107
  *
97
108
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=180207
98
109
  */
99
- p: (typeof platforms)[keyof typeof platforms];
110
+ p: Platforms[keyof Platforms];
100
111
  /**
101
112
  * **Se**ries - [see on Ad Manager][gam]
102
113
  *
@@ -139,7 +150,7 @@ type SharedTargeting = {
139
150
  */
140
151
  declare const getSharedTargeting: (shared: Partial<SharedTargeting>) => Partial<SharedTargeting>;
141
152
  export declare const _: {
142
- getSurgingParam: (surging: number) => SharedTargeting['su'];
153
+ getSurgingParam: (surging: number) => SharedTargeting["su"];
143
154
  };
144
155
  export type { SharedTargeting };
145
156
  export { getSharedTargeting };
@@ -1,34 +1,4 @@
1
1
  import { pickTargetingValues } from './pick-targeting-values';
2
- /* -- Types -- */
3
- const brands = {
4
- Foundation: 'f',
5
- Paid: 'p',
6
- Sponsored: 's',
7
- };
8
- const contentTypes = [
9
- 'article',
10
- 'audio',
11
- 'crossword',
12
- 'gallery',
13
- 'interactive',
14
- 'liveblog',
15
- 'network-front',
16
- 'section',
17
- 'tag',
18
- 'video',
19
- ];
20
- const editions = {
21
- UnitedKingdom: 'uk',
22
- UnitedStates: 'us',
23
- Australia: 'au',
24
- International: 'int',
25
- };
26
- const platforms = {
27
- R2: 'r2',
28
- NextGen: 'ng',
29
- MobileApp: 'app',
30
- AcceleratedMobilePages: 'amp',
31
- };
32
2
  const surges = {
33
3
  0: '0',
34
4
  50: '5',
@@ -0,0 +1,2 @@
1
+ declare const isEligibleForTeads: (slotId: string) => boolean;
2
+ export { isEligibleForTeads };
@@ -0,0 +1,17 @@
1
+ const allowedContentTypes = ['Article', 'LiveBlog'];
2
+ const isEligibleForTeads = (slotId) => {
3
+ const { contentType, isSensitive } = window.guardian.config.page;
4
+ // This IAS value is returned when a page is thought to contain content which is not brand safe
5
+ const isBrandSafe = !window.googletag
6
+ .pubads()
7
+ .getTargeting('ias-kw')
8
+ .includes('IAS_16425_KW');
9
+ if (slotId === 'dfp-ad--inline1' &&
10
+ allowedContentTypes.includes(contentType) &&
11
+ !isSensitive &&
12
+ isBrandSafe) {
13
+ return true;
14
+ }
15
+ return false;
16
+ };
17
+ export { isEligibleForTeads };
@@ -0,0 +1,6 @@
1
+ export type False = 'f';
2
+ export type True = 't';
3
+ export type TrueOrFalse = True | False;
4
+ export type NotApplicable = 'na';
5
+ export type MaybeArray<T> = T | T[];
6
+ export type CustomParams = Record<string, MaybeArray<string | number | boolean>>;
File without changes
@@ -1,4 +1,4 @@
1
- import type { False, True } from '../types';
1
+ import type { False, True } from './types';
2
2
  /**
3
3
  * Viewport Targeting
4
4
  *
@@ -1,11 +1,12 @@
1
1
  import type { Participations } from '@guardian/ab-core';
2
- import type { ConsentState } from '@guardian/consent-management-platform/dist/types';
3
- import type { CustomParams } from '../types';
2
+ import type { ConsentState } from '@guardian/libs';
3
+ import type { CustomParams } from './types';
4
4
  type BuildImaAdTagUrl = {
5
5
  adUnit: string;
6
6
  customParams: CustomParams;
7
7
  consentState: ConsentState;
8
8
  clientSideParticipations: Participations;
9
+ isSignedIn: boolean;
9
10
  };
10
- declare const buildImaAdTagUrl: ({ adUnit, clientSideParticipations, consentState, customParams, }: BuildImaAdTagUrl) => string;
11
+ declare const buildImaAdTagUrl: ({ adUnit, clientSideParticipations, consentState, customParams, isSignedIn, }: BuildImaAdTagUrl) => string;
11
12
  export { buildImaAdTagUrl };
@@ -15,13 +15,14 @@ const encodeCustomParams = (params) => {
15
15
  .join('&');
16
16
  return encodedParams;
17
17
  };
18
- const mergeCustomParamsWithTargeting = (customParams, consentState, clientSideParticipations) => {
18
+ const mergeCustomParamsWithTargeting = (customParams, consentState, clientSideParticipations, isSignedIn) => {
19
19
  let pageTargeting = {};
20
20
  try {
21
21
  pageTargeting = buildPageTargeting({
22
22
  adFree: false,
23
23
  clientSideParticipations,
24
24
  consentState: consentState,
25
+ isSignedIn: isSignedIn,
25
26
  });
26
27
  }
27
28
  catch (e) {
@@ -39,8 +40,8 @@ const mergeCustomParamsWithTargeting = (customParams, consentState, clientSidePa
39
40
  };
40
41
  return mergedCustomParams;
41
42
  };
42
- const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, customParams, }) => {
43
- const mergedCustomParams = mergeCustomParamsWithTargeting(customParams, consentState, clientSideParticipations);
43
+ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, customParams, isSignedIn, }) => {
44
+ const mergedCustomParams = mergeCustomParamsWithTargeting(customParams, consentState, clientSideParticipations, isSignedIn);
44
45
  const queryParams = {
45
46
  iu: adUnit,
46
47
  tfcd: '0',
@@ -53,6 +54,8 @@ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, cust
53
54
  impl: 's',
54
55
  vad_type: 'linear',
55
56
  vpos: 'preroll',
57
+ plcmt: '1',
58
+ description_url: encodeURIComponent(`${window.guardian.config.page.host}/${window.guardian.config.page.pageId}`),
56
59
  /**
57
60
  * cust_params string is encoded
58
61
  * cust_params values are also encoded so they will get double encoded
@@ -64,7 +67,7 @@ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, cust
64
67
  for (const [k, v] of Object.entries(queryParams)) {
65
68
  queryParamsArray.push(`${k}=${v}`);
66
69
  }
67
- return ('https://pubads.g.doubleclick.net/gampad/ads?' +
70
+ return ('https://securepubads.g.doubleclick.net/gampad/ads?' +
68
71
  queryParamsArray.join('&'));
69
72
  };
70
73
  export { buildImaAdTagUrl };