@guardian/commercial-core 5.3.0 → 5.4.1

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.
@@ -1,6 +1,6 @@
1
1
  import type { ConsentState } from '@guardian/consent-management-platform/dist/types';
2
2
  import type { PageTargeting } from './build-page-targeting';
3
- declare const consentlessTargetingKeys: readonly ["ab", "at", "bl", "bp", "br", "cc", "ct", "dcre", "edition", "k", "rp", "s", "se", "sens", "sh", "si", "skinsize", "su", "tn", "url", "urlkw"];
3
+ declare const consentlessTargetingKeys: readonly ["ab", "at", "bl", "bp", "br", "cc", "ct", "dcre", "edition", "k", "rc", "rp", "s", "se", "sens", "sh", "si", "skinsize", "su", "tn", "url", "urlkw"];
4
4
  type ConsentlessTargetingKeys = (typeof consentlessTargetingKeys)[number];
5
5
  type ConsentlessPageTargeting = Partial<Pick<PageTargeting, ConsentlessTargetingKeys>>;
6
6
  /**
@@ -13,6 +13,7 @@ const consentlessTargetingKeys = [
13
13
  'dcre',
14
14
  'edition',
15
15
  'k',
16
+ 'rc',
16
17
  'rp',
17
18
  's',
18
19
  'se',
@@ -23,6 +23,7 @@ type PageTargeting = PartialWithNulls<{
23
23
  pa: TrueOrFalse;
24
24
  permutive: string[];
25
25
  pv: string;
26
+ rc: string;
26
27
  rdp: string;
27
28
  ref: string;
28
29
  rp: 'dotcom-rendering' | 'dotcom-platform';
@@ -29,6 +29,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
29
29
  const { page, isDotcomRendering } = window.guardian.config;
30
30
  const adFreeTargeting = adFree ? { af: 't' } : {};
31
31
  const contentTargeting = (0, content_1.getContentTargeting)({
32
+ webPublicationDate: page.webPublicationDate,
32
33
  eligibleForDCR: isDotcomRendering,
33
34
  path: `/${page.pageId}`,
34
35
  renderingPlatform: isDotcomRendering
@@ -21,6 +21,12 @@ type ContentTargeting = {
21
21
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=11958028
22
22
  */
23
23
  dcre: True | False;
24
+ /**
25
+ * **R**ecently Published **C**ontent - [see on Ad Manager][gam]
26
+ *
27
+ * [gam]: TODO: add URL here once it's been created
28
+ */
29
+ rc: string;
24
30
  /**
25
31
  * Rendering Platform - [see on Ad Manager][gam]
26
32
  *
@@ -65,7 +71,8 @@ type Content = {
65
71
  section: ContentTargeting['s'];
66
72
  sensitive: boolean;
67
73
  videoLength?: number;
74
+ webPublicationDate: number;
68
75
  };
69
- declare const getContentTargeting: ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, }: Content) => ContentTargeting;
76
+ declare const getContentTargeting: ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, webPublicationDate, }: Content) => ContentTargeting;
70
77
  export { getContentTargeting };
71
78
  export type { ContentTargeting };
@@ -28,9 +28,39 @@ const getUrlKeywords = (url) => {
28
28
  .slice(-1)[0];
29
29
  return (0, libs_1.isString)(lastSegment) ? lastSegment.split('-').filter(Boolean) : [];
30
30
  };
31
- const getContentTargeting = ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, }) => {
31
+ // "0" means content < 2 hours old
32
+ // "1" means content between 2 hours and 24 hours old.
33
+ // "2" means content between 24 hours and 3 days old
34
+ // "3" means content between 3 and 7 days old
35
+ // "4" means content between 7 days and 1 month old
36
+ // "5" means content between 1 and 10 months old
37
+ // "6" means content between 10 and 14 months old
38
+ // "7" means content more than 14 months old
39
+ const calculateRecentlyPublishedBucket = (webPublicationDate) => {
40
+ const now = Date.now();
41
+ const hoursSincePublication = (now - webPublicationDate) / 1000 / 60 / 60;
42
+ const daysSincePublication = hoursSincePublication / 24;
43
+ const monthsSincePublication = daysSincePublication / 30; // near enough for our purposes
44
+ if (hoursSincePublication < 2)
45
+ return '0';
46
+ if (hoursSincePublication < 24)
47
+ return '1';
48
+ if (daysSincePublication < 3)
49
+ return '2';
50
+ if (daysSincePublication < 7)
51
+ return '3';
52
+ if (daysSincePublication < 30)
53
+ return '4';
54
+ if (monthsSincePublication < 10)
55
+ return '5';
56
+ if (monthsSincePublication < 14)
57
+ return '6';
58
+ return '7';
59
+ };
60
+ const getContentTargeting = ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, webPublicationDate, }) => {
32
61
  return {
33
62
  dcre: eligibleForDCR ? 't' : 'f',
63
+ rc: calculateRecentlyPublishedBucket(webPublicationDate),
34
64
  rp: renderingPlatform,
35
65
  s: section,
36
66
  sens: sensitive ? 't' : 'f',
@@ -43,6 +43,7 @@ export type GuardianWindowConfig = {
43
43
  section: string;
44
44
  sharedAdTargeting?: Record<string, string | string[]>;
45
45
  videoDuration: number;
46
+ webPublicationDate: number;
46
47
  };
47
48
  tests?: {
48
49
  [key: `${string}Control`]: 'control';
@@ -1,6 +1,6 @@
1
1
  import type { ConsentState } from '@guardian/consent-management-platform/dist/types';
2
2
  import type { PageTargeting } from './build-page-targeting';
3
- declare const consentlessTargetingKeys: readonly ["ab", "at", "bl", "bp", "br", "cc", "ct", "dcre", "edition", "k", "rp", "s", "se", "sens", "sh", "si", "skinsize", "su", "tn", "url", "urlkw"];
3
+ declare const consentlessTargetingKeys: readonly ["ab", "at", "bl", "bp", "br", "cc", "ct", "dcre", "edition", "k", "rc", "rp", "s", "se", "sens", "sh", "si", "skinsize", "su", "tn", "url", "urlkw"];
4
4
  type ConsentlessTargetingKeys = (typeof consentlessTargetingKeys)[number];
5
5
  type ConsentlessPageTargeting = Partial<Pick<PageTargeting, ConsentlessTargetingKeys>>;
6
6
  /**
@@ -10,6 +10,7 @@ const consentlessTargetingKeys = [
10
10
  'dcre',
11
11
  'edition',
12
12
  'k',
13
+ 'rc',
13
14
  'rp',
14
15
  's',
15
16
  'se',
@@ -23,6 +23,7 @@ type PageTargeting = PartialWithNulls<{
23
23
  pa: TrueOrFalse;
24
24
  permutive: string[];
25
25
  pv: string;
26
+ rc: string;
26
27
  rdp: string;
27
28
  ref: string;
28
29
  rp: 'dotcom-rendering' | 'dotcom-platform';
@@ -25,6 +25,7 @@ const buildPageTargeting = ({ adFree, clientSideParticipations, consentState, yo
25
25
  const { page, isDotcomRendering } = window.guardian.config;
26
26
  const adFreeTargeting = adFree ? { af: 't' } : {};
27
27
  const contentTargeting = getContentTargeting({
28
+ webPublicationDate: page.webPublicationDate,
28
29
  eligibleForDCR: isDotcomRendering,
29
30
  path: `/${page.pageId}`,
30
31
  renderingPlatform: isDotcomRendering
@@ -21,6 +21,12 @@ type ContentTargeting = {
21
21
  * [gam]: https://admanager.google.com/59666047#inventory/custom_targeting/detail/custom_key_id=11958028
22
22
  */
23
23
  dcre: True | False;
24
+ /**
25
+ * **R**ecently Published **C**ontent - [see on Ad Manager][gam]
26
+ *
27
+ * [gam]: TODO: add URL here once it's been created
28
+ */
29
+ rc: string;
24
30
  /**
25
31
  * Rendering Platform - [see on Ad Manager][gam]
26
32
  *
@@ -65,7 +71,8 @@ type Content = {
65
71
  section: ContentTargeting['s'];
66
72
  sensitive: boolean;
67
73
  videoLength?: number;
74
+ webPublicationDate: number;
68
75
  };
69
- declare const getContentTargeting: ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, }: Content) => ContentTargeting;
76
+ declare const getContentTargeting: ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, webPublicationDate, }: Content) => ContentTargeting;
70
77
  export { getContentTargeting };
71
78
  export type { ContentTargeting };
@@ -25,9 +25,39 @@ const getUrlKeywords = (url) => {
25
25
  .slice(-1)[0];
26
26
  return isString(lastSegment) ? lastSegment.split('-').filter(Boolean) : [];
27
27
  };
28
- const getContentTargeting = ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, }) => {
28
+ // "0" means content < 2 hours old
29
+ // "1" means content between 2 hours and 24 hours old.
30
+ // "2" means content between 24 hours and 3 days old
31
+ // "3" means content between 3 and 7 days old
32
+ // "4" means content between 7 days and 1 month old
33
+ // "5" means content between 1 and 10 months old
34
+ // "6" means content between 10 and 14 months old
35
+ // "7" means content more than 14 months old
36
+ const calculateRecentlyPublishedBucket = (webPublicationDate) => {
37
+ const now = Date.now();
38
+ const hoursSincePublication = (now - webPublicationDate) / 1000 / 60 / 60;
39
+ const daysSincePublication = hoursSincePublication / 24;
40
+ const monthsSincePublication = daysSincePublication / 30; // near enough for our purposes
41
+ if (hoursSincePublication < 2)
42
+ return '0';
43
+ if (hoursSincePublication < 24)
44
+ return '1';
45
+ if (daysSincePublication < 3)
46
+ return '2';
47
+ if (daysSincePublication < 7)
48
+ return '3';
49
+ if (daysSincePublication < 30)
50
+ return '4';
51
+ if (monthsSincePublication < 10)
52
+ return '5';
53
+ if (monthsSincePublication < 14)
54
+ return '6';
55
+ return '7';
56
+ };
57
+ const getContentTargeting = ({ eligibleForDCR, path, renderingPlatform, section, sensitive, videoLength, webPublicationDate, }) => {
29
58
  return {
30
59
  dcre: eligibleForDCR ? 't' : 'f',
60
+ rc: calculateRecentlyPublishedBucket(webPublicationDate),
31
61
  rp: renderingPlatform,
32
62
  s: section,
33
63
  sens: sensitive ? 't' : 'f',
@@ -43,6 +43,7 @@ export type GuardianWindowConfig = {
43
43
  section: string;
44
44
  sharedAdTargeting?: Record<string, string | string[]>;
45
45
  videoDuration: number;
46
+ webPublicationDate: number;
46
47
  };
47
48
  tests?: {
48
49
  [key: `${string}Control`]: 'control';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guardian/commercial-core",
3
- "version": "5.3.0",
3
+ "version": "5.4.1",
4
4
  "description": "Guardian advertising business logic",
5
5
  "homepage": "https://github.com/guardian/commercial-core#readme",
6
6
  "bugs": {
@@ -49,7 +49,7 @@
49
49
  "@semantic-release/github": "^8.0.2",
50
50
  "@types/google.analytics": "^0.0.42",
51
51
  "@types/googletag": "^3.0.1",
52
- "@types/jest": "^27.0.3",
52
+ "@types/jest": "^29.0.3",
53
53
  "@types/node": "^18.11.9",
54
54
  "@typescript-eslint/eslint-plugin": "^5.5.0",
55
55
  "@typescript-eslint/parser": "^5.5.0",
@@ -63,7 +63,7 @@
63
63
  "eslint-plugin-jest": "^27.2.1",
64
64
  "eslint-plugin-prettier": "^4.0.0",
65
65
  "husky": "^8.0.1",
66
- "jest": "^27.4.1",
66
+ "jest": "^29.4.1",
67
67
  "lint-staged": "^13.0.3",
68
68
  "mockdate": "^3.0.5",
69
69
  "npm-run-all": "^4.1.5",
@@ -74,12 +74,12 @@
74
74
  "tslib": "^2.4.0",
75
75
  "typescript": "^4.5.2"
76
76
  },
77
+ "publishConfig": {
78
+ "access": "public"
79
+ },
77
80
  "peerDependencies": {
78
81
  "@guardian/ab-core": "^2.0.0",
79
82
  "@guardian/consent-management-platform": "^11.0.0",
80
83
  "@guardian/libs": "^10.0.0"
81
- },
82
- "publishConfig": {
83
- "access": "public"
84
84
  }
85
85
  }