@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
@@ -11,6 +11,10 @@ type TimedEvent = {
11
11
  name: string;
12
12
  ts: number;
13
13
  };
14
+ type DurationEvent = {
15
+ name: string;
16
+ duration: number;
17
+ };
14
18
  type EventProperties = {
15
19
  type?: ConnectionType;
16
20
  downlink?: number;
@@ -20,6 +24,7 @@ declare enum Endpoints {
20
24
  CODE = "//performance-events.code.dev-guardianapis.com/commercial-metrics",
21
25
  PROD = "//performance-events.guardianapis.com/commercial-metrics"
22
26
  }
27
+ declare const checkConsent: () => Promise<boolean>;
23
28
  /**
24
29
  * A method to asynchronously send metrics after initialization.
25
30
  */
@@ -33,6 +38,7 @@ interface InitCommercialMetricsArgs {
33
38
  }
34
39
  /**
35
40
  * A method to initialise metrics.
41
+ * Note: this is initialised in the frontend/DCR bundles, not the commercial bundle.
36
42
  * @param init.pageViewId - identifies the page view. Usually available on `guardian.config.ophan.pageViewId`. Defaults to `null`
37
43
  * @param init.browserId - identifies the browser. Usually available via `getCookie({ name: 'bwid' })`. Defaults to `null`
38
44
  * @param init.isDev - used to determine whether to use CODE or PROD endpoints.
@@ -44,9 +50,9 @@ export declare const _: {
44
50
  Endpoints: typeof Endpoints;
45
51
  setEndpoint: (isDev: boolean) => Endpoints;
46
52
  mapEventTimerPropertiesToString: (properties: Array<[string, string | number]>) => Property[];
47
- roundTimeStamp: (events: TimedEvent[]) => Metric[];
53
+ roundTimeStamp: (events: TimedEvent[], measures: DurationEvent[]) => Metric[];
48
54
  transformToObjectEntries: (eventTimerProperties: EventProperties) => Array<[string, string | number | undefined]>;
49
55
  reset: () => void;
50
56
  };
51
57
  export type { Property, TimedEvent, Metric };
52
- export { bypassCommercialMetricsSampling, initCommercialMetrics };
58
+ export { bypassCommercialMetricsSampling, initCommercialMetrics, checkConsent };
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initCommercialMetrics = exports.bypassCommercialMetricsSampling = exports._ = void 0;
4
- const consent_management_platform_1 = require("@guardian/consent-management-platform");
3
+ exports.checkConsent = exports._ = void 0;
4
+ exports.bypassCommercialMetricsSampling = bypassCommercialMetricsSampling;
5
+ exports.initCommercialMetrics = initCommercialMetrics;
5
6
  const libs_1 = require("@guardian/libs");
6
7
  const event_timer_1 = require("./event-timer");
7
8
  var Endpoints;
@@ -18,7 +19,6 @@ let commercialMetricsPayload = {
18
19
  };
19
20
  let devProperties = [];
20
21
  let adBlockerProperties = [];
21
- let initialised = false;
22
22
  let endpoint;
23
23
  const setEndpoint = (isDev) => (endpoint = isDev ? Endpoints.CODE : Endpoints.PROD);
24
24
  const setDevProperties = (isDev) => (devProperties = isDev
@@ -45,15 +45,26 @@ const mapEventTimerPropertiesToString = (properties) => {
45
45
  value: String(value),
46
46
  }));
47
47
  };
48
- const roundTimeStamp = (events) => {
49
- return events.map(({ name, ts }) => ({
48
+ const roundTimeStamp = (events, measures) => {
49
+ const roundedEvents = events.map(({ name, ts }) => ({
50
50
  name,
51
51
  value: Math.ceil(ts),
52
52
  }));
53
+ const roundedMeasures = measures.map(({ name, duration }) => ({
54
+ name,
55
+ value: Math.ceil(duration),
56
+ }));
57
+ return [...roundedEvents, ...roundedMeasures];
53
58
  };
54
59
  function sendMetrics() {
55
60
  (0, libs_1.log)('commercial', 'About to send commercial metrics', commercialMetricsPayload);
56
- return navigator.sendBeacon(endpoint, JSON.stringify(commercialMetricsPayload));
61
+ void fetch(endpoint, {
62
+ method: 'POST',
63
+ body: JSON.stringify(commercialMetricsPayload),
64
+ keepalive: true,
65
+ cache: 'no-store',
66
+ mode: 'no-cors',
67
+ });
57
68
  }
58
69
  /**
59
70
  * Gather how many times the user has experienced the “offline” event
@@ -72,6 +83,15 @@ const getOfflineCount = () => typeof window.guardian.offlineCount === 'number'
72
83
  },
73
84
  ]
74
85
  : [];
86
+ /**
87
+ * Measures added with @guardian/libs’s `startPerformanceMeasure`
88
+ *
89
+ * Allows for more granular monitoring of web page performance.
90
+ */
91
+ const getPerformanceMeasures = (...teams) => (0, libs_1.getMeasures)(teams).map(({ detail: { subscription, name, action }, duration }) => ({
92
+ name: [subscription, name, action].filter(libs_1.isNonNullable).join('_'),
93
+ value: duration,
94
+ }));
75
95
  function gatherMetricsOnPageUnload() {
76
96
  // Assemble commercial properties and metrics
77
97
  const eventTimer = event_timer_1.EventTimer.get();
@@ -82,20 +102,24 @@ function gatherMetricsOnPageUnload() {
82
102
  .concat(devProperties)
83
103
  .concat(adBlockerProperties);
84
104
  commercialMetricsPayload.properties = properties;
85
- const metrics = roundTimeStamp(eventTimer.events).concat(getOfflineCount());
105
+ const metrics = roundTimeStamp(eventTimer.marks, eventTimer.measures)
106
+ .concat(getOfflineCount())
107
+ .concat(getPerformanceMeasures('dotcom'));
86
108
  commercialMetricsPayload.metrics = metrics;
87
109
  sendMetrics();
88
110
  }
89
111
  const listener = (e) => {
90
- switch (e.type) {
91
- case 'visibilitychange':
92
- if (document.visibilityState === 'hidden') {
112
+ if (window.guardian.config.shouldSendCommercialMetrics) {
113
+ switch (e.type) {
114
+ case 'visibilitychange':
115
+ if (document.visibilityState === 'hidden') {
116
+ gatherMetricsOnPageUnload();
117
+ }
118
+ return;
119
+ case 'pagehide':
93
120
  gatherMetricsOnPageUnload();
94
- }
95
- return;
96
- case 'pagehide':
97
- gatherMetricsOnPageUnload();
98
- return;
121
+ return;
122
+ }
99
123
  }
100
124
  };
101
125
  const addVisibilityListeners = () => {
@@ -105,7 +129,7 @@ const addVisibilityListeners = () => {
105
129
  window.addEventListener('pagehide', listener, { once: true });
106
130
  };
107
131
  const checkConsent = async () => {
108
- const consentState = await (0, consent_management_platform_1.onConsent)();
132
+ const consentState = await (0, libs_1.onConsent)();
109
133
  if (consentState.tcfv2) {
110
134
  // TCFv2 mode - check for consent
111
135
  const consents = consentState.tcfv2.consents;
@@ -115,25 +139,26 @@ const checkConsent = async () => {
115
139
  // non-TCFv2 mode - don't check for consent
116
140
  return true;
117
141
  };
142
+ exports.checkConsent = checkConsent;
118
143
  /**
119
144
  * A method to asynchronously send metrics after initialization.
120
145
  */
121
146
  async function bypassCommercialMetricsSampling() {
122
- if (!initialised) {
147
+ if (!window.guardian.config.commercialMetricsInitialised) {
123
148
  console.warn('initCommercialMetrics not yet initialised');
124
149
  return;
125
150
  }
126
151
  const consented = await checkConsent();
127
152
  if (consented) {
128
- addVisibilityListeners();
153
+ window.guardian.config.shouldSendCommercialMetrics = true;
129
154
  }
130
155
  else {
131
156
  (0, libs_1.log)('commercial', "Metrics won't be sent because consent wasn't given");
132
157
  }
133
158
  }
134
- exports.bypassCommercialMetricsSampling = bypassCommercialMetricsSampling;
135
159
  /**
136
160
  * A method to initialise metrics.
161
+ * Note: this is initialised in the frontend/DCR bundles, not the commercial bundle.
137
162
  * @param init.pageViewId - identifies the page view. Usually available on `guardian.config.ophan.pageViewId`. Defaults to `null`
138
163
  * @param init.browserId - identifies the browser. Usually available via `getCookie({ name: 'bwid' })`. Defaults to `null`
139
164
  * @param init.isDev - used to determine whether to use CODE or PROD endpoints.
@@ -146,24 +171,22 @@ async function initCommercialMetrics({ pageViewId, browserId, isDev, adBlockerIn
146
171
  setEndpoint(isDev);
147
172
  setDevProperties(isDev);
148
173
  setAdBlockerProperties(adBlockerInUse);
149
- if (initialised) {
174
+ addVisibilityListeners();
175
+ if (window.guardian.config.commercialMetricsInitialised) {
150
176
  return false;
151
177
  }
152
- initialised = true;
178
+ window.guardian.config.commercialMetricsInitialised = true;
153
179
  const userIsInSamplingGroup = Math.random() <= sampling;
154
180
  if (isDev || userIsInSamplingGroup) {
155
181
  const consented = await checkConsent();
156
182
  if (consented) {
157
- addVisibilityListeners();
183
+ window.guardian.config.shouldSendCommercialMetrics = true;
158
184
  return true;
159
185
  }
160
- else {
161
- (0, libs_1.log)('commercial', "Metrics won't be sent because consent wasn't given");
162
- }
186
+ (0, libs_1.log)('commercial', "Metrics won't be sent because consent wasn't given");
163
187
  }
164
188
  return false;
165
189
  }
166
- exports.initCommercialMetrics = initCommercialMetrics;
167
190
  exports._ = {
168
191
  Endpoints,
169
192
  setEndpoint,
@@ -171,7 +194,8 @@ exports._ = {
171
194
  roundTimeStamp,
172
195
  transformToObjectEntries,
173
196
  reset: () => {
174
- initialised = false;
197
+ window.guardian.config.commercialMetricsInitialised = false;
198
+ window.guardian.config.shouldSendCommercialMetrics = false;
175
199
  commercialMetricsPayload = {
176
200
  page_view_id: undefined,
177
201
  browser_id: undefined,
@@ -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,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.filterValues = exports.buildPageTargeting = void 0;
4
- const consent_management_platform_1 = require("@guardian/consent-management-platform");
5
4
  const libs_1 = require("@guardian/libs");
6
- const get_locale_1 = require("../lib/get-locale");
5
+ const event_timer_1 = require("../event-timer");
6
+ const get_locale_1 = require("../geo/get-locale");
7
7
  const content_1 = require("./content");
8
8
  const personalised_1 = require("./personalised");
9
9
  const session_1 = require("./session");
@@ -25,7 +25,30 @@ const filterValues = (pageTargets) => {
25
25
  return filtered;
26
26
  };
27
27
  exports.filterValues = filterValues;
28
- const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, youtube = false, }) => {
28
+ const lastPerformanceEntryIsNavigationType = () => {
29
+ if (!(0, event_timer_1.supportsPerformanceAPI)()) {
30
+ return false;
31
+ }
32
+ const navigationEvents = performance.getEntriesByType('navigation');
33
+ const lastNavigationEvent = navigationEvents[navigationEvents.length - 1];
34
+ // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType#navigation
35
+ return lastNavigationEvent?.entryType === 'navigation';
36
+ };
37
+ const referrerMatchesHost = (referrer) => {
38
+ if (!referrer) {
39
+ return false;
40
+ }
41
+ const referrerUrl = new URL(referrer);
42
+ return referrerUrl.hostname === window.location.hostname;
43
+ };
44
+ // A consentless friendly way of determining if this is the users first visit to the page
45
+ const isFirstVisit = (referrer) => {
46
+ if ((0, event_timer_1.supportsPerformanceAPI)() && !lastPerformanceEntryIsNavigationType()) {
47
+ return false;
48
+ }
49
+ return !referrerMatchesHost(referrer);
50
+ };
51
+ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, isSignedIn = false, youtube = false, }) => {
29
52
  const { page, isDotcomRendering } = window.guardian.config;
30
53
  const adFreeTargeting = adFree ? { af: 't' } : {};
31
54
  const sharedAdTargeting = page.sharedAdTargeting
@@ -43,17 +66,17 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
43
66
  videoLength: page.videoDuration,
44
67
  keywords: sharedAdTargeting.k ?? [],
45
68
  });
46
- const getReferrer = () => document.referrer || '';
69
+ const referrer = document.referrer || '';
47
70
  const sessionTargeting = (0, session_1.getSessionTargeting)({
48
71
  adTest: (0, libs_1.getCookie)({ name: 'adtest', shouldMemoize: true }),
49
72
  countryCode: (0, get_locale_1.getLocale)(),
50
- isSignedIn: !!(0, libs_1.getCookie)({ name: 'GU_U' }),
73
+ isSignedIn,
51
74
  pageViewId: window.guardian.config.ophan.pageViewId,
52
75
  participations: {
53
76
  clientSideParticipations,
54
77
  serverSideParticipations: window.guardian.config.tests ?? {},
55
78
  },
56
- referrer: getReferrer(),
79
+ referrer,
57
80
  });
58
81
  const getViewport = () => {
59
82
  return {
@@ -63,12 +86,16 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
63
86
  };
64
87
  const viewportTargeting = (0, viewport_1.getViewportTargeting)({
65
88
  viewPortWidth: getViewport().width,
66
- cmpBannerWillShow: !consent_management_platform_1.cmp.hasInitialised() || consent_management_platform_1.cmp.willShowPrivacyMessageSync(),
89
+ cmpBannerWillShow: !libs_1.cmp.hasInitialised() || libs_1.cmp.willShowPrivacyMessageSync(),
67
90
  });
68
91
  const personalisedTargeting = (0, personalised_1.getPersonalisedTargeting)({
69
92
  state: consentState,
70
93
  youtube,
71
94
  });
95
+ const consentlessTargeting = {};
96
+ if (!(0, libs_1.getConsentFor)('googletag', consentState)) {
97
+ consentlessTargeting.firstvisit = isFirstVisit(referrer) ? 't' : 'f';
98
+ }
72
99
  const pageTargets = {
73
100
  ...personalisedTargeting,
74
101
  ...sharedAdTargeting,
@@ -76,6 +103,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
76
103
  ...contentTargeting,
77
104
  ...sessionTargeting,
78
105
  ...viewportTargeting,
106
+ ...consentlessTargeting,
79
107
  };
80
108
  // filter !(string | string[]) and empty values
81
109
  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
@@ -4,7 +4,7 @@ exports.getContentTargeting = void 0;
4
4
  const libs_1 = require("@guardian/libs");
5
5
  /* -- Types -- */
6
6
  const videoLengths = [
7
- '25',
7
+ '25', // TODO: confirm this is a real value
8
8
  '30',
9
9
  '60',
10
10
  '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"];
@@ -38,8 +38,8 @@ const getRawWithConsent = (key, state) => {
38
38
  if (state.tcfv2.consents['1'])
39
39
  return libs_1.storage.local.getRaw(key);
40
40
  }
41
- if (state.ccpa) {
42
- if (!state.ccpa.doNotSell)
41
+ if (state.usnat) {
42
+ if (!state.usnat.doNotSell)
43
43
  return libs_1.storage.local.getRaw(key);
44
44
  }
45
45
  if (state.aus) {
@@ -82,7 +82,7 @@ const getCMPTargeting = (state) => {
82
82
  rdp: 'na',
83
83
  };
84
84
  }
85
- if (state.ccpa) {
85
+ if (state.usnat) {
86
86
  return {
87
87
  consent_tcfv2: 'na',
88
88
  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 };
@@ -2,36 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSharedTargeting = exports._ = void 0;
4
4
  const pick_targeting_values_1 = require("./pick-targeting-values");
5
- /* -- Types -- */
6
- const brands = {
7
- Foundation: 'f',
8
- Paid: 'p',
9
- Sponsored: 's',
10
- };
11
- const contentTypes = [
12
- 'article',
13
- 'audio',
14
- 'crossword',
15
- 'gallery',
16
- 'interactive',
17
- 'liveblog',
18
- 'network-front',
19
- 'section',
20
- 'tag',
21
- 'video',
22
- ];
23
- const editions = {
24
- UnitedKingdom: 'uk',
25
- UnitedStates: 'us',
26
- Australia: 'au',
27
- International: 'int',
28
- };
29
- const platforms = {
30
- R2: 'r2',
31
- NextGen: 'ng',
32
- MobileApp: 'app',
33
- AcceleratedMobilePages: 'amp',
34
- };
35
5
  const surges = {
36
6
  0: '0',
37
7
  50: '5',
@@ -0,0 +1,2 @@
1
+ declare const isEligibleForTeads: (slotId: string) => boolean;
2
+ export { isEligibleForTeads };
@@ -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,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>>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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 };
@@ -18,13 +18,14 @@ const encodeCustomParams = (params) => {
18
18
  .join('&');
19
19
  return encodedParams;
20
20
  };
21
- const mergeCustomParamsWithTargeting = (customParams, consentState, clientSideParticipations) => {
21
+ const mergeCustomParamsWithTargeting = (customParams, consentState, clientSideParticipations, isSignedIn) => {
22
22
  let pageTargeting = {};
23
23
  try {
24
24
  pageTargeting = (0, build_page_targeting_1.buildPageTargeting)({
25
25
  adFree: false,
26
26
  clientSideParticipations,
27
27
  consentState: consentState,
28
+ isSignedIn: isSignedIn,
28
29
  });
29
30
  }
30
31
  catch (e) {
@@ -42,8 +43,8 @@ const mergeCustomParamsWithTargeting = (customParams, consentState, clientSidePa
42
43
  };
43
44
  return mergedCustomParams;
44
45
  };
45
- const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, customParams, }) => {
46
- const mergedCustomParams = mergeCustomParamsWithTargeting(customParams, consentState, clientSideParticipations);
46
+ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, customParams, isSignedIn, }) => {
47
+ const mergedCustomParams = mergeCustomParamsWithTargeting(customParams, consentState, clientSideParticipations, isSignedIn);
47
48
  const queryParams = {
48
49
  iu: adUnit,
49
50
  tfcd: '0',
@@ -56,6 +57,8 @@ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, cust
56
57
  impl: 's',
57
58
  vad_type: 'linear',
58
59
  vpos: 'preroll',
60
+ plcmt: '1',
61
+ description_url: encodeURIComponent(`${window.guardian.config.page.host}/${window.guardian.config.page.pageId}`),
59
62
  /**
60
63
  * cust_params string is encoded
61
64
  * cust_params values are also encoded so they will get double encoded
@@ -67,7 +70,7 @@ const buildImaAdTagUrl = ({ adUnit, clientSideParticipations, consentState, cust
67
70
  for (const [k, v] of Object.entries(queryParams)) {
68
71
  queryParamsArray.push(`${k}=${v}`);
69
72
  }
70
- return ('https://pubads.g.doubleclick.net/gampad/ads?' +
73
+ return ('https://securepubads.g.doubleclick.net/gampad/ads?' +
71
74
  queryParamsArray.join('&'));
72
75
  };
73
76
  exports.buildImaAdTagUrl = buildImaAdTagUrl;