@absmartly/sdk-plugins 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/absmartly-cookie.min.js +1 -1
  2. package/dist/absmartly-dom-changes-core.min.js +1 -1
  3. package/dist/absmartly-dom-changes-lite.min.js +1 -1
  4. package/dist/absmartly-overrides-full.min.js +1 -1
  5. package/dist/absmartly-sdk-plugins.min.js +1 -1
  6. package/dist/absmartly-vitals.min.js +1 -1
  7. package/es/cookies/CookiePlugin.js +31 -61
  8. package/es/cookies/CookiePlugin.js.map +1 -1
  9. package/es/cookies/cookieUtils.js +82 -0
  10. package/es/cookies/cookieUtils.js.map +1 -0
  11. package/es/cookies/index.js +1 -0
  12. package/es/cookies/index.js.map +1 -1
  13. package/es/core/DOMChangesPluginLite.js +199 -103
  14. package/es/core/DOMChangesPluginLite.js.map +1 -1
  15. package/es/core/DOMManipulatorLite.js +64 -9
  16. package/es/core/DOMManipulatorLite.js.map +1 -1
  17. package/es/core/ExposureTracker.js +6 -15
  18. package/es/core/ExposureTracker.js.map +1 -1
  19. package/es/entries/dom-with-overrides-lite.js +6 -1
  20. package/es/entries/dom-with-overrides-lite.js.map +1 -1
  21. package/es/index.js +4 -0
  22. package/es/index.js.map +1 -1
  23. package/es/overrides/index.js +1 -0
  24. package/es/overrides/index.js.map +1 -1
  25. package/es/overrides/overridesUtils.js +255 -0
  26. package/es/overrides/overridesUtils.js.map +1 -0
  27. package/es/utils/debug.js +2 -1
  28. package/es/utils/debug.js.map +1 -1
  29. package/es/vitals/WebVitalsPlugin.js +65 -54
  30. package/es/vitals/WebVitalsPlugin.js.map +1 -1
  31. package/lib/cookies/CookiePlugin.d.ts +0 -3
  32. package/lib/cookies/CookiePlugin.js +31 -61
  33. package/lib/cookies/CookiePlugin.js.map +1 -1
  34. package/lib/cookies/cookieUtils.d.ts +34 -0
  35. package/lib/cookies/cookieUtils.js +90 -0
  36. package/lib/cookies/cookieUtils.js.map +1 -0
  37. package/lib/cookies/index.d.ts +2 -0
  38. package/lib/cookies/index.js +8 -1
  39. package/lib/cookies/index.js.map +1 -1
  40. package/lib/core/DOMChangesPluginLite.d.ts +1 -1
  41. package/lib/core/DOMChangesPluginLite.js +199 -103
  42. package/lib/core/DOMChangesPluginLite.js.map +1 -1
  43. package/lib/core/DOMManipulatorLite.js +64 -9
  44. package/lib/core/DOMManipulatorLite.js.map +1 -1
  45. package/lib/core/ExposureTracker.d.ts +4 -1
  46. package/lib/core/ExposureTracker.js +6 -15
  47. package/lib/core/ExposureTracker.js.map +1 -1
  48. package/lib/entries/dom-with-overrides-lite.d.ts +7 -1
  49. package/lib/entries/dom-with-overrides-lite.js +19 -1
  50. package/lib/entries/dom-with-overrides-lite.js.map +1 -1
  51. package/lib/index.d.ts +4 -0
  52. package/lib/index.js +17 -1
  53. package/lib/index.js.map +1 -1
  54. package/lib/overrides/index.d.ts +2 -0
  55. package/lib/overrides/index.js +8 -1
  56. package/lib/overrides/index.js.map +1 -1
  57. package/lib/overrides/overridesUtils.d.ts +48 -0
  58. package/lib/overrides/overridesUtils.js +263 -0
  59. package/lib/overrides/overridesUtils.js.map +1 -0
  60. package/lib/utils/debug.js +2 -1
  61. package/lib/utils/debug.js.map +1 -1
  62. package/lib/vitals/WebVitalsPlugin.d.ts +1 -2
  63. package/lib/vitals/WebVitalsPlugin.js +98 -54
  64. package/lib/vitals/WebVitalsPlugin.js.map +1 -1
  65. package/package.json +4 -1
  66. package/types/cookies/CookiePlugin.d.ts +0 -3
  67. package/types/cookies/cookieUtils.d.ts +34 -0
  68. package/types/cookies/index.d.ts +2 -0
  69. package/types/core/DOMChangesPluginLite.d.ts +1 -1
  70. package/types/core/ExposureTracker.d.ts +4 -1
  71. package/types/entries/dom-with-overrides-lite.d.ts +7 -1
  72. package/types/index.d.ts +4 -0
  73. package/types/overrides/index.d.ts +2 -0
  74. package/types/overrides/overridesUtils.d.ts +48 -0
  75. package/types/vitals/WebVitalsPlugin.d.ts +1 -2
@@ -91,7 +91,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
91
91
  this.persistenceObserver = null;
92
92
  this.reapplyingElements = new Set();
93
93
  this.reapplyLogThrottle = new Map();
94
- this.appliedStyleChanges = new Map();
94
+ this.appliedChanges = new Map();
95
95
  this.antiFlickerTimeout = null;
96
96
  this.antiFlickerStyleId = 'absmartly-antiflicker';
97
97
  this.config = {
@@ -183,10 +183,45 @@ var DOMChangesPluginLite = /** @class */ (function () {
183
183
  });
184
184
  };
185
185
  DOMChangesPluginLite.prototype.setupMutationObserver = function () {
186
- var observer = new MutationObserver(function () {
187
- // Check for pending changes that might now be applicable
188
- // Note: We don't have a centralized pending changes store in lite version,
189
- // the PendingChangeManager handles this internally
186
+ var _this = this;
187
+ var observer = new MutationObserver(function (mutations) {
188
+ // Re-apply ALL changes to elements that were replaced by React (hydration mismatch)
189
+ mutations.forEach(function (mutation) {
190
+ if (mutation.type === 'childList') {
191
+ // Check if any added nodes match our applied change selectors
192
+ mutation.addedNodes.forEach(function (node) {
193
+ if (node.nodeType === Node.ELEMENT_NODE) {
194
+ var element_1 = node;
195
+ // Check all experiments with applied changes (not just style changes)
196
+ _this.appliedChanges.forEach(function (changes, experimentName) {
197
+ changes.forEach(function (change) {
198
+ try {
199
+ // Check if this new element or any of its descendants match the selector
200
+ var matchingElements = element_1.matches(change.selector)
201
+ ? [element_1]
202
+ : Array.from(element_1.querySelectorAll(change.selector));
203
+ matchingElements.forEach(function (matchingEl) {
204
+ if (_this.config.debug) {
205
+ logDebug('[SPA-REAPPLY] Re-applying change to newly added element (React hydration recovery)', {
206
+ experimentName: experimentName,
207
+ selector: change.selector,
208
+ element: matchingEl.tagName,
209
+ changeType: change.type,
210
+ });
211
+ }
212
+ // Re-apply the change to the new element (ALL types: style, class, attribute, html, text, etc.)
213
+ _this.domManipulator.applyChange(change, experimentName);
214
+ });
215
+ }
216
+ catch (e) {
217
+ // Invalid selector, skip
218
+ }
219
+ });
220
+ });
221
+ }
222
+ });
223
+ }
224
+ });
190
225
  });
191
226
  observer.observe(document.body, {
192
227
  childList: true,
@@ -258,8 +293,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
258
293
  // Clear style managers - StyleSheetManager doesn't have a remove method
259
294
  // The stylesheets will be reused or cleared on next applyChanges
260
295
  this.styleManagers.clear();
261
- // Clear applied style changes
262
- this.appliedStyleChanges.clear();
296
+ // Clear applied changes
297
+ this.appliedChanges.clear();
263
298
  // Clear HTML injections
264
299
  this.htmlInjector.destroy();
265
300
  // Clear variant extractor cache to force re-extraction
@@ -342,8 +377,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
342
377
  };
343
378
  DOMChangesPluginLite.prototype.applyChanges = function (experimentName) {
344
379
  return __awaiter(this, void 0, void 0, function () {
345
- var startTime, currentURL, error_3, allExperiments, totalApplied, experimentStats, allExperiments_1, allExperiments_1_1, _a, expName, experimentData, currentVariant, variantData, urlFilter, globalDefaults, anyVariantMatchesURL, shouldApplyVisualChanges, changes, allVariantChanges, hasAnyChangesInAnyVariant, stats, hasImmediateTrigger, hasViewportTrigger, changes_1, changes_1_1, change, success, elements, changes_2, changes_2_1, change, hasAnyViewportTriggerInAnyVariant, hasAnyImmediateTriggerInAnyVariant, allVariantChanges_1, allVariantChanges_1_1, variantChanges, variantChanges_1, variantChanges_1_1, change, duration;
346
- var e_1, _b, e_2, _c, e_3, _d, e_4, _e, e_5, _f;
380
+ var startTime, currentURL, error_3, allExperiments, totalApplied, experimentStats, allExperiments_1, allExperiments_1_1, _a, expName, experimentData, currentVariant, variantData, urlFilter, globalDefaults, anyVariantMatchesURL, shouldApplyVisualChanges, changes, allVariantChanges, hasAnyChangesInAnyVariant, stats, changes_1, changes_1_1, change, success, elements, hasAnyViewportTriggerInAnyVariant, hasAnyImmediateTriggerInAnyVariant, allVariantsData, allVariantsData_1, allVariantsData_1_1, _b, variantIndex, variantData_1, variantChanges, variantMatchesURL, config, urlFilterConfig, variantChanges_1, variantChanges_1_1, change, duration;
381
+ var e_1, _c, e_2, _d, e_3, _e, e_4, _f;
347
382
  return __generator(this, function (_g) {
348
383
  switch (_g.label) {
349
384
  case 0:
@@ -416,8 +451,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
416
451
  }); })) || [],
417
452
  });
418
453
  }
419
- hasImmediateTrigger = false;
420
- hasViewportTrigger = false;
421
454
  // Apply visual changes only if URL matches for user's variant AND user has changes
422
455
  if (shouldApplyVisualChanges && changes && changes.length > 0) {
423
456
  try {
@@ -427,12 +460,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
427
460
  if (success) {
428
461
  totalApplied++;
429
462
  stats.success++;
430
- if (change.trigger_on_view) {
431
- hasViewportTrigger = true;
432
- }
433
- else {
434
- hasImmediateTrigger = true;
435
- }
436
463
  }
437
464
  else if (change.type !== 'create' && change.type !== 'styleRules') {
438
465
  // Track pending changes for stats
@@ -440,9 +467,6 @@ var DOMChangesPluginLite = /** @class */ (function () {
440
467
  elements = document.querySelectorAll(change.selector);
441
468
  if (elements.length === 0 && (this.config.spa || change.waitForElement)) {
442
469
  stats.pending++;
443
- if (change.trigger_on_view) {
444
- hasViewportTrigger = true;
445
- }
446
470
  }
447
471
  }
448
472
  catch (error) {
@@ -456,82 +480,106 @@ var DOMChangesPluginLite = /** @class */ (function () {
456
480
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
457
481
  finally {
458
482
  try {
459
- if (changes_1_1 && !changes_1_1.done && (_c = changes_1.return)) _c.call(changes_1);
483
+ if (changes_1_1 && !changes_1_1.done && (_d = changes_1.return)) _d.call(changes_1);
460
484
  }
461
485
  finally { if (e_2) throw e_2.error; }
462
486
  }
463
487
  }
464
488
  else if (changes && changes.length > 0) {
465
- try {
466
- // URL doesn't match for user's variant OR user has no changes
467
- // Check if user's changes have viewport trigger (if they exist)
468
- // We still need to set up tracking for SRM prevention
469
- for (changes_2 = (e_3 = void 0, __values(changes)), changes_2_1 = changes_2.next(); !changes_2_1.done; changes_2_1 = changes_2.next()) {
470
- change = changes_2_1.value;
471
- if (change.trigger_on_view) {
472
- hasViewportTrigger = true;
473
- }
474
- else {
475
- hasImmediateTrigger = true;
476
- }
477
- }
478
- }
479
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
480
- finally {
481
- try {
482
- if (changes_2_1 && !changes_2_1.done && (_d = changes_2.return)) _d.call(changes_2);
483
- }
484
- finally { if (e_3) throw e_3.error; }
485
- }
486
489
  logDebug("[ABsmartly] Experiment '".concat(expName, "' variant ").concat(currentVariant, " doesn't match URL filter or has no changes, but setting up tracking for SRM prevention"));
487
490
  }
488
- hasAnyViewportTriggerInAnyVariant = hasViewportTrigger;
489
- hasAnyImmediateTriggerInAnyVariant = hasImmediateTrigger;
490
- if (!hasViewportTrigger || !hasImmediateTrigger) {
491
- try {
492
- for (allVariantChanges_1 = (e_4 = void 0, __values(allVariantChanges)), allVariantChanges_1_1 = allVariantChanges_1.next(); !allVariantChanges_1_1.done; allVariantChanges_1_1 = allVariantChanges_1.next()) {
493
- variantChanges = allVariantChanges_1_1.value;
494
- if (variantChanges && variantChanges.length > 0) {
495
- try {
496
- for (variantChanges_1 = (e_5 = void 0, __values(variantChanges)), variantChanges_1_1 = variantChanges_1.next(); !variantChanges_1_1.done; variantChanges_1_1 = variantChanges_1.next()) {
497
- change = variantChanges_1_1.value;
498
- if (change.trigger_on_view) {
499
- hasAnyViewportTriggerInAnyVariant = true;
500
- }
501
- else {
502
- hasAnyImmediateTriggerInAnyVariant = true;
503
- }
504
- // Early exit if we found both types
505
- if (hasAnyViewportTriggerInAnyVariant && hasAnyImmediateTriggerInAnyVariant) {
506
- break;
507
- }
508
- }
491
+ hasAnyViewportTriggerInAnyVariant = false;
492
+ hasAnyImmediateTriggerInAnyVariant = false;
493
+ allVariantsData = this.variantExtractor.getAllVariantsData(expName);
494
+ if (this.config.debug) {
495
+ logDebug("[ABsmartly] Checking trigger types for experiment '".concat(expName, "' on URL: ").concat(currentURL), {
496
+ allVariantsDataSize: allVariantsData.size,
497
+ allVariantChangesLength: allVariantChanges.length,
498
+ });
499
+ // Log the structure of each variant's data
500
+ allVariantsData.forEach(function (data, idx) {
501
+ logDebug("[ABsmartly] Variant ".concat(idx, " data structure:"), {
502
+ isArray: Array.isArray(data),
503
+ isObject: typeof data === 'object',
504
+ hasUrlFilter: data && typeof data === 'object' && !Array.isArray(data) && 'urlFilter' in data,
505
+ keys: data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data) : 'N/A',
506
+ });
507
+ });
508
+ }
509
+ try {
510
+ // Loop through ALL variants (not just ones with changes)
511
+ // We need to check URL filters from the raw data, which includes variants without changes
512
+ for (allVariantsData_1 = (e_3 = void 0, __values(allVariantsData)), allVariantsData_1_1 = allVariantsData_1.next(); !allVariantsData_1_1.done; allVariantsData_1_1 = allVariantsData_1.next()) {
513
+ _b = __read(allVariantsData_1_1.value, 2), variantIndex = _b[0], variantData_1 = _b[1];
514
+ variantChanges = allVariantChanges[variantIndex];
515
+ if (!variantChanges || variantChanges.length === 0) {
516
+ continue;
517
+ }
518
+ variantMatchesURL = true;
519
+ if (variantData_1 && typeof variantData_1 === 'object' && !Array.isArray(variantData_1)) {
520
+ config = variantData_1;
521
+ if ('urlFilter' in config && config.urlFilter) {
522
+ urlFilterConfig = config;
523
+ variantMatchesURL = URLMatcher.matches(urlFilterConfig.urlFilter, currentURL);
524
+ if (this.config.debug) {
525
+ logDebug("[ABsmartly] Variant ".concat(variantIndex, " has URL filter, matches: ").concat(variantMatchesURL));
509
526
  }
510
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
511
- finally {
512
- try {
513
- if (variantChanges_1_1 && !variantChanges_1_1.done && (_f = variantChanges_1.return)) _f.call(variantChanges_1);
527
+ }
528
+ // If no urlFilter property, variantMatchesURL stays true (legacy behavior)
529
+ }
530
+ // Only collect trigger types from variants whose URL filters match
531
+ if (variantMatchesURL) {
532
+ try {
533
+ for (variantChanges_1 = (e_4 = void 0, __values(variantChanges)), variantChanges_1_1 = variantChanges_1.next(); !variantChanges_1_1.done; variantChanges_1_1 = variantChanges_1.next()) {
534
+ change = variantChanges_1_1.value;
535
+ if (change.trigger_on_view) {
536
+ hasAnyViewportTriggerInAnyVariant = true;
537
+ }
538
+ else {
539
+ hasAnyImmediateTriggerInAnyVariant = true;
540
+ }
541
+ // Early exit if we found both types
542
+ if (hasAnyViewportTriggerInAnyVariant && hasAnyImmediateTriggerInAnyVariant) {
543
+ break;
514
544
  }
515
- finally { if (e_5) throw e_5.error; }
516
545
  }
517
546
  }
518
- if (hasAnyViewportTriggerInAnyVariant && hasAnyImmediateTriggerInAnyVariant) {
519
- break;
547
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
548
+ finally {
549
+ try {
550
+ if (variantChanges_1_1 && !variantChanges_1_1.done && (_f = variantChanges_1.return)) _f.call(variantChanges_1);
551
+ }
552
+ finally { if (e_4) throw e_4.error; }
553
+ }
554
+ if (this.config.debug) {
555
+ logDebug("[ABsmartly] Variant ".concat(variantIndex, " matches URL - hasImmediate: ").concat(hasAnyImmediateTriggerInAnyVariant, ", hasViewport: ").concat(hasAnyViewportTriggerInAnyVariant));
520
556
  }
521
557
  }
522
- }
523
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
524
- finally {
525
- try {
526
- if (allVariantChanges_1_1 && !allVariantChanges_1_1.done && (_e = allVariantChanges_1.return)) _e.call(allVariantChanges_1);
558
+ else {
559
+ if (this.config.debug) {
560
+ logDebug("[ABsmartly] Variant ".concat(variantIndex, " does NOT match URL - skipping"));
561
+ }
562
+ }
563
+ if (hasAnyViewportTriggerInAnyVariant && hasAnyImmediateTriggerInAnyVariant) {
564
+ break;
527
565
  }
528
- finally { if (e_4) throw e_4.error; }
529
566
  }
530
567
  }
568
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
569
+ finally {
570
+ try {
571
+ if (allVariantsData_1_1 && !allVariantsData_1_1.done && (_e = allVariantsData_1.return)) _e.call(allVariantsData_1);
572
+ }
573
+ finally { if (e_3) throw e_3.error; }
574
+ }
575
+ if (this.config.debug) {
576
+ logDebug("[ABsmartly] Final trigger decision for '".concat(expName, "': hasImmediate=").concat(hasAnyImmediateTriggerInAnyVariant, ", hasViewport=").concat(hasAnyViewportTriggerInAnyVariant));
577
+ }
531
578
  // CRITICAL: Always register experiment for tracking if ANY variant has ANY trigger type
532
579
  // This prevents SRM even when user's variant doesn't match URL filter
580
+ // Pass the URL-filtered trigger flags to ExposureTracker
533
581
  if (hasAnyViewportTriggerInAnyVariant || hasAnyImmediateTriggerInAnyVariant) {
534
- this.exposureTracker.registerExperiment(expName, currentVariant || 0, changes || [], allVariantChanges);
582
+ this.exposureTracker.registerExperiment(expName, currentVariant || 0, changes || [], allVariantChanges, hasAnyImmediateTriggerInAnyVariant, hasAnyViewportTriggerInAnyVariant);
535
583
  }
536
584
  // Note: We do NOT call treatment() here anymore to avoid duplicate calls.
537
585
  // The ExposureTracker.registerExperiment() will call triggerExposure() internally
@@ -544,7 +592,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
544
592
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
545
593
  finally {
546
594
  try {
547
- if (allExperiments_1_1 && !allExperiments_1_1.done && (_b = allExperiments_1.return)) _b.call(allExperiments_1);
595
+ if (allExperiments_1_1 && !allExperiments_1_1.done && (_c = allExperiments_1.return)) _c.call(allExperiments_1);
548
596
  }
549
597
  finally { if (e_1) throw e_1.error; }
550
598
  }
@@ -585,7 +633,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
585
633
  * Get all experiments with their variant data and metadata
586
634
  */
587
635
  DOMChangesPluginLite.prototype.getAllExperimentsData = function () {
588
- var e_6, _a;
636
+ var e_5, _a;
589
637
  var experiments = new Map();
590
638
  var allVariants = this.variantExtractor.extractAllChanges();
591
639
  try {
@@ -619,12 +667,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
619
667
  experiments.set(expName, { variantData: variantData, urlFilter: urlFilter, globalDefaults: globalDefaults });
620
668
  }
621
669
  }
622
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
670
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
623
671
  finally {
624
672
  try {
625
673
  if (allVariants_1_1 && !allVariants_1_1.done && (_a = allVariants_1.return)) _a.call(allVariants_1);
626
674
  }
627
- finally { if (e_6) throw e_6.error; }
675
+ finally { if (e_5) throw e_5.error; }
628
676
  }
629
677
  return experiments;
630
678
  };
@@ -749,7 +797,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
749
797
  }
750
798
  };
751
799
  DOMChangesPluginLite.prototype.emit = function (event, data) {
752
- var e_7, _a;
800
+ var e_6, _a;
753
801
  var listeners = this.eventListeners.get(event) || [];
754
802
  try {
755
803
  for (var listeners_1 = __values(listeners), listeners_1_1 = listeners_1.next(); !listeners_1_1.done; listeners_1_1 = listeners_1.next()) {
@@ -762,12 +810,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
762
810
  }
763
811
  }
764
812
  }
765
- catch (e_7_1) { e_7 = { error: e_7_1 }; }
813
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
766
814
  finally {
767
815
  try {
768
816
  if (listeners_1_1 && !listeners_1_1.done && (_a = listeners_1.return)) _a.call(listeners_1);
769
817
  }
770
- finally { if (e_7) throw e_7.error; }
818
+ finally { if (e_6) throw e_6.error; }
771
819
  }
772
820
  };
773
821
  DOMChangesPluginLite.prototype.getStyleManager = function (experimentName) {
@@ -843,7 +891,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
843
891
  this.eventListeners.clear();
844
892
  this.exposedExperiments.clear();
845
893
  this.watchedElements = new WeakMap();
846
- this.appliedStyleChanges.clear();
894
+ this.appliedChanges.clear();
847
895
  this.reapplyingElements.clear();
848
896
  this.reapplyLogThrottle.clear();
849
897
  this.unregisterFromContext();
@@ -972,20 +1020,31 @@ var DOMChangesPluginLite = /** @class */ (function () {
972
1020
  this.watchedElements.set(element, experiments);
973
1021
  }
974
1022
  experiments.add(experimentName);
975
- // Store the applied style change for this experiment
976
- if (!this.appliedStyleChanges.has(experimentName)) {
977
- this.appliedStyleChanges.set(experimentName, []);
1023
+ // Store the applied change for this experiment (ALL types: style, class, attribute, html, text, etc.)
1024
+ if (!this.appliedChanges.has(experimentName)) {
1025
+ this.appliedChanges.set(experimentName, []);
978
1026
  }
979
- var changes = this.appliedStyleChanges.get(experimentName);
1027
+ var changes = this.appliedChanges.get(experimentName);
980
1028
  var isNewWatch = !changes.includes(change);
981
1029
  if (isNewWatch) {
982
1030
  changes.push(change);
983
1031
  // Only log when actually adding a new watch, not on every reapply
984
1032
  if (this.config.debug) {
985
- logDebug('[ABsmartly] Watching element for style persistence', {
1033
+ var currentStyles_1 = {};
1034
+ if (change.value && typeof change.value === 'object') {
1035
+ Object.keys(change.value).forEach(function (prop) {
1036
+ var cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();
1037
+ currentStyles_1[cssProp] = element.style.getPropertyValue(cssProp);
1038
+ });
1039
+ }
1040
+ logDebug('[WATCH-ELEMENT] Started watching element for persistence/hydration recovery', {
986
1041
  experimentName: experimentName,
987
1042
  selector: change.selector,
988
1043
  element: element.tagName,
1044
+ changeType: change.type,
1045
+ value: change.value,
1046
+ currentStyles: change.type === 'style' ? currentStyles_1 : undefined,
1047
+ timestamp: Date.now(),
989
1048
  });
990
1049
  }
991
1050
  }
@@ -1006,10 +1065,34 @@ var DOMChangesPluginLite = /** @class */ (function () {
1006
1065
  var _this = this;
1007
1066
  if (this.persistenceObserver)
1008
1067
  return;
1068
+ if (this.config.debug) {
1069
+ logDebug('[PERSISTENCE-OBSERVER] Setting up persistence observer', {
1070
+ timestamp: Date.now(),
1071
+ watchedElementsCount: this.watchedElements ? 'has WeakMap' : 'no WeakMap',
1072
+ });
1073
+ }
1009
1074
  this.persistenceObserver = new MutationObserver(function (mutations) {
1075
+ if (_this.config.debug) {
1076
+ logDebug('[MUTATION-DETECTED] Persistence observer detected mutations', {
1077
+ mutationCount: mutations.length,
1078
+ timestamp: Date.now(),
1079
+ mutations: mutations.map(function (m) {
1080
+ var _a;
1081
+ return ({
1082
+ target: m.target.tagName,
1083
+ oldValue: (_a = m.oldValue) === null || _a === void 0 ? void 0 : _a.substring(0, 100),
1084
+ });
1085
+ }),
1086
+ });
1087
+ }
1010
1088
  mutations.forEach(function (mutation) {
1011
1089
  var element = mutation.target;
1012
1090
  if (_this.reapplyingElements.has(element)) {
1091
+ if (_this.config.debug) {
1092
+ logDebug('[MUTATION-SKIP] Skipping mutation - currently reapplying', {
1093
+ element: element.tagName,
1094
+ });
1095
+ }
1013
1096
  return;
1014
1097
  }
1015
1098
  var experiments = _this.watchedElements.get(element);
@@ -1020,31 +1103,37 @@ var DOMChangesPluginLite = /** @class */ (function () {
1020
1103
  var now = Date.now();
1021
1104
  var lastLogged = _this.reapplyLogThrottle.get(elementKey) || 0;
1022
1105
  if (now - lastLogged > 5000) {
1023
- logDebug('[ABsmartly] Style mutation detected on watched element', {
1106
+ logDebug('[MUTATION-ON-WATCHED] Style mutation detected on watched element', {
1024
1107
  element: element.tagName,
1025
1108
  selector: element.getAttribute('name') || element.className,
1026
1109
  oldValue: mutation.oldValue,
1110
+ newValue: element.getAttribute('style'),
1111
+ experiments: Array.from(experiments),
1027
1112
  });
1028
1113
  _this.reapplyLogThrottle.set(elementKey, now);
1029
1114
  }
1030
1115
  }
1031
1116
  experiments.forEach(function (experimentName) {
1032
- var appliedChanges = _this.appliedStyleChanges.get(experimentName);
1117
+ var appliedChanges = _this.appliedChanges.get(experimentName);
1033
1118
  if (appliedChanges) {
1034
1119
  appliedChanges.forEach(function (change) {
1035
- var e_8, _a;
1036
- if (change.type === 'style' && element.matches(change.selector)) {
1120
+ var e_7, _a;
1121
+ // Skip the .matches() check - we already know this element should have this change
1122
+ // because we added it to watchedElements when we applied it successfully.
1123
+ // The .matches() check fails for complex selectors with parent relationships (e.g., "div > p")
1124
+ if (change.type === 'style') {
1037
1125
  var needsReapply = _this.checkStyleOverwritten(element, change.value);
1038
1126
  if (needsReapply) {
1039
1127
  _this.reapplyingElements.add(element);
1040
- _this.domManipulator.applyChange(change, experimentName);
1041
1128
  var logKey = "".concat(experimentName, "-").concat(change.selector);
1042
1129
  var now = Date.now();
1043
1130
  var lastLogged = _this.reapplyLogThrottle.get(logKey) || 0;
1044
1131
  if (_this.config.debug && now - lastLogged > 5000) {
1045
- logDebug('Reapplied style after mutation (React/framework conflict detected)', {
1132
+ logDebug('[REAPPLY-TRIGGERED] Reapplying style after mutation (React/framework conflict detected)', {
1046
1133
  experimentName: experimentName,
1047
1134
  selector: change.selector,
1135
+ element: element.tagName,
1136
+ timestamp: now,
1048
1137
  note: 'This happens when the page framework (React/Vue/etc) fights with DOM changes',
1049
1138
  });
1050
1139
  _this.reapplyLogThrottle.set(logKey, now);
@@ -1059,21 +1148,22 @@ var DOMChangesPluginLite = /** @class */ (function () {
1059
1148
  }
1060
1149
  }
1061
1150
  }
1062
- catch (e_8_1) { e_8 = { error: e_8_1 }; }
1151
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
1063
1152
  finally {
1064
1153
  try {
1065
1154
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1066
1155
  }
1067
- finally { if (e_8) throw e_8.error; }
1156
+ finally { if (e_7) throw e_7.error; }
1068
1157
  }
1069
1158
  }
1070
1159
  }
1160
+ _this.domManipulator.applyChange(change, experimentName);
1071
1161
  setTimeout(function () {
1072
1162
  _this.reapplyingElements.delete(element);
1073
1163
  }, 0);
1074
1164
  }
1075
1165
  else if (_this.config.debug) {
1076
- logDebug('[ABsmartly] Style mutation detected but no reapply needed', {
1166
+ logDebug('[MUTATION-NO-REAPPLY] Style mutation detected but no reapply needed', {
1077
1167
  experimentName: experimentName,
1078
1168
  selector: change.selector,
1079
1169
  });
@@ -1092,11 +1182,17 @@ var DOMChangesPluginLite = /** @class */ (function () {
1092
1182
  attributeOldValue: true,
1093
1183
  });
1094
1184
  if (this.config.debug) {
1095
- logDebug('[ABsmartly] Style persistence observer setup complete');
1185
+ logDebug('[PERSISTENCE-OBSERVER] Setup complete - now observing style mutations', {
1186
+ target: 'document.body',
1187
+ attributeFilter: ['style'],
1188
+ subtree: true,
1189
+ attributeOldValue: true,
1190
+ timestamp: Date.now(),
1191
+ });
1096
1192
  }
1097
1193
  };
1098
1194
  DOMChangesPluginLite.prototype.checkStyleOverwritten = function (element, expectedStyles) {
1099
- var e_9, _a;
1195
+ var e_8, _a;
1100
1196
  try {
1101
1197
  for (var _b = __values(Object.entries(expectedStyles)), _c = _b.next(); !_c.done; _c = _b.next()) {
1102
1198
  var _d = __read(_c.value, 2), prop = _d[0], value = _d[1];
@@ -1108,12 +1204,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
1108
1204
  }
1109
1205
  }
1110
1206
  }
1111
- catch (e_9_1) { e_9 = { error: e_9_1 }; }
1207
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
1112
1208
  finally {
1113
1209
  try {
1114
1210
  if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1115
1211
  }
1116
- finally { if (e_9) throw e_9.error; }
1212
+ finally { if (e_8) throw e_8.error; }
1117
1213
  }
1118
1214
  return false;
1119
1215
  };