@liquidcommercedev/rmn-sdk 1.5.0-beta.5 → 1.5.0-beta.6
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 +140 -14
- package/dist/index.esm.js +140 -14
- package/dist/types/enums.d.ts +1 -0
- package/dist/types/modules/event/event.interface.d.ts +5 -0
- package/dist/types/modules/event/helpers/datalayer.monitor.d.ts +12 -1
- package/dist/types/modules/event/helpers/localstorage.service.d.ts +26 -7
- package/dist/types/modules/event/helpers/utils.d.ts +24 -0
- package/dist/types/modules/event/pubsub.d.ts +7 -7
- package/dist/types/modules/event/user.monitor.d.ts +1 -0
- package/dist/types/types.d.ts +1 -1
- package/package.json +1 -1
- package/umd/liquidcommerce-rmn-sdk.min.js +1 -1
package/dist/index.cjs
CHANGED
@@ -62,6 +62,7 @@ exports.RMN_SPOT_EVENT = void 0;
|
|
62
62
|
RMN_SPOT_EVENT["CLICK"] = "CLICK";
|
63
63
|
RMN_SPOT_EVENT["PURCHASE"] = "PURCHASE";
|
64
64
|
RMN_SPOT_EVENT["ADD_TO_CART"] = "ADD_TO_CART";
|
65
|
+
RMN_SPOT_EVENT["REMOVE_FROM_CART"] = "REMOVE_FROM_CART";
|
65
66
|
RMN_SPOT_EVENT["ADD_TO_WISHLIST"] = "ADD_TO_WISHLIST";
|
66
67
|
RMN_SPOT_EVENT["BUY_NOW"] = "BUY_NOW";
|
67
68
|
})(exports.RMN_SPOT_EVENT || (exports.RMN_SPOT_EVENT = {}));
|
@@ -15166,6 +15167,84 @@ const GFONT_CORMORANT = `
|
|
15166
15167
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant:ital,wght@0,300..700;1,300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
|
15167
15168
|
`;
|
15168
15169
|
|
15170
|
+
function getEventTypeFromRawEvent(event) {
|
15171
|
+
if (!event) {
|
15172
|
+
return null;
|
15173
|
+
}
|
15174
|
+
if (event.includes('cart')) {
|
15175
|
+
if (event.includes('add')) {
|
15176
|
+
return exports.RMN_SPOT_EVENT.ADD_TO_CART;
|
15177
|
+
}
|
15178
|
+
if (event.includes('remove')) {
|
15179
|
+
return exports.RMN_SPOT_EVENT.REMOVE_FROM_CART;
|
15180
|
+
}
|
15181
|
+
}
|
15182
|
+
if (event.includes('purchase')) {
|
15183
|
+
return exports.RMN_SPOT_EVENT.PURCHASE;
|
15184
|
+
}
|
15185
|
+
// if(event.includes('refund')) {
|
15186
|
+
// return RMN_SPOT_EVENT.REFUND;
|
15187
|
+
// }
|
15188
|
+
if (event.includes('wishlist') && event.includes('add')) {
|
15189
|
+
return exports.RMN_SPOT_EVENT.ADD_TO_WISHLIST;
|
15190
|
+
}
|
15191
|
+
return null;
|
15192
|
+
}
|
15193
|
+
/**
|
15194
|
+
* Recursively extracts ID values from a nested data structure.
|
15195
|
+
* Searches for specified property names and collects their primitive values (strings/numbers).
|
15196
|
+
*
|
15197
|
+
* @param data - The data structure to search through (can be nested objects/arrays)
|
15198
|
+
* @param propertyNames - Array of property names to look for (defaults to ['id', 'upc', 'groupingId', 'sku', 'productId'])
|
15199
|
+
* @returns Array of extracted ID values (strings/numbers only)
|
15200
|
+
*
|
15201
|
+
* @example
|
15202
|
+
* const data = {
|
15203
|
+
* id: [1, 2, 3],
|
15204
|
+
* nested: { id: 'abc' },
|
15205
|
+
* items: [{ id: 456 }]
|
15206
|
+
* };
|
15207
|
+
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
|
15208
|
+
*/
|
15209
|
+
function extractDeepIds(data, propertyNames = ['id', 'upc', 'groupingId', 'sku', 'productId']) {
|
15210
|
+
const ids = [];
|
15211
|
+
// Set for faster property name lookups
|
15212
|
+
const propertySet = new Set(propertyNames);
|
15213
|
+
/**
|
15214
|
+
* Processes a value and extracts IDs if it matches criteria
|
15215
|
+
* @param value - The value to process
|
15216
|
+
* @param currentKey - The property name of the current value
|
15217
|
+
*/
|
15218
|
+
const processValue = (value, currentKey) => {
|
15219
|
+
// Early exit for null/undefined values
|
15220
|
+
if (value == null)
|
15221
|
+
return;
|
15222
|
+
// If current key matches our target properties
|
15223
|
+
if (currentKey && propertySet.has(currentKey)) {
|
15224
|
+
if (Array.isArray(value)) {
|
15225
|
+
// Filter and push valid array values in one pass
|
15226
|
+
ids.push(...value.filter((item) => typeof item === 'string' || typeof item === 'number'));
|
15227
|
+
}
|
15228
|
+
else if (typeof value === 'string' || typeof value === 'number') {
|
15229
|
+
ids.push(value);
|
15230
|
+
}
|
15231
|
+
return; // Stop processing this branch after handling the ID
|
15232
|
+
}
|
15233
|
+
// Recursively process nested structures
|
15234
|
+
if (Array.isArray(value)) {
|
15235
|
+
value.forEach((item) => processValue(item));
|
15236
|
+
}
|
15237
|
+
else if (typeof value === 'object') {
|
15238
|
+
// Process all enumerable properties
|
15239
|
+
for (const [key, val] of Object.entries(value)) {
|
15240
|
+
processValue(val, key);
|
15241
|
+
}
|
15242
|
+
}
|
15243
|
+
};
|
15244
|
+
processValue(data);
|
15245
|
+
return ids; // No need to filter nulls as we handle that during collection
|
15246
|
+
}
|
15247
|
+
|
15169
15248
|
class DataLayerMonitor {
|
15170
15249
|
constructor() {
|
15171
15250
|
if (!window.dataLayer) {
|
@@ -15187,11 +15266,25 @@ class DataLayerMonitor {
|
|
15187
15266
|
const result = this.originalPush.apply(window.dataLayer, args);
|
15188
15267
|
const pushedEvent = args[0];
|
15189
15268
|
if (this.listener) {
|
15190
|
-
this.
|
15269
|
+
const normalizedData = this.cleanEventData(pushedEvent);
|
15270
|
+
if (normalizedData) {
|
15271
|
+
this.listener(normalizedData);
|
15272
|
+
}
|
15191
15273
|
}
|
15192
15274
|
return result;
|
15193
15275
|
};
|
15194
15276
|
}
|
15277
|
+
cleanEventData(data) {
|
15278
|
+
const eventName = getEventTypeFromRawEvent(data.event);
|
15279
|
+
if (!eventName) {
|
15280
|
+
return null;
|
15281
|
+
}
|
15282
|
+
const productIds = extractDeepIds(data.value);
|
15283
|
+
return {
|
15284
|
+
event: eventName,
|
15285
|
+
productIds,
|
15286
|
+
};
|
15287
|
+
}
|
15195
15288
|
stop() {
|
15196
15289
|
if (this.originalPush) {
|
15197
15290
|
window.dataLayer.push = this.originalPush;
|
@@ -15240,6 +15333,14 @@ class IntersectionObserverService {
|
|
15240
15333
|
}
|
15241
15334
|
}
|
15242
15335
|
|
15336
|
+
var ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX;
|
15337
|
+
(function (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX) {
|
15338
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_ID"] = 0] = "SPOT_ID";
|
15339
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_TYPE"] = 1] = "SPOT_TYPE";
|
15340
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["EVENTS"] = 2] = "EVENTS";
|
15341
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PRODUCT_IDS"] = 3] = "PRODUCT_IDS";
|
15342
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["CREATED_AT"] = 4] = "CREATED_AT";
|
15343
|
+
})(ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX || (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX = {}));
|
15243
15344
|
class LocalStorage {
|
15244
15345
|
constructor() {
|
15245
15346
|
if (typeof window.localStorage === 'undefined') {
|
@@ -15265,7 +15366,11 @@ class LocalStorage {
|
|
15265
15366
|
try {
|
15266
15367
|
const parsedData = JSON.parse(localStorageData);
|
15267
15368
|
if (parsedData && typeof parsedData === 'object') {
|
15268
|
-
|
15369
|
+
const data = {};
|
15370
|
+
for (const [key, value] of Object.entries(parsedData)) {
|
15371
|
+
data[key] = this.arrayToObject(value);
|
15372
|
+
}
|
15373
|
+
this.spots = this.objectToMap(data);
|
15269
15374
|
}
|
15270
15375
|
else {
|
15271
15376
|
this.clearLocalStorage();
|
@@ -15295,13 +15400,17 @@ class LocalStorage {
|
|
15295
15400
|
getSpots() {
|
15296
15401
|
if (!this.spots)
|
15297
15402
|
return undefined;
|
15298
|
-
return this.
|
15403
|
+
return this.mapToObject(this.spots);
|
15299
15404
|
}
|
15300
15405
|
updateLocalStorage() {
|
15301
15406
|
if (!this.spots)
|
15302
15407
|
return undefined;
|
15303
|
-
const data = this.
|
15304
|
-
|
15408
|
+
const data = this.mapToObject(this.spots);
|
15409
|
+
const dataArray = {};
|
15410
|
+
for (const [key, value] of Object.entries(data)) {
|
15411
|
+
dataArray[key] = this.objectToArray(value);
|
15412
|
+
}
|
15413
|
+
window.localStorage.setItem(LocalStorage.localStorageKey, JSON.stringify(dataArray));
|
15305
15414
|
}
|
15306
15415
|
clearLocalStorage() {
|
15307
15416
|
window.localStorage.removeItem(LocalStorage.localStorageKey);
|
@@ -15317,12 +15426,24 @@ class LocalStorage {
|
|
15317
15426
|
});
|
15318
15427
|
this.updateLocalStorage();
|
15319
15428
|
}
|
15320
|
-
|
15429
|
+
mapToObject(map) {
|
15321
15430
|
return Object.fromEntries(map);
|
15322
15431
|
}
|
15323
|
-
|
15432
|
+
objectToMap(obj) {
|
15324
15433
|
return new Map(Object.entries(obj));
|
15325
15434
|
}
|
15435
|
+
objectToArray(obj) {
|
15436
|
+
return [obj.spotId, obj.spotType, obj.events, obj.productIds, obj.createdAt];
|
15437
|
+
}
|
15438
|
+
arrayToObject(arr) {
|
15439
|
+
return {
|
15440
|
+
spotId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_ID],
|
15441
|
+
spotType: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_TYPE],
|
15442
|
+
events: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.EVENTS],
|
15443
|
+
productIds: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PRODUCT_IDS],
|
15444
|
+
createdAt: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.CREATED_AT],
|
15445
|
+
};
|
15446
|
+
}
|
15326
15447
|
}
|
15327
15448
|
LocalStorage.localStorageKey = 'lc_rmn';
|
15328
15449
|
LocalStorage.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
|
@@ -18016,7 +18137,7 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
|
|
18016
18137
|
/**
|
18017
18138
|
* PubSub class
|
18018
18139
|
* Manages event subscriptions and publications
|
18019
|
-
* @template
|
18140
|
+
* @template IRmnEventMap A record type defining the structure of events and their data
|
18020
18141
|
*/
|
18021
18142
|
class PubSub {
|
18022
18143
|
constructor() {
|
@@ -18070,12 +18191,12 @@ class PubSub {
|
|
18070
18191
|
/**
|
18071
18192
|
* Usage Example:
|
18072
18193
|
*
|
18073
|
-
* interface
|
18194
|
+
* interface IRmnEventMap {
|
18074
18195
|
* userLogin: { username: string; timestamp: number };
|
18075
18196
|
* pageView: { url: string; timestamp: number };
|
18076
18197
|
* }
|
18077
18198
|
*
|
18078
|
-
* const pubSub = new PubSub<
|
18199
|
+
* const pubSub = new PubSub<IRmnEventMap>();
|
18079
18200
|
*
|
18080
18201
|
* // Subscribe to events
|
18081
18202
|
* const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
|
@@ -18106,7 +18227,6 @@ var AnalyticsTool;
|
|
18106
18227
|
class UserMonitor {
|
18107
18228
|
constructor() {
|
18108
18229
|
const analyticsTool = this.detectAnalyticsTool();
|
18109
|
-
console.info({ analyticsTool });
|
18110
18230
|
switch (analyticsTool) {
|
18111
18231
|
case AnalyticsTool.GoogleAnalytics:
|
18112
18232
|
this.implementedMonitor = DataLayerMonitor.getInstance();
|
@@ -18130,13 +18250,19 @@ class UserMonitor {
|
|
18130
18250
|
start() {
|
18131
18251
|
if (!this.implementedMonitor)
|
18132
18252
|
return;
|
18133
|
-
this.implementedMonitor.setListener((
|
18253
|
+
this.implementedMonitor.setListener((eventData) => {
|
18134
18254
|
var _a;
|
18135
|
-
|
18136
|
-
console.info({ spots: (_a = this.localStorage) === null || _a === void 0 ? void 0 : _a.getSpots() });
|
18255
|
+
this.matchAndFireEvent(eventData, (_a = this.localStorage) === null || _a === void 0 ? void 0 : _a.getSpots());
|
18137
18256
|
});
|
18138
18257
|
this.implementedMonitor.start();
|
18139
18258
|
}
|
18259
|
+
matchAndFireEvent(
|
18260
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
18261
|
+
_eventData,
|
18262
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
18263
|
+
_spots) {
|
18264
|
+
// console.info({ eventData, spots });
|
18265
|
+
}
|
18140
18266
|
detectAnalyticsTool() {
|
18141
18267
|
let analyticsTool = AnalyticsTool.Other;
|
18142
18268
|
// Check for Google Analytics
|
package/dist/index.esm.js
CHANGED
@@ -60,6 +60,7 @@ var RMN_SPOT_EVENT;
|
|
60
60
|
RMN_SPOT_EVENT["CLICK"] = "CLICK";
|
61
61
|
RMN_SPOT_EVENT["PURCHASE"] = "PURCHASE";
|
62
62
|
RMN_SPOT_EVENT["ADD_TO_CART"] = "ADD_TO_CART";
|
63
|
+
RMN_SPOT_EVENT["REMOVE_FROM_CART"] = "REMOVE_FROM_CART";
|
63
64
|
RMN_SPOT_EVENT["ADD_TO_WISHLIST"] = "ADD_TO_WISHLIST";
|
64
65
|
RMN_SPOT_EVENT["BUY_NOW"] = "BUY_NOW";
|
65
66
|
})(RMN_SPOT_EVENT || (RMN_SPOT_EVENT = {}));
|
@@ -15164,6 +15165,84 @@ const GFONT_CORMORANT = `
|
|
15164
15165
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant:ital,wght@0,300..700;1,300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap">
|
15165
15166
|
`;
|
15166
15167
|
|
15168
|
+
function getEventTypeFromRawEvent(event) {
|
15169
|
+
if (!event) {
|
15170
|
+
return null;
|
15171
|
+
}
|
15172
|
+
if (event.includes('cart')) {
|
15173
|
+
if (event.includes('add')) {
|
15174
|
+
return RMN_SPOT_EVENT.ADD_TO_CART;
|
15175
|
+
}
|
15176
|
+
if (event.includes('remove')) {
|
15177
|
+
return RMN_SPOT_EVENT.REMOVE_FROM_CART;
|
15178
|
+
}
|
15179
|
+
}
|
15180
|
+
if (event.includes('purchase')) {
|
15181
|
+
return RMN_SPOT_EVENT.PURCHASE;
|
15182
|
+
}
|
15183
|
+
// if(event.includes('refund')) {
|
15184
|
+
// return RMN_SPOT_EVENT.REFUND;
|
15185
|
+
// }
|
15186
|
+
if (event.includes('wishlist') && event.includes('add')) {
|
15187
|
+
return RMN_SPOT_EVENT.ADD_TO_WISHLIST;
|
15188
|
+
}
|
15189
|
+
return null;
|
15190
|
+
}
|
15191
|
+
/**
|
15192
|
+
* Recursively extracts ID values from a nested data structure.
|
15193
|
+
* Searches for specified property names and collects their primitive values (strings/numbers).
|
15194
|
+
*
|
15195
|
+
* @param data - The data structure to search through (can be nested objects/arrays)
|
15196
|
+
* @param propertyNames - Array of property names to look for (defaults to ['id', 'upc', 'groupingId', 'sku', 'productId'])
|
15197
|
+
* @returns Array of extracted ID values (strings/numbers only)
|
15198
|
+
*
|
15199
|
+
* @example
|
15200
|
+
* const data = {
|
15201
|
+
* id: [1, 2, 3],
|
15202
|
+
* nested: { id: 'abc' },
|
15203
|
+
* items: [{ id: 456 }]
|
15204
|
+
* };
|
15205
|
+
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
|
15206
|
+
*/
|
15207
|
+
function extractDeepIds(data, propertyNames = ['id', 'upc', 'groupingId', 'sku', 'productId']) {
|
15208
|
+
const ids = [];
|
15209
|
+
// Set for faster property name lookups
|
15210
|
+
const propertySet = new Set(propertyNames);
|
15211
|
+
/**
|
15212
|
+
* Processes a value and extracts IDs if it matches criteria
|
15213
|
+
* @param value - The value to process
|
15214
|
+
* @param currentKey - The property name of the current value
|
15215
|
+
*/
|
15216
|
+
const processValue = (value, currentKey) => {
|
15217
|
+
// Early exit for null/undefined values
|
15218
|
+
if (value == null)
|
15219
|
+
return;
|
15220
|
+
// If current key matches our target properties
|
15221
|
+
if (currentKey && propertySet.has(currentKey)) {
|
15222
|
+
if (Array.isArray(value)) {
|
15223
|
+
// Filter and push valid array values in one pass
|
15224
|
+
ids.push(...value.filter((item) => typeof item === 'string' || typeof item === 'number'));
|
15225
|
+
}
|
15226
|
+
else if (typeof value === 'string' || typeof value === 'number') {
|
15227
|
+
ids.push(value);
|
15228
|
+
}
|
15229
|
+
return; // Stop processing this branch after handling the ID
|
15230
|
+
}
|
15231
|
+
// Recursively process nested structures
|
15232
|
+
if (Array.isArray(value)) {
|
15233
|
+
value.forEach((item) => processValue(item));
|
15234
|
+
}
|
15235
|
+
else if (typeof value === 'object') {
|
15236
|
+
// Process all enumerable properties
|
15237
|
+
for (const [key, val] of Object.entries(value)) {
|
15238
|
+
processValue(val, key);
|
15239
|
+
}
|
15240
|
+
}
|
15241
|
+
};
|
15242
|
+
processValue(data);
|
15243
|
+
return ids; // No need to filter nulls as we handle that during collection
|
15244
|
+
}
|
15245
|
+
|
15167
15246
|
class DataLayerMonitor {
|
15168
15247
|
constructor() {
|
15169
15248
|
if (!window.dataLayer) {
|
@@ -15185,11 +15264,25 @@ class DataLayerMonitor {
|
|
15185
15264
|
const result = this.originalPush.apply(window.dataLayer, args);
|
15186
15265
|
const pushedEvent = args[0];
|
15187
15266
|
if (this.listener) {
|
15188
|
-
this.
|
15267
|
+
const normalizedData = this.cleanEventData(pushedEvent);
|
15268
|
+
if (normalizedData) {
|
15269
|
+
this.listener(normalizedData);
|
15270
|
+
}
|
15189
15271
|
}
|
15190
15272
|
return result;
|
15191
15273
|
};
|
15192
15274
|
}
|
15275
|
+
cleanEventData(data) {
|
15276
|
+
const eventName = getEventTypeFromRawEvent(data.event);
|
15277
|
+
if (!eventName) {
|
15278
|
+
return null;
|
15279
|
+
}
|
15280
|
+
const productIds = extractDeepIds(data.value);
|
15281
|
+
return {
|
15282
|
+
event: eventName,
|
15283
|
+
productIds,
|
15284
|
+
};
|
15285
|
+
}
|
15193
15286
|
stop() {
|
15194
15287
|
if (this.originalPush) {
|
15195
15288
|
window.dataLayer.push = this.originalPush;
|
@@ -15238,6 +15331,14 @@ class IntersectionObserverService {
|
|
15238
15331
|
}
|
15239
15332
|
}
|
15240
15333
|
|
15334
|
+
var ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX;
|
15335
|
+
(function (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX) {
|
15336
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_ID"] = 0] = "SPOT_ID";
|
15337
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["SPOT_TYPE"] = 1] = "SPOT_TYPE";
|
15338
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["EVENTS"] = 2] = "EVENTS";
|
15339
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["PRODUCT_IDS"] = 3] = "PRODUCT_IDS";
|
15340
|
+
ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX["CREATED_AT"] = 4] = "CREATED_AT";
|
15341
|
+
})(ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX || (ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX = {}));
|
15241
15342
|
class LocalStorage {
|
15242
15343
|
constructor() {
|
15243
15344
|
if (typeof window.localStorage === 'undefined') {
|
@@ -15263,7 +15364,11 @@ class LocalStorage {
|
|
15263
15364
|
try {
|
15264
15365
|
const parsedData = JSON.parse(localStorageData);
|
15265
15366
|
if (parsedData && typeof parsedData === 'object') {
|
15266
|
-
|
15367
|
+
const data = {};
|
15368
|
+
for (const [key, value] of Object.entries(parsedData)) {
|
15369
|
+
data[key] = this.arrayToObject(value);
|
15370
|
+
}
|
15371
|
+
this.spots = this.objectToMap(data);
|
15267
15372
|
}
|
15268
15373
|
else {
|
15269
15374
|
this.clearLocalStorage();
|
@@ -15293,13 +15398,17 @@ class LocalStorage {
|
|
15293
15398
|
getSpots() {
|
15294
15399
|
if (!this.spots)
|
15295
15400
|
return undefined;
|
15296
|
-
return this.
|
15401
|
+
return this.mapToObject(this.spots);
|
15297
15402
|
}
|
15298
15403
|
updateLocalStorage() {
|
15299
15404
|
if (!this.spots)
|
15300
15405
|
return undefined;
|
15301
|
-
const data = this.
|
15302
|
-
|
15406
|
+
const data = this.mapToObject(this.spots);
|
15407
|
+
const dataArray = {};
|
15408
|
+
for (const [key, value] of Object.entries(data)) {
|
15409
|
+
dataArray[key] = this.objectToArray(value);
|
15410
|
+
}
|
15411
|
+
window.localStorage.setItem(LocalStorage.localStorageKey, JSON.stringify(dataArray));
|
15303
15412
|
}
|
15304
15413
|
clearLocalStorage() {
|
15305
15414
|
window.localStorage.removeItem(LocalStorage.localStorageKey);
|
@@ -15315,12 +15424,24 @@ class LocalStorage {
|
|
15315
15424
|
});
|
15316
15425
|
this.updateLocalStorage();
|
15317
15426
|
}
|
15318
|
-
|
15427
|
+
mapToObject(map) {
|
15319
15428
|
return Object.fromEntries(map);
|
15320
15429
|
}
|
15321
|
-
|
15430
|
+
objectToMap(obj) {
|
15322
15431
|
return new Map(Object.entries(obj));
|
15323
15432
|
}
|
15433
|
+
objectToArray(obj) {
|
15434
|
+
return [obj.spotId, obj.spotType, obj.events, obj.productIds, obj.createdAt];
|
15435
|
+
}
|
15436
|
+
arrayToObject(arr) {
|
15437
|
+
return {
|
15438
|
+
spotId: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_ID],
|
15439
|
+
spotType: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.SPOT_TYPE],
|
15440
|
+
events: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.EVENTS],
|
15441
|
+
productIds: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.PRODUCT_IDS],
|
15442
|
+
createdAt: arr[ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX.CREATED_AT],
|
15443
|
+
};
|
15444
|
+
}
|
15324
15445
|
}
|
15325
15446
|
LocalStorage.localStorageKey = 'lc_rmn';
|
15326
15447
|
LocalStorage.spotExpirationTime = 1000 * 60 * 60 * 24 * 7; // 7 days
|
@@ -18014,7 +18135,7 @@ const SPOT_TEMPLATE_HTML_ELEMENT = (spot, config) => {
|
|
18014
18135
|
/**
|
18015
18136
|
* PubSub class
|
18016
18137
|
* Manages event subscriptions and publications
|
18017
|
-
* @template
|
18138
|
+
* @template IRmnEventMap A record type defining the structure of events and their data
|
18018
18139
|
*/
|
18019
18140
|
class PubSub {
|
18020
18141
|
constructor() {
|
@@ -18068,12 +18189,12 @@ class PubSub {
|
|
18068
18189
|
/**
|
18069
18190
|
* Usage Example:
|
18070
18191
|
*
|
18071
|
-
* interface
|
18192
|
+
* interface IRmnEventMap {
|
18072
18193
|
* userLogin: { username: string; timestamp: number };
|
18073
18194
|
* pageView: { url: string; timestamp: number };
|
18074
18195
|
* }
|
18075
18196
|
*
|
18076
|
-
* const pubSub = new PubSub<
|
18197
|
+
* const pubSub = new PubSub<IRmnEventMap>();
|
18077
18198
|
*
|
18078
18199
|
* // Subscribe to events
|
18079
18200
|
* const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
|
@@ -18104,7 +18225,6 @@ var AnalyticsTool;
|
|
18104
18225
|
class UserMonitor {
|
18105
18226
|
constructor() {
|
18106
18227
|
const analyticsTool = this.detectAnalyticsTool();
|
18107
|
-
console.info({ analyticsTool });
|
18108
18228
|
switch (analyticsTool) {
|
18109
18229
|
case AnalyticsTool.GoogleAnalytics:
|
18110
18230
|
this.implementedMonitor = DataLayerMonitor.getInstance();
|
@@ -18128,13 +18248,19 @@ class UserMonitor {
|
|
18128
18248
|
start() {
|
18129
18249
|
if (!this.implementedMonitor)
|
18130
18250
|
return;
|
18131
|
-
this.implementedMonitor.setListener((
|
18251
|
+
this.implementedMonitor.setListener((eventData) => {
|
18132
18252
|
var _a;
|
18133
|
-
|
18134
|
-
console.info({ spots: (_a = this.localStorage) === null || _a === void 0 ? void 0 : _a.getSpots() });
|
18253
|
+
this.matchAndFireEvent(eventData, (_a = this.localStorage) === null || _a === void 0 ? void 0 : _a.getSpots());
|
18135
18254
|
});
|
18136
18255
|
this.implementedMonitor.start();
|
18137
18256
|
}
|
18257
|
+
matchAndFireEvent(
|
18258
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
18259
|
+
_eventData,
|
18260
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
18261
|
+
_spots) {
|
18262
|
+
// console.info({ eventData, spots });
|
18263
|
+
}
|
18138
18264
|
detectAnalyticsTool() {
|
18139
18265
|
let analyticsTool = AnalyticsTool.Other;
|
18140
18266
|
// Check for Google Analytics
|
package/dist/types/enums.d.ts
CHANGED
@@ -44,6 +44,10 @@ export interface IAddToCartEvent {
|
|
44
44
|
placementId: string;
|
45
45
|
spotId: string;
|
46
46
|
}
|
47
|
+
export interface IRemoveFromCartEvent {
|
48
|
+
placementId: string;
|
49
|
+
spotId: string;
|
50
|
+
}
|
47
51
|
export interface IAddToWishlistEvent {
|
48
52
|
placementId: string;
|
49
53
|
spotId: string;
|
@@ -61,6 +65,7 @@ export interface IRmnEventMap {
|
|
61
65
|
[RMN_SPOT_EVENT.CLICK]: IClickEvent;
|
62
66
|
[RMN_SPOT_EVENT.IMPRESSION]: IImpressionEvent;
|
63
67
|
[RMN_SPOT_EVENT.ADD_TO_CART]: IAddToCartEvent;
|
68
|
+
[RMN_SPOT_EVENT.REMOVE_FROM_CART]: IRemoveFromCartEvent;
|
64
69
|
[RMN_SPOT_EVENT.ADD_TO_WISHLIST]: IAddToWishlistEvent;
|
65
70
|
[RMN_SPOT_EVENT.PURCHASE]: IPurchaseEvent;
|
66
71
|
[RMN_SPOT_EVENT.BUY_NOW]: IBuyNowEvent;
|
@@ -1,10 +1,21 @@
|
|
1
|
+
import type { RMN_SPOT_EVENT } from 'enums';
|
2
|
+
export interface IDataLayerEvent {
|
3
|
+
event?: string;
|
4
|
+
value?: any[];
|
5
|
+
[key: string]: any;
|
6
|
+
}
|
7
|
+
export interface INormalizedEventData {
|
8
|
+
event: RMN_SPOT_EVENT;
|
9
|
+
productIds: Array<string | number>;
|
10
|
+
}
|
1
11
|
export declare class DataLayerMonitor {
|
2
12
|
private static instance;
|
3
13
|
private readonly originalPush;
|
4
14
|
private listener?;
|
5
15
|
private constructor();
|
6
16
|
static getInstance(): DataLayerMonitor;
|
7
|
-
setListener(listener: (data:
|
17
|
+
setListener(listener: (data: INormalizedEventData) => void): void;
|
8
18
|
start(): void;
|
19
|
+
private cleanEventData;
|
9
20
|
stop(): void;
|
10
21
|
}
|
@@ -1,9 +1,5 @@
|
|
1
1
|
import type { RMN_SPOT_TYPE } from 'enums';
|
2
2
|
import type { ISpotEvent } from 'modules/selection';
|
3
|
-
export type LocalStorageSpotsMapType = Map<string, // spotId
|
4
|
-
ILocalStorageSpot>;
|
5
|
-
export type LocalStorageSpotsObjType = Record<string, // spotId
|
6
|
-
ILocalStorageSpot>;
|
7
3
|
export interface ILocalStorageSpot {
|
8
4
|
spotId: string;
|
9
5
|
spotType: RMN_SPOT_TYPE;
|
@@ -11,6 +7,27 @@ export interface ILocalStorageSpot {
|
|
11
7
|
productIds: Array<string | number>;
|
12
8
|
createdAt?: number;
|
13
9
|
}
|
10
|
+
export type LocalStorageSpotsMapType = Map<string, // spotId
|
11
|
+
ILocalStorageSpot>;
|
12
|
+
export type LocalStorageSpotsObjectType = Record<string, // spotId
|
13
|
+
ILocalStorageSpot>;
|
14
|
+
export type LocalStorageSpotArray = [
|
15
|
+
string,
|
16
|
+
RMN_SPOT_TYPE,
|
17
|
+
ISpotEvent[],
|
18
|
+
Array<string | number>,
|
19
|
+
// PRODUCT_IDS = 3
|
20
|
+
number | undefined
|
21
|
+
];
|
22
|
+
export declare enum ENUM_LOCAL_STORAGE_SPOT_ARRAY_INDEX {
|
23
|
+
SPOT_ID = 0,
|
24
|
+
SPOT_TYPE = 1,
|
25
|
+
EVENTS = 2,
|
26
|
+
PRODUCT_IDS = 3,
|
27
|
+
CREATED_AT = 4
|
28
|
+
}
|
29
|
+
export type LocalStorageSpotsArrayType = Record<string, // spotId
|
30
|
+
LocalStorageSpotArray>;
|
14
31
|
export declare class LocalStorage {
|
15
32
|
private spots?;
|
16
33
|
private static instance;
|
@@ -22,10 +39,12 @@ export declare class LocalStorage {
|
|
22
39
|
setSpot(spotId: string, data: ILocalStorageSpot): void;
|
23
40
|
removeSpot(spotId: string): void;
|
24
41
|
getSpot(spotId: string): ILocalStorageSpot | undefined;
|
25
|
-
getSpots():
|
42
|
+
getSpots(): LocalStorageSpotsObjectType | undefined;
|
26
43
|
private updateLocalStorage;
|
27
44
|
private clearLocalStorage;
|
28
45
|
private removeExpiredSpots;
|
29
|
-
private
|
30
|
-
private
|
46
|
+
private mapToObject;
|
47
|
+
private objectToMap;
|
48
|
+
private objectToArray;
|
49
|
+
private arrayToObject;
|
31
50
|
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { RMN_SPOT_EVENT } from 'enums';
|
2
|
+
export interface IExtractIdsProps {
|
3
|
+
id?: string | number;
|
4
|
+
upc?: string | number;
|
5
|
+
[key: string]: string | number | undefined;
|
6
|
+
}
|
7
|
+
export declare function getEventTypeFromRawEvent(event?: string): RMN_SPOT_EVENT | null;
|
8
|
+
/**
|
9
|
+
* Recursively extracts ID values from a nested data structure.
|
10
|
+
* Searches for specified property names and collects their primitive values (strings/numbers).
|
11
|
+
*
|
12
|
+
* @param data - The data structure to search through (can be nested objects/arrays)
|
13
|
+
* @param propertyNames - Array of property names to look for (defaults to ['id', 'upc', 'groupingId', 'sku', 'productId'])
|
14
|
+
* @returns Array of extracted ID values (strings/numbers only)
|
15
|
+
*
|
16
|
+
* @example
|
17
|
+
* const data = {
|
18
|
+
* id: [1, 2, 3],
|
19
|
+
* nested: { id: 'abc' },
|
20
|
+
* items: [{ id: 456 }]
|
21
|
+
* };
|
22
|
+
* extractDeepIds(data); // Returns [1, 2, 3, 'abc', 456]
|
23
|
+
*/
|
24
|
+
export declare function extractDeepIds(data: any, propertyNames?: readonly string[]): Array<string | number>;
|
@@ -10,11 +10,11 @@ export type PubSubUnsubscribe = () => void;
|
|
10
10
|
/**
|
11
11
|
* PubSub class
|
12
12
|
* Manages event subscriptions and publications
|
13
|
-
* @template
|
13
|
+
* @template IRmnEventMap A record type defining the structure of events and their data
|
14
14
|
*/
|
15
|
-
export declare class PubSub<
|
15
|
+
export declare class PubSub<IRmnEventMap> {
|
16
16
|
private static instance;
|
17
|
-
static getInstance<
|
17
|
+
static getInstance<IRmnEventMap>(): PubSub<IRmnEventMap>;
|
18
18
|
/**
|
19
19
|
* Object to store subscribers for each event type
|
20
20
|
*/
|
@@ -30,7 +30,7 @@ export declare class PubSub<IEventMap> {
|
|
30
30
|
* console.log(`User ${data.username} logged in`);
|
31
31
|
* });
|
32
32
|
*/
|
33
|
-
subscribe<K extends keyof
|
33
|
+
subscribe<K extends keyof IRmnEventMap>(eventType: K, callback: PubSubCallback<IRmnEventMap[K]>): PubSubUnsubscribe;
|
34
34
|
/**
|
35
35
|
* Publish an event
|
36
36
|
* @param eventType - The type of event to publish
|
@@ -39,17 +39,17 @@ export declare class PubSub<IEventMap> {
|
|
39
39
|
* @Example:
|
40
40
|
* pubSub.publish('userLogin', { username: 'john_doe', timestamp: Date.now() });
|
41
41
|
*/
|
42
|
-
publish<K extends keyof
|
42
|
+
publish<K extends keyof IRmnEventMap>(eventType: K, data: IRmnEventMap[K]): void;
|
43
43
|
}
|
44
44
|
/**
|
45
45
|
* Usage Example:
|
46
46
|
*
|
47
|
-
* interface
|
47
|
+
* interface IRmnEventMap {
|
48
48
|
* userLogin: { username: string; timestamp: number };
|
49
49
|
* pageView: { url: string; timestamp: number };
|
50
50
|
* }
|
51
51
|
*
|
52
|
-
* const pubSub = new PubSub<
|
52
|
+
* const pubSub = new PubSub<IRmnEventMap>();
|
53
53
|
*
|
54
54
|
* // Subscribe to events
|
55
55
|
* const unsubscribeLogin = pubSub.subscribe('userLogin', (data) => {
|