@liquidcommercedev/rmn-sdk 1.5.0-beta.25 → 1.5.0-beta.27

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 CHANGED
@@ -6133,120 +6133,6 @@ function getEventTypeFromRawEvent(event) {
6133
6133
  }
6134
6134
 
6135
6135
  // Configuration object with target field names
6136
- const extractorConfig = {
6137
- ids: [
6138
- // Ps: The function handles all the variations of keywords that end with "id" or "ids"
6139
- // Universal product identifiers
6140
- 'gtin',
6141
- 'gtin8',
6142
- 'gtin12',
6143
- 'gtin13',
6144
- 'gtin14',
6145
- 'mpn',
6146
- 'sku',
6147
- 'upc',
6148
- 'ean',
6149
- 'isbn',
6150
- 'isbn10',
6151
- 'isbn13',
6152
- 'asin',
6153
- // Product codes and references
6154
- 'coupon',
6155
- 'barcode',
6156
- 'product_code',
6157
- 'part_number',
6158
- 'model_number',
6159
- 'item_variant',
6160
- 'item_number',
6161
- 'article_number',
6162
- 'reference',
6163
- 'salsifyGrouping',
6164
- 'grouping',
6165
- ],
6166
- price: [
6167
- 'price',
6168
- 'unitPrice',
6169
- 'cost',
6170
- 'current_price',
6171
- 'sale_price',
6172
- 'price_value',
6173
- 'sale_price_value',
6174
- 'regular_price',
6175
- 'discount_price',
6176
- 'unit_price',
6177
- 'original_price',
6178
- 'final_price',
6179
- 'retail_price',
6180
- ],
6181
- };
6182
- /**
6183
- * Extracts deep values from an object based on specified target type
6184
- * @param data - The source data object to extract values from
6185
- * @param target - The type of values to extract ('ids' or 'price')
6186
- * @param options - Optional configuration for the extraction process
6187
- * @returns Array of extracted values or a single value if onlyFirst is true
6188
- */
6189
- function extractDeepValues(data, target, options = {}) {
6190
- const {
6191
- // eslint-disable-next-line @typescript-eslint/naming-convention
6192
- onlyFirst = false, shouldIncludeZero = false, } = options;
6193
- const values = [];
6194
- const targetProperties = new Set(extractorConfig[target].map((name) => name.toLowerCase()));
6195
- /**
6196
- * Checks if a property name matches the target criteria
6197
- */
6198
- const isTargetField = (key) => {
6199
- const normalizedKey = key.toLowerCase();
6200
- const hasTarget = targetProperties.has(normalizedKey);
6201
- if (target === 'ids') {
6202
- return normalizedKey.endsWith('id') || normalizedKey.endsWith('ids') || hasTarget;
6203
- }
6204
- return hasTarget;
6205
- };
6206
- /**
6207
- * Validates and normalizes extracted values
6208
- */
6209
- const validateValue = (value) => {
6210
- if (typeof value === 'string') {
6211
- return value.trim().length > 0;
6212
- }
6213
- if (typeof value === 'number') {
6214
- return !isNaN(value) && (shouldIncludeZero || value !== 0);
6215
- }
6216
- return false;
6217
- };
6218
- /**
6219
- * Processes a value and extracts matching fields
6220
- */
6221
- const processValue = (value, currentKey) => {
6222
- // Early exit conditions
6223
- if (value == null || (onlyFirst && values.length > 0))
6224
- return;
6225
- // Process current value if it matches target criteria
6226
- if (currentKey && isTargetField(currentKey)) {
6227
- if (Array.isArray(value)) {
6228
- const validValues = value.filter(validateValue);
6229
- values.push(...validValues);
6230
- }
6231
- else if (validateValue(value)) {
6232
- values.push(value);
6233
- }
6234
- return;
6235
- }
6236
- // Recursive processing for nested structures
6237
- if (Array.isArray(value)) {
6238
- value.forEach((item) => processValue(item));
6239
- }
6240
- else if (typeof value === 'object') {
6241
- Object.entries(value).forEach(([key, val]) => processValue(val, key));
6242
- }
6243
- };
6244
- processValue(data);
6245
- // Return based on options
6246
- if (values.length === 0)
6247
- return undefined;
6248
- return onlyFirst ? values[0] : values;
6249
- }
6250
6136
  /**
6251
6137
  * Cleans and normalizes an array of product IDs by:
6252
6138
  * 1. Converting all IDs to strings
@@ -16675,8 +16561,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
16675
16561
  // Map clone to original for event handling
16676
16562
  this.cloneToOriginalMap.set(clonedSlide, this.slides[index]);
16677
16563
  let isDragging = false;
16678
- slideElement.addEventListener('mousedown', () => isDragging = false);
16679
- slideElement.addEventListener('mousemove', () => isDragging = true);
16564
+ slideElement.addEventListener('mousedown', () => (isDragging = false));
16565
+ slideElement.addEventListener('mousemove', () => (isDragging = true));
16680
16566
  // Add event delegation to the slide container
16681
16567
  slideElement.addEventListener('click', (e) => {
16682
16568
  if (isDragging) {
@@ -17199,7 +17085,8 @@ if (typeof window !== 'undefined' && typeof window.customElements !== 'undefined
17199
17085
  CarouselElement = CustomCarouselElement;
17200
17086
  }
17201
17087
 
17202
- function SkeletonTemplate({ fluid, width, height }) {
17088
+ function SkeletonTemplate({ fluid, width, height, spotType, }) {
17089
+ const isSmall = spotType === exports.RMN_SPOT_TYPE.RB_IN_TEXT;
17203
17090
  return `
17204
17091
  <style>
17205
17092
  :host {
@@ -17210,42 +17097,20 @@ function SkeletonTemplate({ fluid, width, height }) {
17210
17097
  width: ${fluid ? '100%' : `${width}px`};
17211
17098
  height: ${fluid ? '100%' : `${height}px`};
17212
17099
  background: #ffffff;
17213
- padding: 20px;
17100
+ padding: ${isSmall ? '0' : '1rem'};
17214
17101
  border-radius: 5px;
17215
17102
  }
17216
17103
 
17217
- .content {
17218
- height: 100%;
17219
- display: flex;
17220
- flex-direction: column;
17221
- gap: 20px;
17222
- }
17223
-
17224
- .image-placeholder {
17104
+ .line {
17225
17105
  width: 100%;
17226
17106
  height: 100%;
17107
+ min-height: 15px;
17227
17108
  background: #f0f0f0;
17228
- border-radius: 4px;
17229
- position: relative;
17230
- overflow: hidden;
17231
- }
17232
-
17233
- .lines-container {
17234
- display: flex;
17235
- flex-direction: column;
17236
- justify-content: flex-end;
17237
- }
17238
-
17239
- .line {
17240
- height: 20px;
17241
- background: #f0f0f0;
17242
- border-radius: 4px;
17243
- margin-bottom: 15px;
17109
+ border-radius: 5px;
17244
17110
  position: relative;
17245
17111
  overflow: hidden;
17246
17112
  }
17247
17113
 
17248
- .image-placeholder::after,
17249
17114
  .line::after {
17250
17115
  content: "";
17251
17116
  position: absolute;
@@ -17262,18 +17127,6 @@ function SkeletonTemplate({ fluid, width, height }) {
17262
17127
  animation: shimmer 1.5s infinite;
17263
17128
  }
17264
17129
 
17265
- .line.header {
17266
- width: 25%;
17267
- }
17268
-
17269
- .line.description {
17270
- width: 65%;
17271
- }
17272
-
17273
- .line.button {
17274
- width: 40%;
17275
- }
17276
-
17277
17130
  @keyframes shimmer {
17278
17131
  0% {
17279
17132
  transform: translateX(-100%);
@@ -17284,14 +17137,7 @@ function SkeletonTemplate({ fluid, width, height }) {
17284
17137
  }
17285
17138
  </style>
17286
17139
 
17287
- <div class="content">
17288
- <div class="image-placeholder"></div>
17289
- <div class="lines-container">
17290
- <div class="line header"></div>
17291
- <div class="line description"></div>
17292
- <div class="line button"></div>
17293
- </div>
17294
- </div>
17140
+ <div class="line"></div>
17295
17141
  `;
17296
17142
  }
17297
17143
 
@@ -17470,6 +17316,7 @@ class ElementService {
17470
17316
  const skeleton = document.createElement(SKELETON_ELEMENT_TAG);
17471
17317
  const dimensions = SPOT_DIMENSIONS[params.spotType];
17472
17318
  skeleton.data = {
17319
+ spotType: params.spotType,
17473
17320
  fluid: params.fluid,
17474
17321
  ...dimensions,
17475
17322
  };
@@ -18911,7 +18758,7 @@ function rbHomepageHeroTwoTileTemplate(spot, config) {
18911
18758
  `;
18912
18759
  }
18913
18760
 
18914
- const STYLES$4 = ({ textColor = '#ffffff', backgroundColor = 'transparent' }, { prefix }) => `
18761
+ const STYLES$4 = ({ textColor = '#212121', backgroundColor = 'transparent' }, { prefix }) => `
18915
18762
  <style>
18916
18763
  .${prefix} {
18917
18764
  display: block;
@@ -18928,6 +18775,10 @@ const STYLES$4 = ({ textColor = '#ffffff', backgroundColor = 'transparent' }, {
18928
18775
  font-family: "Source Sans 3", system-ui;
18929
18776
  margin: 0;
18930
18777
  }
18778
+
18779
+ .${prefix}__header:hover {
18780
+ color: #b5914a;
18781
+ }
18931
18782
  </style>
18932
18783
  `;
18933
18784
  function rbInTextTemplate(spot, config) {
@@ -19381,40 +19232,45 @@ class DataLayerMonitor {
19381
19232
  return result;
19382
19233
  }
19383
19234
  for (const pushedEvent of args) {
19384
- const normalizedData = this.cleanEventData(pushedEvent);
19385
- if (normalizedData) {
19386
- this.listener(normalizedData);
19235
+ const eventName = getEventTypeFromRawEvent(pushedEvent.event);
19236
+ if (!eventName) {
19237
+ continue;
19238
+ }
19239
+ const productData = this.extractProductData(pushedEvent);
19240
+ const eventData = {
19241
+ event: eventName,
19242
+ products: productData,
19243
+ };
19244
+ if (productData) {
19245
+ this.listener(eventData);
19387
19246
  }
19388
19247
  }
19389
19248
  return result;
19390
19249
  };
19391
19250
  }
19392
- cleanEventData(data) {
19393
- const eventName = getEventTypeFromRawEvent(data.event);
19394
- if (!eventName) {
19395
- return null;
19396
- }
19397
- const productIds = extractDeepValues(data, 'ids', {
19398
- onlyFirst: false,
19399
- shouldIncludeZero: true,
19400
- });
19401
- if (Array.isArray(productIds) && productIds.length === 0) {
19402
- return null;
19403
- }
19404
- const normalizedData = {
19405
- event: eventName,
19406
- productIds,
19407
- };
19408
- if (eventName === exports.RMN_SPOT_EVENT.PURCHASE) {
19409
- const productPrice = extractDeepValues(data, 'price', {
19410
- onlyFirst: true,
19411
- shouldIncludeZero: true,
19412
- });
19413
- if (productPrice) {
19414
- normalizedData.productPrice = productPrice;
19251
+ extractProductData(event) {
19252
+ var _a, _b, _c, _d, _e, _f, _g, _h;
19253
+ const items = ((_a = event === null || event === void 0 ? void 0 : event.value) === null || _a === void 0 ? void 0 : _a.items) ||
19254
+ ((_b = event === null || event === void 0 ? void 0 : event.ecommerce) === null || _b === void 0 ? void 0 : _b.items) ||
19255
+ ((_d = (_c = event === null || event === void 0 ? void 0 : event.ecommerce) === null || _c === void 0 ? void 0 : _c.detail) === null || _d === void 0 ? void 0 : _d.products) ||
19256
+ ((_f = (_e = event === null || event === void 0 ? void 0 : event.ecommerce) === null || _e === void 0 ? void 0 : _e.checkout) === null || _f === void 0 ? void 0 : _f.products) ||
19257
+ ((_h = (_g = event === null || event === void 0 ? void 0 : event.ecommerce) === null || _g === void 0 ? void 0 : _g.purchase) === null || _h === void 0 ? void 0 : _h.products) ||
19258
+ [];
19259
+ return items.map((item) => {
19260
+ const data = {
19261
+ id: item.item_id || item.id || '',
19262
+ name: item.item_name || item.name || '',
19263
+ brand: item.item_brand || item.brand || '',
19264
+ variant: item.item_variant || item.variant || '',
19265
+ price: Number(item.price) || 0,
19266
+ quantity: Number(item.quantity) || 1,
19267
+ discount: Number(item.discount) || 0,
19268
+ };
19269
+ if (!data.id) {
19270
+ return null;
19415
19271
  }
19416
- }
19417
- return normalizedData;
19272
+ return data;
19273
+ });
19418
19274
  }
19419
19275
  stop() {
19420
19276
  if (this.originalPush) {
@@ -19461,27 +19317,52 @@ class MonitorService {
19461
19317
  this.implementedMonitor.start();
19462
19318
  }
19463
19319
  async matchAndFireEvent(eventData, spots) {
19464
- var _a, _b;
19320
+ var _a;
19465
19321
  if (!spots)
19466
19322
  return;
19467
- const eventProductIds = new Set(cleanProductIds(eventData.productIds));
19468
19323
  for (const spot of Object.values(spots)) {
19469
19324
  if (!spot.productIds.length)
19470
19325
  continue;
19471
- const hasCommonProductIds = cleanProductIds(spot.productIds).find((productId) => eventProductIds.has(productId));
19472
- if (!hasCommonProductIds || !Object.values(exports.RMN_SPOT_EVENT).includes(eventData.event)) {
19473
- continue;
19326
+ for (const data of eventData.products) {
19327
+ if (!Object.values(exports.RMN_SPOT_EVENT).includes(eventData.event)) {
19328
+ continue;
19329
+ }
19330
+ const spotRelatedProductIdsSet = new Set(cleanProductIds(spot.productIds));
19331
+ const [eventProductId] = cleanProductIds([data.id]);
19332
+ const [eventProductBrand] = cleanProductIds([data.brand]);
19333
+ const [eventVariantBrand] = cleanProductIds([data.variant]);
19334
+ const isProductMatch = [eventProductId, eventProductBrand, eventVariantBrand].some((id) => spotRelatedProductIdsSet.has(id));
19335
+ if (!isProductMatch) {
19336
+ continue;
19337
+ }
19338
+ const eventPosition = spot.events.findIndex((event) => event.event === eventData.event);
19339
+ if (eventPosition === -1)
19340
+ continue;
19341
+ const eventUrl = spot.events[eventPosition].url;
19342
+ let additionalQueryParams = '';
19343
+ if (eventData.event === exports.RMN_SPOT_EVENT.PURCHASE) {
19344
+ const gmv = data.price && data.quantity ? data.price * data.quantity : undefined;
19345
+ // gmv = gross merchandise value, it is calculated by multiplying the product price by the product quantity
19346
+ additionalQueryParams = objectToQueryParams({ gmv });
19347
+ }
19348
+ // Fire the event and publish it to the pubsub service
19349
+ await this.fireAndPublishSpotEvent({
19350
+ spotEvent: eventData.event,
19351
+ eventUrl: `${eventUrl}${additionalQueryParams ? `&${additionalQueryParams}` : ''}`,
19352
+ placementId: spot.placementId,
19353
+ spotId: spot.spotId,
19354
+ });
19355
+ // Remove the event url from the spot to prevent duplicate events
19356
+ spot.events[eventPosition].url = '';
19357
+ // Update the spots in the local storage
19358
+ (_a = this.localStorageService) === null || _a === void 0 ? void 0 : _a.setSpot(spot.spotId, {
19359
+ placementId: spot.placementId,
19360
+ spotId: spot.spotId,
19361
+ spotType: spot.spotType,
19362
+ events: spot.events,
19363
+ productIds: spot.productIds,
19364
+ });
19474
19365
  }
19475
- const eventUrl = (_b = (_a = spot.events.find((event) => event.event === eventData.event)) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : '';
19476
- const additionalQueryParams = objectToQueryParams({
19477
- override: eventData.productPrice,
19478
- });
19479
- await this.fireAndPublishSpotEvent({
19480
- spotEvent: eventData.event,
19481
- eventUrl: `${eventUrl}${additionalQueryParams ? `&${additionalQueryParams}` : ''}`,
19482
- placementId: spot.placementId,
19483
- spotId: spot.spotId,
19484
- });
19485
19366
  }
19486
19367
  }
19487
19368
  async fireAndPublishSpotEvent({ spotEvent, eventUrl, placementId, spotId, }) {