diff --git a/.changeset/popular-trees-brake.md b/.changeset/popular-trees-brake.md
new file mode 100644
index 000000000..6055bd4f4
--- /dev/null
+++ b/.changeset/popular-trees-brake.md
@@ -0,0 +1,5 @@
+---
+'@guardian/libs': minor
+---
+
+Test for Consent or Pay
diff --git a/apps/github-pages/src/components/CmpTest.svelte b/apps/github-pages/src/components/CmpTest.svelte
index 2186fce56..0dca6750a 100644
--- a/apps/github-pages/src/components/CmpTest.svelte
+++ b/apps/github-pages/src/components/CmpTest.svelte
@@ -3,6 +3,11 @@
import { cmp, onConsentChange, log } from '@guardian/libs';
import { onMount } from 'svelte';
+
+ let subscribed = window.location.search.includes('subscribed');
+ let isFeatureFlagEnabled = window.location.search.includes('CMP_COP');
+ // localStorage.setItem('subscribed', window.location.search.includes('subscribed'));
+
switch (window.location.hash) {
case '#tcfv2':
localStorage.setItem('framework', JSON.stringify('tcfv2'));
@@ -37,6 +42,13 @@
log('cmp', event);
}
+ let rejectAllFunc = () => {
+ cmp.rejectAll().then(() => {
+ logEvent({ title: 'rejectAll'});
+ // window.location.reload();
+ });
+ };
+
let clearPreferences = () => {
// clear local storage
// https://documentation.sourcepoint.com/web-implementation/general/cookies-and-local-storage#cmp-local-storage
@@ -60,6 +72,23 @@
clearPreferences();
};
+ const toggleSubscribed = () => {
+ subscribed = !subscribed;
+ toggleQueryParams('subscribed');
+ localStorage.setItem('subscribed', JSON.stringify(subscribed));
+ };
+
+ const toggleQueryParams = (param) => {
+ let queryParams = new URLSearchParams(window.location.search);
+ queryParams.has(param) ? queryParams.delete(param) : queryParams.append(param, '');
+ window.location.search = queryParams.toString();
+ };
+
+ const toggleIsFeatureFlagEnabled = () => {
+ isFeatureFlagEnabled = !isFeatureFlagEnabled;
+ toggleQueryParams('CMP_COP');
+ };
+
$: consentState = {};
$: eventsList = [];
@@ -91,10 +120,7 @@
}
// do this loads to make sure that doesn't break things
- cmp.init({ country });
- cmp.init({ country });
- cmp.init({ country });
- cmp.init({ country });
+ cmp.init({ country, subscribed: subscribed ?? false });
});
@@ -104,6 +130,7 @@
>open privacy manager
+
+
+
+
diff --git a/libs/@guardian/libs/src/consent-management-platform/cmp.ts b/libs/@guardian/libs/src/consent-management-platform/cmp.ts
index 2b4faba55..99fb79905 100644
--- a/libs/@guardian/libs/src/consent-management-platform/cmp.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/cmp.ts
@@ -16,9 +16,13 @@ import type {
WillShowPrivacyMessage,
} from './types';
-const init = (framework: ConsentFramework, pubData?: PubData): void => {
+const init = (
+ framework: ConsentFramework,
+ subscribed: boolean,
+ pubData?: PubData,
+): void => {
mark('cmp-init');
- initSourcepoint(framework, pubData);
+ initSourcepoint(framework, pubData, subscribed);
};
const willShowPrivacyMessage: WillShowPrivacyMessage = () =>
diff --git a/libs/@guardian/libs/src/consent-management-platform/index.test.ts b/libs/@guardian/libs/src/consent-management-platform/index.test.ts
index 4b213e55d..a214ac6bd 100644
--- a/libs/@guardian/libs/src/consent-management-platform/index.test.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/index.test.ts
@@ -23,8 +23,8 @@ describe('cmp.init', () => {
it('does nothing if CMP is disabled', () => {
disable();
- cmp.init({ country: 'GB' });
- cmp.init({ country: 'US' });
+ cmp.init({ country: 'GB', subscribed: true });
+ cmp.init({ country: 'US', subscribed: true });
expect(CMP.init).not.toHaveBeenCalled();
@@ -33,22 +33,22 @@ describe('cmp.init', () => {
it('requires country to be set', () => {
expect(() => {
- cmp.init({ pubData: {} });
+ cmp.init({ subscribed: true, pubData: {} });
}).toThrow('required');
});
it('initializes CMP when in the US', () => {
- cmp.init({ country: 'US' });
+ cmp.init({ country: 'US', subscribed: true });
expect(CMP.init).toHaveBeenCalledTimes(1);
});
it('initializes CMP when in Australia', () => {
- cmp.init({ country: 'AU' });
+ cmp.init({ country: 'AU', subscribed: true });
expect(CMP.init).toHaveBeenCalledTimes(1);
});
it('initializes TCF when neither in the US or Australia', () => {
- cmp.init({ country: 'GB' });
+ cmp.init({ country: 'GB', subscribed: true });
expect(CMP.init).toHaveBeenCalledTimes(1);
});
});
@@ -56,10 +56,10 @@ describe('cmp.init', () => {
// *************** START commercial.dcr.js hotfix ***************
describe('hotfix cmp.init', () => {
it('only initialises once per page', () => {
- cmp.init({ country: 'GB' });
- cmp.init({ country: 'GB' });
- cmp.init({ country: 'GB' });
- cmp.init({ country: 'GB' });
+ cmp.init({ country: 'GB', subscribed: true });
+ cmp.init({ country: 'GB', subscribed: true });
+ cmp.init({ country: 'GB', subscribed: true });
+ cmp.init({ country: 'GB', subscribed: true });
expect(CMP.init).toHaveBeenCalledTimes(1);
expect(window.guCmpHotFix.initialised).toBe(true);
});
@@ -68,7 +68,7 @@ describe('hotfix cmp.init', () => {
const consoleWarn = jest
.spyOn(global.console, 'warn')
.mockImplementation(() => undefined);
- cmp.init({ country: 'GB' });
+ cmp.init({ country: 'GB', subscribed: true });
const currentVersion = window.guCmpHotFix.cmp?.version;
const mockedVersion = 'X.X.X-mock';
@@ -106,6 +106,7 @@ describe('hotfix cmp.init', () => {
willShowPrivacyMessage: () => new Promise(() => true),
willShowPrivacyMessageSync: () => true,
hasInitialised: () => true,
+ rejectAll: () => new Promise(() => undefined),
showPrivacyManager: () => {
console.warn('This is a dummy for showPrivacyManager');
},
diff --git a/libs/@guardian/libs/src/consent-management-platform/index.ts b/libs/@guardian/libs/src/consent-management-platform/index.ts
index 96c5eab68..f2dfd12bb 100644
--- a/libs/@guardian/libs/src/consent-management-platform/index.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/index.ts
@@ -6,6 +6,7 @@ import { getConsentFor as clientGetConsentFor } from './getConsentFor';
import { getFramework } from './getFramework';
import { onConsent as clientOnConsent } from './onConsent';
import { onConsentChange as clientOnConsentChange } from './onConsentChange';
+import { rejectAll as clientRejectAll } from './rejectAll';
import {
isServerSide,
cmp as serverCmp,
@@ -33,7 +34,7 @@ const initialised = new Promise((resolve) => {
resolveInitialised = resolve;
});
-const init: InitCMP = ({ pubData, country }) => {
+const init: InitCMP = ({ pubData, country, subscribed = true }) => {
if (isDisabled() || isServerSide) {
return;
}
@@ -61,7 +62,7 @@ const init: InitCMP = ({ pubData, country }) => {
const framework = getFramework(country);
- UnifiedCMP.init(framework, pubData ?? {});
+ UnifiedCMP.init(framework, subscribed, pubData ?? {});
void UnifiedCMP.willShowPrivacyMessage().then((willShowValue) => {
_willShowPrivacyMessage = willShowValue;
@@ -92,6 +93,10 @@ const showPrivacyManager = () => {
void initialised.then(UnifiedCMP.showPrivacyManager);
};
+const rejectAll = isServerSide
+ ? clientRejectAll
+ : (window.guCmpHotFix.rejectAll ??= clientRejectAll);
+
export const cmp: CMP = isServerSide
? serverCmp
: (window.guCmpHotFix.cmp ??= {
@@ -100,6 +105,7 @@ export const cmp: CMP = isServerSide
willShowPrivacyMessageSync,
hasInitialised,
showPrivacyManager,
+ rejectAll,
version: version,
// special helper methods for disabling CMP
diff --git a/libs/@guardian/libs/src/consent-management-platform/lib/sourcepointConfig.ts b/libs/@guardian/libs/src/consent-management-platform/lib/sourcepointConfig.ts
index 6dbaab03e..e8b7e5c77 100644
--- a/libs/@guardian/libs/src/consent-management-platform/lib/sourcepointConfig.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/lib/sourcepointConfig.ts
@@ -2,7 +2,8 @@ import { isGuardianDomain } from './domain';
export const ACCOUNT_ID = 1257;
export const PRIVACY_MANAGER_USNAT = 1068329;
-export const PROPERTY_ID = 7417;
+export const PROPERTY_ID = 9398;
+// export const PROPERTY_ID = 7417;
export const PROPERTY_ID_AUSTRALIA = 13348;
export const PRIVACY_MANAGER_TCFV2 = 106842;
export const PRIVACY_MANAGER_AUSTRALIA = 1178486;
diff --git a/libs/@guardian/libs/src/consent-management-platform/rejectAll.ts b/libs/@guardian/libs/src/consent-management-platform/rejectAll.ts
new file mode 100644
index 000000000..f91bca31d
--- /dev/null
+++ b/libs/@guardian/libs/src/consent-management-platform/rejectAll.ts
@@ -0,0 +1,22 @@
+import { getCurrentFramework } from './getCurrentFramework';
+import { invokeCallbacks } from './onConsentChange';
+import { rejectAllForUser } from './tcfv2/api';
+
+const rejectAll = (): Promise =>
+ // Consider jurisdiction/framework and countries.
+ new Promise((resolve, reject) => {
+ console.log('Rejecting all');
+ if (getCurrentFramework() === 'tcfv2') {
+ rejectAllForUser()
+ .then(() => {
+ invokeCallbacks();
+ resolve();
+ })
+ .catch(() => {
+ reject(new Error('Unable to reject all'));
+ });
+ } else {
+ reject(new Error('Framework not supported'));
+ }
+ });
+export { rejectAll };
diff --git a/libs/@guardian/libs/src/consent-management-platform/server.ts b/libs/@guardian/libs/src/consent-management-platform/server.ts
index 912760e1b..6fb1f95f0 100644
--- a/libs/@guardian/libs/src/consent-management-platform/server.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/server.ts
@@ -34,6 +34,7 @@ export const cmp: CMP = {
version: 'n/a',
willShowPrivacyMessage: serverSideWarnAndReturn(Promise.resolve(false)),
willShowPrivacyMessageSync: serverSideWarnAndReturn(false),
+ rejectAll: serverSideWarnAndReturn(Promise.resolve()),
};
export const onConsent = (): ReturnType => {
diff --git a/libs/@guardian/libs/src/consent-management-platform/sourcepoint.ts b/libs/@guardian/libs/src/consent-management-platform/sourcepoint.ts
index d6a30b2e7..dfa04f6d2 100644
--- a/libs/@guardian/libs/src/consent-management-platform/sourcepoint.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/sourcepoint.ts
@@ -30,7 +30,8 @@ const getPropertyHref = (framework: ConsentFramework): Property => {
if (framework == 'aus') {
return 'https://au.theguardian.com';
}
- return isGuardianDomain() ? null : 'https://test.theguardian.com';
+ // return isGuardianDomain() ? null : 'https://test.theguardian.com';
+ return isGuardianDomain() ? null : 'http://ui-dev';
};
const getPropertyId = (framework: ConsentFramework): number => {
@@ -40,7 +41,11 @@ const getPropertyId = (framework: ConsentFramework): number => {
return PROPERTY_ID;
};
-export const init = (framework: ConsentFramework, pubData = {}): void => {
+export const init = (
+ framework: ConsentFramework,
+ pubData = {},
+ subscribed: boolean,
+): void => {
stub(framework);
// make sure nothing else on the page has accidentally
@@ -72,6 +77,8 @@ export const init = (framework: ConsentFramework, pubData = {}): void => {
window.guardian?.config?.tests?.useSourcepointPropertyIdVariant ===
'variant';
+ const isFeatureFlagEnabled = window.location.search.includes('CMP_COP');
+
log('cmp', `framework: ${framework}`);
log('cmp', `frameworkMessageType: ${frameworkMessageType}`);
@@ -82,9 +89,11 @@ export const init = (framework: ConsentFramework, pubData = {}): void => {
baseEndpoint: ENDPOINT,
accountId: ACCOUNT_ID,
propertyHref: getPropertyHref(framework),
+ propertyId: getPropertyId(framework),
targetingParams: {
framework,
},
+ campaignEnv: 'stage',
pubData: { ...pubData, cmpInitTimeUtc: new Date().getTime() },
// ccpa or gdpr object added below
@@ -142,6 +151,18 @@ export const init = (framework: ConsentFramework, pubData = {}): void => {
)
) {
setTimeout(invokeCallbacks, 0);
+
+ if (
+ choiceTypeID === SourcePointChoiceTypes.RejectAll &&
+ message_type === 'gdpr' &&
+ !subscribed &&
+ isFeatureFlagEnabled
+ ) {
+ console.log('User has rejected all');
+ window.location.replace(
+ `https://support.theguardian.com/uk/contribute?redirectUrl=${window.location.href}`,
+ );
+ }
}
},
onPrivacyManagerAction: function (message_type, pmData) {
@@ -198,6 +219,8 @@ export const init = (framework: ConsentFramework, pubData = {}): void => {
window._sp_.config.gdpr = {
targetingParams: {
framework,
+ subscribed,
+ isFeatureFlagEnabled,
},
};
break;
diff --git a/libs/@guardian/libs/src/consent-management-platform/tcfv2/api.ts b/libs/@guardian/libs/src/consent-management-platform/tcfv2/api.ts
index 0b8d8c996..348db36cf 100644
--- a/libs/@guardian/libs/src/consent-management-platform/tcfv2/api.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/tcfv2/api.ts
@@ -6,6 +6,7 @@ type Command =
| 'ping'
| 'addEventListener'
| 'removeEventListener'
+ | 'postRejectAll'
| 'getCustomVendorConsents'; // Sourcepoint addition https://documentation.sourcepoint.com/web-implementation/sourcepoint-gdpr-and-tcf-v2-support/__tcfapi-getcustomvendorconsents-api
const api = (command: Command) =>
@@ -33,3 +34,6 @@ export const getTCData = (): Promise =>
export const getCustomVendorConsents = (): Promise =>
api('getCustomVendorConsents') as Promise;
+
+export const rejectAllForUser = (): Promise =>
+ api('postRejectAll') as Promise;
diff --git a/libs/@guardian/libs/src/consent-management-platform/types/index.ts b/libs/@guardian/libs/src/consent-management-platform/types/index.ts
index 0b5bbb11c..80d95bdf1 100644
--- a/libs/@guardian/libs/src/consent-management-platform/types/index.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/types/index.ts
@@ -12,6 +12,7 @@ export type CMP = {
willShowPrivacyMessageSync: () => boolean;
hasInitialised: () => boolean;
showPrivacyManager: () => void;
+ rejectAll: () => Promise;
version: string;
__isDisabled: () => boolean;
__disable: () => void;
@@ -21,6 +22,7 @@ export type CMP = {
export type InitCMP = (arg0: {
pubData?: PubData;
country?: CountryCode;
+ subscribed?: boolean;
}) => void;
export type OnConsentChange = (
@@ -46,7 +48,11 @@ export interface PubData {
[propName: string]: unknown;
}
export interface SourcepointImplementation {
- init: (framework: ConsentFramework, pubData?: PubData) => void;
+ init: (
+ framework: ConsentFramework,
+ subscribed: boolean,
+ pubData?: PubData,
+ ) => void;
willShowPrivacyMessage: WillShowPrivacyMessage;
showPrivacyManager: () => void;
}
diff --git a/libs/@guardian/libs/src/consent-management-platform/types/window.d.ts b/libs/@guardian/libs/src/consent-management-platform/types/window.d.ts
index 26d1c4d2a..ae050c4ac 100644
--- a/libs/@guardian/libs/src/consent-management-platform/types/window.d.ts
+++ b/libs/@guardian/libs/src/consent-management-platform/types/window.d.ts
@@ -3,6 +3,7 @@ import type { Property } from '../lib/property';
import type { EndPoint } from '../lib/sourcepointConfig';
import type { onConsent } from '../onConsent';
import type { onConsentChange } from '../onConsentChange';
+import type { rejectAll } from '../rejectAll';
import type { AUSData } from './aus';
import type { TCData } from './tcfv2/TCData';
import type { GPPData } from './usnat';
@@ -20,6 +21,7 @@ type GuCmpHotFix = {
onConsent?: typeof onConsent;
onConsentChange?: typeof onConsentChange;
getConsentFor?: typeof getConsentFor;
+ rejectAll?: typeof rejectAll;
};
declare global {
@@ -34,8 +36,10 @@ declare global {
accountId: number;
propertyHref?: Property;
propertyId?: number;
+ campaignEnv: 'prod' | 'stage';
targetingParams: {
framework: ConsentFramework;
+ isExcluded?: boolean;
};
ccpa?: {
targetingParams?: {
@@ -45,6 +49,8 @@ declare global {
gdpr?: {
targetingParams?: {
framework: ConsentFramework;
+ subscribed: boolean;
+ isFeatureFlagEnabled?: boolean;
};
};
usnat?: {