@financial-times/cmp-client 0.0.0-beta.1 → 0.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +259 -26
- package/dist/index.js +259 -26
- package/dist/src/client.d.ts +1 -1
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/lib/debug.d.ts.map +1 -1
- package/dist/src/tracking/__tests__/state.test.d.ts +2 -0
- package/dist/src/tracking/__tests__/state.test.d.ts.map +1 -0
- package/dist/src/tracking/constants.d.ts +3 -0
- package/dist/src/tracking/constants.d.ts.map +1 -0
- package/dist/src/tracking/index.d.ts +3 -0
- package/dist/src/tracking/index.d.ts.map +1 -0
- package/dist/src/tracking/state.d.ts +9 -0
- package/dist/src/tracking/state.d.ts.map +1 -0
- package/package.json +4 -2
- package/typings/types.d.ts +38 -1
package/dist/index.cjs
CHANGED
|
@@ -7,13 +7,10 @@ var __publicField = (obj, key, value) => {
|
|
|
7
7
|
};
|
|
8
8
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
9
9
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
10
|
-
const version = "0.0.0-beta.
|
|
10
|
+
const version = "0.0.0-beta.2";
|
|
11
11
|
const events = {
|
|
12
12
|
onMessageChoiceSelect: (...args) => {
|
|
13
13
|
console.log("[debug] onMessageChoiceSelect", args);
|
|
14
|
-
if (choice_type_id == 9) {
|
|
15
|
-
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2030 12:00:00 UTC";
|
|
16
|
-
}
|
|
17
14
|
},
|
|
18
15
|
onMessageReady: (...args) => {
|
|
19
16
|
console.log("[debug] onMessageReady", args);
|
|
@@ -23,9 +20,6 @@ const events = {
|
|
|
23
20
|
},
|
|
24
21
|
onPrivacyManagerAction: (...args) => {
|
|
25
22
|
console.log("[debug] onPrivacyManagerAction", args);
|
|
26
|
-
if (pmData.purposeConsent == "none" && pmData.vendorConsent == "none") {
|
|
27
|
-
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2030 12:00:00 UTC";
|
|
28
|
-
}
|
|
29
23
|
},
|
|
30
24
|
onPMCancel: (...args) => {
|
|
31
25
|
console.log("[debug] onPMCancel", args);
|
|
@@ -2935,6 +2929,212 @@ function consentReadyHandlerFn(props) {
|
|
|
2935
2929
|
document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
|
|
2936
2930
|
};
|
|
2937
2931
|
}
|
|
2932
|
+
let getRandomValues;
|
|
2933
|
+
const rnds8 = new Uint8Array(16);
|
|
2934
|
+
function rng() {
|
|
2935
|
+
if (!getRandomValues) {
|
|
2936
|
+
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
2937
|
+
if (!getRandomValues) {
|
|
2938
|
+
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
return getRandomValues(rnds8);
|
|
2942
|
+
}
|
|
2943
|
+
const byteToHex = [];
|
|
2944
|
+
for (let i = 0; i < 256; ++i) {
|
|
2945
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
2946
|
+
}
|
|
2947
|
+
function unsafeStringify(arr, offset = 0) {
|
|
2948
|
+
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
2949
|
+
}
|
|
2950
|
+
const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
2951
|
+
const native = {
|
|
2952
|
+
randomUUID
|
|
2953
|
+
};
|
|
2954
|
+
function v4(options, buf, offset) {
|
|
2955
|
+
if (native.randomUUID && !buf && !options) {
|
|
2956
|
+
return native.randomUUID();
|
|
2957
|
+
}
|
|
2958
|
+
options = options || {};
|
|
2959
|
+
const rnds = options.random || (options.rng || rng)();
|
|
2960
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
2961
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
2962
|
+
if (buf) {
|
|
2963
|
+
offset = offset || 0;
|
|
2964
|
+
for (let i = 0; i < 16; ++i) {
|
|
2965
|
+
buf[offset + i] = rnds[i];
|
|
2966
|
+
}
|
|
2967
|
+
return buf;
|
|
2968
|
+
}
|
|
2969
|
+
return unsafeStringify(rnds);
|
|
2970
|
+
}
|
|
2971
|
+
const COOKIE_MESSAGE = "cookie-message";
|
|
2972
|
+
const PRIVACY_MANAGER = "manage-cookies";
|
|
2973
|
+
const INITIAL_STATE = Object.freeze({
|
|
2974
|
+
activeComponent: COOKIE_MESSAGE
|
|
2975
|
+
});
|
|
2976
|
+
let privateState = INITIAL_STATE;
|
|
2977
|
+
function isPlainObject(obj) {
|
|
2978
|
+
return typeof obj === "object" && obj !== null && obj.constructor === Object && Object.prototype.toString.call(obj) === "[object Object]";
|
|
2979
|
+
}
|
|
2980
|
+
const getState = () => ({ ...privateState });
|
|
2981
|
+
const setState = (newState) => {
|
|
2982
|
+
if (!isPlainObject(newState)) {
|
|
2983
|
+
console.error("Invalid state changes");
|
|
2984
|
+
return;
|
|
2985
|
+
}
|
|
2986
|
+
privateState = { ...privateState, ...newState };
|
|
2987
|
+
};
|
|
2988
|
+
const ACCEPT_ALL_CHOICE = 11;
|
|
2989
|
+
const MANAGE_PREFS_CHOICE = 12;
|
|
2990
|
+
const REJECT_ALL_CHOICE = 13;
|
|
2991
|
+
const cookieToggleFlags = ["adsDisableInternalCMP", "pwm.cmp", "messageSlotBottom"];
|
|
2992
|
+
function initTracking(context) {
|
|
2993
|
+
const componentId = v4();
|
|
2994
|
+
const flags = extractRelevantFlags(context.flags);
|
|
2995
|
+
window._sp_queue = window._sp_queue ?? [];
|
|
2996
|
+
window._sp_queue.push(() => {
|
|
2997
|
+
var _a2, _b2;
|
|
2998
|
+
for (const [eventId, eventHandler] of Object.entries(trackingEventHandlers)) {
|
|
2999
|
+
(_b2 = (_a2 = window._sp_).addEventListener) == null ? void 0 : _b2.call(_a2, eventId, eventHandler({ ...context, flags, componentId }));
|
|
3000
|
+
}
|
|
3001
|
+
});
|
|
3002
|
+
}
|
|
3003
|
+
function extractRelevantFlags(flags) {
|
|
3004
|
+
const output = {};
|
|
3005
|
+
if (typeof flags === "object") {
|
|
3006
|
+
cookieToggleFlags.forEach((flagName) => {
|
|
3007
|
+
if (Object.prototype.hasOwnProperty.call(flags, flagName)) {
|
|
3008
|
+
output[flagName] = flags[flagName];
|
|
3009
|
+
}
|
|
3010
|
+
});
|
|
3011
|
+
}
|
|
3012
|
+
return output;
|
|
3013
|
+
}
|
|
3014
|
+
function track(payload) {
|
|
3015
|
+
if (!payload)
|
|
3016
|
+
return;
|
|
3017
|
+
const rootEl = document.body;
|
|
3018
|
+
const event = new CustomEvent("oTracking.event", {
|
|
3019
|
+
bubbles: true,
|
|
3020
|
+
cancelable: true,
|
|
3021
|
+
detail: payload.detail
|
|
3022
|
+
});
|
|
3023
|
+
rootEl.dispatchEvent(event);
|
|
3024
|
+
}
|
|
3025
|
+
function dispatchComponentEvent({
|
|
3026
|
+
trackingProps,
|
|
3027
|
+
action,
|
|
3028
|
+
triggerAction,
|
|
3029
|
+
messageType
|
|
3030
|
+
}) {
|
|
3031
|
+
const state = getState();
|
|
3032
|
+
const { componentId, product, app, flags } = trackingProps;
|
|
3033
|
+
const event = {
|
|
3034
|
+
detail: {
|
|
3035
|
+
component: {
|
|
3036
|
+
id: componentId,
|
|
3037
|
+
name: state.activeComponent,
|
|
3038
|
+
type: "overlay",
|
|
3039
|
+
subtype: "cmp",
|
|
3040
|
+
componentContentId: state[messageType]
|
|
3041
|
+
},
|
|
3042
|
+
category: "component",
|
|
3043
|
+
action,
|
|
3044
|
+
...triggerAction && { trigger_action: triggerAction },
|
|
3045
|
+
...product && { product },
|
|
3046
|
+
...app && { app },
|
|
3047
|
+
custom: [
|
|
3048
|
+
{
|
|
3049
|
+
cookie_toggle_flag: flags
|
|
3050
|
+
}
|
|
3051
|
+
]
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
track(event);
|
|
3055
|
+
}
|
|
3056
|
+
const trackingEventHandlers = {
|
|
3057
|
+
onMessageChoiceSelect: (trackingProps) => (messageType, _choiceId, choiceTypeId) => {
|
|
3058
|
+
if (choiceTypeId === ACCEPT_ALL_CHOICE) {
|
|
3059
|
+
dispatchComponentEvent({
|
|
3060
|
+
trackingProps,
|
|
3061
|
+
action: "click",
|
|
3062
|
+
triggerAction: "accept_all",
|
|
3063
|
+
messageType
|
|
3064
|
+
});
|
|
3065
|
+
}
|
|
3066
|
+
if (choiceTypeId === MANAGE_PREFS_CHOICE) {
|
|
3067
|
+
dispatchComponentEvent({
|
|
3068
|
+
trackingProps,
|
|
3069
|
+
action: "click",
|
|
3070
|
+
triggerAction: "manage_cookies",
|
|
3071
|
+
messageType
|
|
3072
|
+
});
|
|
3073
|
+
setState({
|
|
3074
|
+
activeComponent: PRIVACY_MANAGER
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
if (choiceTypeId === REJECT_ALL_CHOICE) {
|
|
3078
|
+
dispatchComponentEvent({
|
|
3079
|
+
trackingProps,
|
|
3080
|
+
action: "click",
|
|
3081
|
+
triggerAction: "reject_all",
|
|
3082
|
+
messageType
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3085
|
+
},
|
|
3086
|
+
onMessageReady: (trackingProps) => (messageType) => {
|
|
3087
|
+
dispatchComponentEvent({
|
|
3088
|
+
trackingProps,
|
|
3089
|
+
action: "view",
|
|
3090
|
+
messageType
|
|
3091
|
+
});
|
|
3092
|
+
},
|
|
3093
|
+
onPrivacyManagerAction: (trackingProps) => (messageType, pmData) => {
|
|
3094
|
+
const { purposeConsent, vendorConsent } = pmData;
|
|
3095
|
+
const isAcceptAll = purposeConsent === "all" && vendorConsent === "all";
|
|
3096
|
+
const isRejectAll = purposeConsent === "none" && vendorConsent === "none";
|
|
3097
|
+
setState({
|
|
3098
|
+
activeComponent: PRIVACY_MANAGER
|
|
3099
|
+
});
|
|
3100
|
+
if (isAcceptAll) {
|
|
3101
|
+
dispatchComponentEvent({
|
|
3102
|
+
trackingProps,
|
|
3103
|
+
action: "click",
|
|
3104
|
+
triggerAction: "accept_all",
|
|
3105
|
+
messageType
|
|
3106
|
+
});
|
|
3107
|
+
} else if (isRejectAll) {
|
|
3108
|
+
dispatchComponentEvent({
|
|
3109
|
+
trackingProps,
|
|
3110
|
+
action: "click",
|
|
3111
|
+
triggerAction: "reject_all",
|
|
3112
|
+
messageType
|
|
3113
|
+
});
|
|
3114
|
+
} else {
|
|
3115
|
+
dispatchComponentEvent({
|
|
3116
|
+
trackingProps,
|
|
3117
|
+
action: "click",
|
|
3118
|
+
triggerAction: "save_and_close",
|
|
3119
|
+
messageType
|
|
3120
|
+
});
|
|
3121
|
+
}
|
|
3122
|
+
},
|
|
3123
|
+
onMessageReceiveData: () => (messageType, data) => {
|
|
3124
|
+
const { messageId } = data;
|
|
3125
|
+
setState({
|
|
3126
|
+
[messageType]: messageId
|
|
3127
|
+
});
|
|
3128
|
+
},
|
|
3129
|
+
onError: (trackingProps) => (messageType, errorCode) => {
|
|
3130
|
+
dispatchComponentEvent({
|
|
3131
|
+
trackingProps,
|
|
3132
|
+
action: "error",
|
|
3133
|
+
triggerAction: errorCode,
|
|
3134
|
+
messageType
|
|
3135
|
+
});
|
|
3136
|
+
}
|
|
3137
|
+
};
|
|
2938
3138
|
async function initSourcepointCmp({
|
|
2939
3139
|
propertyConfig = FT_DOTCOM_PROD,
|
|
2940
3140
|
userId,
|
|
@@ -2942,9 +3142,9 @@ async function initSourcepointCmp({
|
|
|
2942
3142
|
consentProxyHost = FT_CONSENT_PROXY_HOST,
|
|
2943
3143
|
cookieDomain = FT_COOKIE_DOMAIN,
|
|
2944
3144
|
formOfWordsId = SOURCEPOINT_FOW_ID,
|
|
2945
|
-
useConsentStore = true
|
|
3145
|
+
useConsentStore = true,
|
|
3146
|
+
trackingContext = {}
|
|
2946
3147
|
} = {}) {
|
|
2947
|
-
var _a2;
|
|
2948
3148
|
if (!userId && useFTSession) {
|
|
2949
3149
|
try {
|
|
2950
3150
|
const response = await getUuid();
|
|
@@ -2959,32 +3159,65 @@ async function initSourcepointCmp({
|
|
|
2959
3159
|
if (userId) {
|
|
2960
3160
|
propertyConfig.authId = userId;
|
|
2961
3161
|
}
|
|
2962
|
-
if (
|
|
2963
|
-
console.warn(
|
|
3162
|
+
if (propertyConfig.events) {
|
|
3163
|
+
console.warn(
|
|
3164
|
+
"[cmp-client] Passing an events map in the config is not supported and will be ignored. Please use window._sp_.addEventListener() to listen for events"
|
|
3165
|
+
);
|
|
3166
|
+
delete propertyConfig.events;
|
|
2964
3167
|
}
|
|
2965
|
-
const events2 = {
|
|
2966
|
-
...propertyConfig.events ?? {},
|
|
2967
|
-
onConsentReady: consentReadyHandlerFn({
|
|
2968
|
-
userId,
|
|
2969
|
-
consentProxyHost,
|
|
2970
|
-
cookieDomain,
|
|
2971
|
-
formOfWordsId,
|
|
2972
|
-
useConsentStore
|
|
2973
|
-
})
|
|
2974
|
-
};
|
|
2975
3168
|
function getCookie(name) {
|
|
3169
|
+
var _a2, _b2;
|
|
2976
3170
|
const value = `; ${document.cookie}`;
|
|
2977
3171
|
const parts = value.split(`; ${name}=`);
|
|
2978
3172
|
if (parts.length === 2)
|
|
2979
|
-
return parts.pop().split(";").shift();
|
|
3173
|
+
return (_b2 = (_a2 = parts.pop()) == null ? void 0 : _a2.split(";")) == null ? void 0 : _b2.shift();
|
|
2980
3174
|
}
|
|
2981
|
-
propertyConfig
|
|
3175
|
+
propertyConfig = {
|
|
3176
|
+
...propertyConfig,
|
|
2982
3177
|
targetingParams: {
|
|
2983
|
-
|
|
2984
|
-
"cookiew": getCookie("cw")
|
|
3178
|
+
cookiew: getCookie("cw")
|
|
2985
3179
|
}
|
|
2986
3180
|
};
|
|
2987
|
-
bootstrapCmp(
|
|
3181
|
+
bootstrapCmp(propertyConfig);
|
|
3182
|
+
window._sp_queue.push(() => {
|
|
3183
|
+
var _a2, _b2;
|
|
3184
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3185
|
+
_a2,
|
|
3186
|
+
"onConsentReady",
|
|
3187
|
+
consentReadyHandlerFn({
|
|
3188
|
+
userId,
|
|
3189
|
+
consentProxyHost,
|
|
3190
|
+
cookieDomain,
|
|
3191
|
+
formOfWordsId,
|
|
3192
|
+
useConsentStore
|
|
3193
|
+
})
|
|
3194
|
+
);
|
|
3195
|
+
});
|
|
3196
|
+
window._sp_queue.push(() => {
|
|
3197
|
+
var _a2, _b2;
|
|
3198
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3199
|
+
_a2,
|
|
3200
|
+
"onMessageChoiceSelect",
|
|
3201
|
+
(_messageType, _choiceId, choiceTypeId) => {
|
|
3202
|
+
if (choiceTypeId === 9) {
|
|
3203
|
+
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2023 12:00:00 UTC";
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
);
|
|
3207
|
+
});
|
|
3208
|
+
window._sp_queue.push(() => {
|
|
3209
|
+
var _a2, _b2;
|
|
3210
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3211
|
+
_a2,
|
|
3212
|
+
"onPrivacyManagerAction",
|
|
3213
|
+
(_messageType, pmData) => {
|
|
3214
|
+
if (pmData.purposeConsent == "none" && pmData.vendorConsent == "none") {
|
|
3215
|
+
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2023 12:00:00 UTC";
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
);
|
|
3219
|
+
});
|
|
3220
|
+
initTracking(trackingContext);
|
|
2988
3221
|
}
|
|
2989
3222
|
window.FT_CMP_CLIENT_VERSION = version;
|
|
2990
3223
|
exports.debug = debug;
|
package/dist/index.js
CHANGED
|
@@ -5,13 +5,10 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
7
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
|
|
8
|
-
const version = "0.0.0-beta.
|
|
8
|
+
const version = "0.0.0-beta.2";
|
|
9
9
|
const events = {
|
|
10
10
|
onMessageChoiceSelect: (...args) => {
|
|
11
11
|
console.log("[debug] onMessageChoiceSelect", args);
|
|
12
|
-
if (choice_type_id == 9) {
|
|
13
|
-
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2030 12:00:00 UTC";
|
|
14
|
-
}
|
|
15
12
|
},
|
|
16
13
|
onMessageReady: (...args) => {
|
|
17
14
|
console.log("[debug] onMessageReady", args);
|
|
@@ -21,9 +18,6 @@ const events = {
|
|
|
21
18
|
},
|
|
22
19
|
onPrivacyManagerAction: (...args) => {
|
|
23
20
|
console.log("[debug] onPrivacyManagerAction", args);
|
|
24
|
-
if (pmData.purposeConsent == "none" && pmData.vendorConsent == "none") {
|
|
25
|
-
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2030 12:00:00 UTC";
|
|
26
|
-
}
|
|
27
21
|
},
|
|
28
22
|
onPMCancel: (...args) => {
|
|
29
23
|
console.log("[debug] onPMCancel", args);
|
|
@@ -2933,6 +2927,212 @@ function consentReadyHandlerFn(props) {
|
|
|
2933
2927
|
document.dispatchEvent(new CustomEvent("oCookieMessage.act", { bubbles: true }));
|
|
2934
2928
|
};
|
|
2935
2929
|
}
|
|
2930
|
+
let getRandomValues;
|
|
2931
|
+
const rnds8 = new Uint8Array(16);
|
|
2932
|
+
function rng() {
|
|
2933
|
+
if (!getRandomValues) {
|
|
2934
|
+
getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
|
|
2935
|
+
if (!getRandomValues) {
|
|
2936
|
+
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
return getRandomValues(rnds8);
|
|
2940
|
+
}
|
|
2941
|
+
const byteToHex = [];
|
|
2942
|
+
for (let i = 0; i < 256; ++i) {
|
|
2943
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
2944
|
+
}
|
|
2945
|
+
function unsafeStringify(arr, offset = 0) {
|
|
2946
|
+
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
2947
|
+
}
|
|
2948
|
+
const randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
2949
|
+
const native = {
|
|
2950
|
+
randomUUID
|
|
2951
|
+
};
|
|
2952
|
+
function v4(options, buf, offset) {
|
|
2953
|
+
if (native.randomUUID && !buf && !options) {
|
|
2954
|
+
return native.randomUUID();
|
|
2955
|
+
}
|
|
2956
|
+
options = options || {};
|
|
2957
|
+
const rnds = options.random || (options.rng || rng)();
|
|
2958
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
2959
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
2960
|
+
if (buf) {
|
|
2961
|
+
offset = offset || 0;
|
|
2962
|
+
for (let i = 0; i < 16; ++i) {
|
|
2963
|
+
buf[offset + i] = rnds[i];
|
|
2964
|
+
}
|
|
2965
|
+
return buf;
|
|
2966
|
+
}
|
|
2967
|
+
return unsafeStringify(rnds);
|
|
2968
|
+
}
|
|
2969
|
+
const COOKIE_MESSAGE = "cookie-message";
|
|
2970
|
+
const PRIVACY_MANAGER = "manage-cookies";
|
|
2971
|
+
const INITIAL_STATE = Object.freeze({
|
|
2972
|
+
activeComponent: COOKIE_MESSAGE
|
|
2973
|
+
});
|
|
2974
|
+
let privateState = INITIAL_STATE;
|
|
2975
|
+
function isPlainObject(obj) {
|
|
2976
|
+
return typeof obj === "object" && obj !== null && obj.constructor === Object && Object.prototype.toString.call(obj) === "[object Object]";
|
|
2977
|
+
}
|
|
2978
|
+
const getState = () => ({ ...privateState });
|
|
2979
|
+
const setState = (newState) => {
|
|
2980
|
+
if (!isPlainObject(newState)) {
|
|
2981
|
+
console.error("Invalid state changes");
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
privateState = { ...privateState, ...newState };
|
|
2985
|
+
};
|
|
2986
|
+
const ACCEPT_ALL_CHOICE = 11;
|
|
2987
|
+
const MANAGE_PREFS_CHOICE = 12;
|
|
2988
|
+
const REJECT_ALL_CHOICE = 13;
|
|
2989
|
+
const cookieToggleFlags = ["adsDisableInternalCMP", "pwm.cmp", "messageSlotBottom"];
|
|
2990
|
+
function initTracking(context) {
|
|
2991
|
+
const componentId = v4();
|
|
2992
|
+
const flags = extractRelevantFlags(context.flags);
|
|
2993
|
+
window._sp_queue = window._sp_queue ?? [];
|
|
2994
|
+
window._sp_queue.push(() => {
|
|
2995
|
+
var _a2, _b2;
|
|
2996
|
+
for (const [eventId, eventHandler] of Object.entries(trackingEventHandlers)) {
|
|
2997
|
+
(_b2 = (_a2 = window._sp_).addEventListener) == null ? void 0 : _b2.call(_a2, eventId, eventHandler({ ...context, flags, componentId }));
|
|
2998
|
+
}
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
function extractRelevantFlags(flags) {
|
|
3002
|
+
const output = {};
|
|
3003
|
+
if (typeof flags === "object") {
|
|
3004
|
+
cookieToggleFlags.forEach((flagName) => {
|
|
3005
|
+
if (Object.prototype.hasOwnProperty.call(flags, flagName)) {
|
|
3006
|
+
output[flagName] = flags[flagName];
|
|
3007
|
+
}
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
return output;
|
|
3011
|
+
}
|
|
3012
|
+
function track(payload) {
|
|
3013
|
+
if (!payload)
|
|
3014
|
+
return;
|
|
3015
|
+
const rootEl = document.body;
|
|
3016
|
+
const event = new CustomEvent("oTracking.event", {
|
|
3017
|
+
bubbles: true,
|
|
3018
|
+
cancelable: true,
|
|
3019
|
+
detail: payload.detail
|
|
3020
|
+
});
|
|
3021
|
+
rootEl.dispatchEvent(event);
|
|
3022
|
+
}
|
|
3023
|
+
function dispatchComponentEvent({
|
|
3024
|
+
trackingProps,
|
|
3025
|
+
action,
|
|
3026
|
+
triggerAction,
|
|
3027
|
+
messageType
|
|
3028
|
+
}) {
|
|
3029
|
+
const state = getState();
|
|
3030
|
+
const { componentId, product, app, flags } = trackingProps;
|
|
3031
|
+
const event = {
|
|
3032
|
+
detail: {
|
|
3033
|
+
component: {
|
|
3034
|
+
id: componentId,
|
|
3035
|
+
name: state.activeComponent,
|
|
3036
|
+
type: "overlay",
|
|
3037
|
+
subtype: "cmp",
|
|
3038
|
+
componentContentId: state[messageType]
|
|
3039
|
+
},
|
|
3040
|
+
category: "component",
|
|
3041
|
+
action,
|
|
3042
|
+
...triggerAction && { trigger_action: triggerAction },
|
|
3043
|
+
...product && { product },
|
|
3044
|
+
...app && { app },
|
|
3045
|
+
custom: [
|
|
3046
|
+
{
|
|
3047
|
+
cookie_toggle_flag: flags
|
|
3048
|
+
}
|
|
3049
|
+
]
|
|
3050
|
+
}
|
|
3051
|
+
};
|
|
3052
|
+
track(event);
|
|
3053
|
+
}
|
|
3054
|
+
const trackingEventHandlers = {
|
|
3055
|
+
onMessageChoiceSelect: (trackingProps) => (messageType, _choiceId, choiceTypeId) => {
|
|
3056
|
+
if (choiceTypeId === ACCEPT_ALL_CHOICE) {
|
|
3057
|
+
dispatchComponentEvent({
|
|
3058
|
+
trackingProps,
|
|
3059
|
+
action: "click",
|
|
3060
|
+
triggerAction: "accept_all",
|
|
3061
|
+
messageType
|
|
3062
|
+
});
|
|
3063
|
+
}
|
|
3064
|
+
if (choiceTypeId === MANAGE_PREFS_CHOICE) {
|
|
3065
|
+
dispatchComponentEvent({
|
|
3066
|
+
trackingProps,
|
|
3067
|
+
action: "click",
|
|
3068
|
+
triggerAction: "manage_cookies",
|
|
3069
|
+
messageType
|
|
3070
|
+
});
|
|
3071
|
+
setState({
|
|
3072
|
+
activeComponent: PRIVACY_MANAGER
|
|
3073
|
+
});
|
|
3074
|
+
}
|
|
3075
|
+
if (choiceTypeId === REJECT_ALL_CHOICE) {
|
|
3076
|
+
dispatchComponentEvent({
|
|
3077
|
+
trackingProps,
|
|
3078
|
+
action: "click",
|
|
3079
|
+
triggerAction: "reject_all",
|
|
3080
|
+
messageType
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
},
|
|
3084
|
+
onMessageReady: (trackingProps) => (messageType) => {
|
|
3085
|
+
dispatchComponentEvent({
|
|
3086
|
+
trackingProps,
|
|
3087
|
+
action: "view",
|
|
3088
|
+
messageType
|
|
3089
|
+
});
|
|
3090
|
+
},
|
|
3091
|
+
onPrivacyManagerAction: (trackingProps) => (messageType, pmData) => {
|
|
3092
|
+
const { purposeConsent, vendorConsent } = pmData;
|
|
3093
|
+
const isAcceptAll = purposeConsent === "all" && vendorConsent === "all";
|
|
3094
|
+
const isRejectAll = purposeConsent === "none" && vendorConsent === "none";
|
|
3095
|
+
setState({
|
|
3096
|
+
activeComponent: PRIVACY_MANAGER
|
|
3097
|
+
});
|
|
3098
|
+
if (isAcceptAll) {
|
|
3099
|
+
dispatchComponentEvent({
|
|
3100
|
+
trackingProps,
|
|
3101
|
+
action: "click",
|
|
3102
|
+
triggerAction: "accept_all",
|
|
3103
|
+
messageType
|
|
3104
|
+
});
|
|
3105
|
+
} else if (isRejectAll) {
|
|
3106
|
+
dispatchComponentEvent({
|
|
3107
|
+
trackingProps,
|
|
3108
|
+
action: "click",
|
|
3109
|
+
triggerAction: "reject_all",
|
|
3110
|
+
messageType
|
|
3111
|
+
});
|
|
3112
|
+
} else {
|
|
3113
|
+
dispatchComponentEvent({
|
|
3114
|
+
trackingProps,
|
|
3115
|
+
action: "click",
|
|
3116
|
+
triggerAction: "save_and_close",
|
|
3117
|
+
messageType
|
|
3118
|
+
});
|
|
3119
|
+
}
|
|
3120
|
+
},
|
|
3121
|
+
onMessageReceiveData: () => (messageType, data) => {
|
|
3122
|
+
const { messageId } = data;
|
|
3123
|
+
setState({
|
|
3124
|
+
[messageType]: messageId
|
|
3125
|
+
});
|
|
3126
|
+
},
|
|
3127
|
+
onError: (trackingProps) => (messageType, errorCode) => {
|
|
3128
|
+
dispatchComponentEvent({
|
|
3129
|
+
trackingProps,
|
|
3130
|
+
action: "error",
|
|
3131
|
+
triggerAction: errorCode,
|
|
3132
|
+
messageType
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
3135
|
+
};
|
|
2936
3136
|
async function initSourcepointCmp({
|
|
2937
3137
|
propertyConfig = FT_DOTCOM_PROD,
|
|
2938
3138
|
userId,
|
|
@@ -2940,9 +3140,9 @@ async function initSourcepointCmp({
|
|
|
2940
3140
|
consentProxyHost = FT_CONSENT_PROXY_HOST,
|
|
2941
3141
|
cookieDomain = FT_COOKIE_DOMAIN,
|
|
2942
3142
|
formOfWordsId = SOURCEPOINT_FOW_ID,
|
|
2943
|
-
useConsentStore = true
|
|
3143
|
+
useConsentStore = true,
|
|
3144
|
+
trackingContext = {}
|
|
2944
3145
|
} = {}) {
|
|
2945
|
-
var _a2;
|
|
2946
3146
|
if (!userId && useFTSession) {
|
|
2947
3147
|
try {
|
|
2948
3148
|
const response = await getUuid();
|
|
@@ -2957,32 +3157,65 @@ async function initSourcepointCmp({
|
|
|
2957
3157
|
if (userId) {
|
|
2958
3158
|
propertyConfig.authId = userId;
|
|
2959
3159
|
}
|
|
2960
|
-
if (
|
|
2961
|
-
console.warn(
|
|
3160
|
+
if (propertyConfig.events) {
|
|
3161
|
+
console.warn(
|
|
3162
|
+
"[cmp-client] Passing an events map in the config is not supported and will be ignored. Please use window._sp_.addEventListener() to listen for events"
|
|
3163
|
+
);
|
|
3164
|
+
delete propertyConfig.events;
|
|
2962
3165
|
}
|
|
2963
|
-
const events2 = {
|
|
2964
|
-
...propertyConfig.events ?? {},
|
|
2965
|
-
onConsentReady: consentReadyHandlerFn({
|
|
2966
|
-
userId,
|
|
2967
|
-
consentProxyHost,
|
|
2968
|
-
cookieDomain,
|
|
2969
|
-
formOfWordsId,
|
|
2970
|
-
useConsentStore
|
|
2971
|
-
})
|
|
2972
|
-
};
|
|
2973
3166
|
function getCookie(name) {
|
|
3167
|
+
var _a2, _b2;
|
|
2974
3168
|
const value = `; ${document.cookie}`;
|
|
2975
3169
|
const parts = value.split(`; ${name}=`);
|
|
2976
3170
|
if (parts.length === 2)
|
|
2977
|
-
return parts.pop().split(";").shift();
|
|
3171
|
+
return (_b2 = (_a2 = parts.pop()) == null ? void 0 : _a2.split(";")) == null ? void 0 : _b2.shift();
|
|
2978
3172
|
}
|
|
2979
|
-
propertyConfig
|
|
3173
|
+
propertyConfig = {
|
|
3174
|
+
...propertyConfig,
|
|
2980
3175
|
targetingParams: {
|
|
2981
|
-
|
|
2982
|
-
"cookiew": getCookie("cw")
|
|
3176
|
+
cookiew: getCookie("cw")
|
|
2983
3177
|
}
|
|
2984
3178
|
};
|
|
2985
|
-
bootstrapCmp(
|
|
3179
|
+
bootstrapCmp(propertyConfig);
|
|
3180
|
+
window._sp_queue.push(() => {
|
|
3181
|
+
var _a2, _b2;
|
|
3182
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3183
|
+
_a2,
|
|
3184
|
+
"onConsentReady",
|
|
3185
|
+
consentReadyHandlerFn({
|
|
3186
|
+
userId,
|
|
3187
|
+
consentProxyHost,
|
|
3188
|
+
cookieDomain,
|
|
3189
|
+
formOfWordsId,
|
|
3190
|
+
useConsentStore
|
|
3191
|
+
})
|
|
3192
|
+
);
|
|
3193
|
+
});
|
|
3194
|
+
window._sp_queue.push(() => {
|
|
3195
|
+
var _a2, _b2;
|
|
3196
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3197
|
+
_a2,
|
|
3198
|
+
"onMessageChoiceSelect",
|
|
3199
|
+
(_messageType, _choiceId, choiceTypeId) => {
|
|
3200
|
+
if (choiceTypeId === 9) {
|
|
3201
|
+
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2023 12:00:00 UTC";
|
|
3202
|
+
}
|
|
3203
|
+
}
|
|
3204
|
+
);
|
|
3205
|
+
});
|
|
3206
|
+
window._sp_queue.push(() => {
|
|
3207
|
+
var _a2, _b2;
|
|
3208
|
+
(_b2 = (_a2 = window._sp_) == null ? void 0 : _a2.addEventListener) == null ? void 0 : _b2.call(
|
|
3209
|
+
_a2,
|
|
3210
|
+
"onPrivacyManagerAction",
|
|
3211
|
+
(_messageType, pmData) => {
|
|
3212
|
+
if (pmData.purposeConsent == "none" && pmData.vendorConsent == "none") {
|
|
3213
|
+
document.cookie = "cw=dismissed; expires=Thu, 18 Dec 2023 12:00:00 UTC";
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
);
|
|
3217
|
+
});
|
|
3218
|
+
initTracking(trackingContext);
|
|
2986
3219
|
}
|
|
2987
3220
|
window.FT_CMP_CLIENT_VERSION = version;
|
|
2988
3221
|
export {
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CMPInitOptions } from "../typings/types.d.ts";
|
|
2
|
-
export declare function initSourcepointCmp({ propertyConfig, userId, useFTSession, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore, }?: CMPInitOptions): Promise<void>;
|
|
2
|
+
export declare function initSourcepointCmp({ propertyConfig, userId, useFTSession, consentProxyHost, cookieDomain, formOfWordsId, useConsentStore, trackingContext, }?: CMPInitOptions): Promise<void>;
|
|
3
3
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,uBAAuB,CAAC;AAUrF,wBAAsB,kBAAkB,CAAC,EACvC,cAA+B,EAC/B,MAAM,EACN,YAAmB,EACnB,gBAAwC,EACxC,YAA+B,EAC/B,aAAkC,EAClC,eAAsB,EACtB,eAAoB,GACrB,GAAE,cAAmB,iBA6ErB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/lib/debug.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;qCACgB,KAAK;
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/lib/debug.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;qCACgB,KAAK;8BAGZ,KAAK;oCAGC,KAAK;sCAGH,KAAK;0BAGjB,KAAK;oCAGK,KAAK;iCAGR,KAAK;;kBAQL,OAAO,GAAG,SAAS;;uBAM7B,KAAK;CAGzB,CAAC;AAEF,wBAAgB,YAAY,SAO3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.test.d.ts","sourceRoot":"","sources":["../../../../src/tracking/__tests__/state.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/tracking/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,eAAO,MAAM,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tracking/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKV,eAAe,EAEhB,MAAM,0BAA0B,CAAC;AAUlC,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,QASpD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const INITIAL_STATE: Readonly<{
|
|
2
|
+
activeComponent: "cookie-message";
|
|
3
|
+
}>;
|
|
4
|
+
export declare function isPlainObject(obj: unknown): obj is object;
|
|
5
|
+
export declare const getState: () => {
|
|
6
|
+
[x: string]: string | number | boolean | null | undefined;
|
|
7
|
+
};
|
|
8
|
+
export declare const setState: (newState: unknown) => void;
|
|
9
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/tracking/state.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,aAAa;;EAExB,CAAC;AAIH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAOzD;AAGD,eAAO,MAAM,QAAQ;;CAA8B,CAAC;AAEpD,eAAO,MAAM,QAAQ,aAAc,OAAO,SAOzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/cmp-client",
|
|
3
|
-
"version": "0.0.0-beta.
|
|
3
|
+
"version": "0.0.0-beta.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@iabtechlabtcf/core": "^1.5.10",
|
|
20
|
-
"next-session-client": "^5.0.0"
|
|
20
|
+
"next-session-client": "^5.0.0",
|
|
21
|
+
"uuid": "^9.0.1"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
24
|
+
"@types/uuid": "^9.0.7",
|
|
23
25
|
"eslint": "^8.53.0",
|
|
24
26
|
"npm-run-all": "^4.1.5",
|
|
25
27
|
"typescript": "^5.2.2",
|
package/typings/types.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface SPConfig {
|
|
|
16
16
|
joinHref?: boolean;
|
|
17
17
|
events?: Partial<SPLifecycleEvents>;
|
|
18
18
|
authId?: string;
|
|
19
|
+
targetingParams?: Record<string, unknown>;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export type SPEventCallback = (
|
|
@@ -33,7 +34,7 @@ export type CMPInitOptions = Partial<{
|
|
|
33
34
|
cookieDomain: string;
|
|
34
35
|
formOfWordsId: string;
|
|
35
36
|
useConsentStore: boolean;
|
|
36
|
-
|
|
37
|
+
trackingContext?: TrackingContext;
|
|
37
38
|
}>;
|
|
38
39
|
|
|
39
40
|
export interface ConsentPayloadOptions {
|
|
@@ -96,3 +97,39 @@ export interface ConsentState {
|
|
|
96
97
|
raw: RawConsentState;
|
|
97
98
|
parsed: ParsedConsentState;
|
|
98
99
|
}
|
|
100
|
+
|
|
101
|
+
export type TrackingProps = {
|
|
102
|
+
product?: string;
|
|
103
|
+
app?: string;
|
|
104
|
+
flags: FlagsObject;
|
|
105
|
+
componentId: string;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export type TrackingContext = {
|
|
109
|
+
product?: string;
|
|
110
|
+
app?: string;
|
|
111
|
+
flags?: FlagsObject;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export type TrackingEvent = {
|
|
115
|
+
detail: {
|
|
116
|
+
component: {
|
|
117
|
+
id: string;
|
|
118
|
+
name: string;
|
|
119
|
+
type: string;
|
|
120
|
+
subtype: string;
|
|
121
|
+
componentContentId: string | number;
|
|
122
|
+
};
|
|
123
|
+
category: string;
|
|
124
|
+
action: string;
|
|
125
|
+
custom?: Array<Record<string, unknown>>;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
export type SPMessageType = "gdpr" | "ccpa" | "ios14" | "custom";
|
|
129
|
+
|
|
130
|
+
export type SPPMData = {
|
|
131
|
+
purposeConsent: "all" | "none" | "some";
|
|
132
|
+
vendorConsent: "all" | "none" | "some";
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export type FlagsObject = Record<string, string | boolean>;
|