@absmartly/sdk-plugins 1.2.2 → 1.3.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.
Files changed (124) 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-overrides-lite.min.js +1 -1
  6. package/dist/absmartly-sdk-plugins.min.js +1 -1
  7. package/dist/absmartly-vitals.min.js +1 -1
  8. package/es/analytics/AnalyticsPlugin.js +96 -0
  9. package/es/analytics/AnalyticsPlugin.js.map +1 -0
  10. package/es/analytics/index.js +2 -0
  11. package/es/analytics/index.js.map +1 -0
  12. package/es/analytics/types.js +2 -0
  13. package/es/analytics/types.js.map +1 -0
  14. package/es/cookies/CookiePlugin.js +59 -18
  15. package/es/cookies/CookiePlugin.js.map +1 -1
  16. package/es/core/DOMChangesPluginLite.js +217 -106
  17. package/es/core/DOMChangesPluginLite.js.map +1 -1
  18. package/es/core/DOMManipulatorLite.js +285 -153
  19. package/es/core/DOMManipulatorLite.js.map +1 -1
  20. package/es/core/ExposureTracker.js +310 -108
  21. package/es/core/ExposureTracker.js.map +1 -1
  22. package/es/core/HTMLInjector.js +11 -1
  23. package/es/core/HTMLInjector.js.map +1 -1
  24. package/es/core/PendingChangeManager.js +114 -54
  25. package/es/core/PendingChangeManager.js.map +1 -1
  26. package/es/generated/buildInfo.js +1 -1
  27. package/es/index.js +1 -0
  28. package/es/index.js.map +1 -1
  29. package/es/overrides/BrowserCookieAdapter.js +3 -31
  30. package/es/overrides/BrowserCookieAdapter.js.map +1 -1
  31. package/es/overrides/OverridesPlugin.js +39 -107
  32. package/es/overrides/OverridesPlugin.js.map +1 -1
  33. package/es/overrides/OverridesPluginLite.js +5 -136
  34. package/es/overrides/OverridesPluginLite.js.map +1 -1
  35. package/es/parsers/VariantExtractor.js +21 -18
  36. package/es/parsers/VariantExtractor.js.map +1 -1
  37. package/es/url-redirect/URLRedirectExtractor.js +8 -2
  38. package/es/url-redirect/URLRedirectExtractor.js.map +1 -1
  39. package/es/url-redirect/URLRedirectMatcher.js +130 -0
  40. package/es/url-redirect/URLRedirectMatcher.js.map +1 -1
  41. package/es/url-redirect/URLRedirectPlugin.js +14 -5
  42. package/es/url-redirect/URLRedirectPlugin.js.map +1 -1
  43. package/es/utils/URLMatcher.js.map +1 -1
  44. package/es/utils/debug.js +11 -0
  45. package/es/utils/debug.js.map +1 -1
  46. package/es/utils/persistence.js +143 -75
  47. package/es/utils/persistence.js.map +1 -1
  48. package/es/utils/plugin-registry.js.map +1 -1
  49. package/es/vitals/WebVitalsPlugin.js +9 -4
  50. package/es/vitals/WebVitalsPlugin.js.map +1 -1
  51. package/lib/analytics/AnalyticsPlugin.d.ts +8 -0
  52. package/lib/analytics/AnalyticsPlugin.js +99 -0
  53. package/lib/analytics/AnalyticsPlugin.js.map +1 -0
  54. package/lib/analytics/index.d.ts +2 -0
  55. package/lib/analytics/index.js +6 -0
  56. package/lib/analytics/index.js.map +1 -0
  57. package/lib/analytics/types.d.ts +5 -0
  58. package/lib/analytics/types.js +3 -0
  59. package/lib/analytics/types.js.map +1 -0
  60. package/lib/cookies/CookiePlugin.js +59 -18
  61. package/lib/cookies/CookiePlugin.js.map +1 -1
  62. package/lib/core/DOMChangesPluginLite.d.ts +5 -2
  63. package/lib/core/DOMChangesPluginLite.js +217 -106
  64. package/lib/core/DOMChangesPluginLite.js.map +1 -1
  65. package/lib/core/DOMManipulatorLite.d.ts +24 -0
  66. package/lib/core/DOMManipulatorLite.js +284 -152
  67. package/lib/core/DOMManipulatorLite.js.map +1 -1
  68. package/lib/core/ExposureTracker.js +310 -108
  69. package/lib/core/ExposureTracker.js.map +1 -1
  70. package/lib/core/HTMLInjector.d.ts +1 -0
  71. package/lib/core/HTMLInjector.js +11 -1
  72. package/lib/core/HTMLInjector.js.map +1 -1
  73. package/lib/core/PendingChangeManager.js +114 -54
  74. package/lib/core/PendingChangeManager.js.map +1 -1
  75. package/lib/generated/buildInfo.d.ts +1 -1
  76. package/lib/generated/buildInfo.js +1 -1
  77. package/lib/index.d.ts +2 -0
  78. package/lib/index.js +3 -1
  79. package/lib/index.js.map +1 -1
  80. package/lib/overrides/BrowserCookieAdapter.js +3 -31
  81. package/lib/overrides/BrowserCookieAdapter.js.map +1 -1
  82. package/lib/overrides/OverridesPlugin.js +39 -107
  83. package/lib/overrides/OverridesPlugin.js.map +1 -1
  84. package/lib/overrides/OverridesPluginLite.d.ts +5 -1
  85. package/lib/overrides/OverridesPluginLite.js +5 -136
  86. package/lib/overrides/OverridesPluginLite.js.map +1 -1
  87. package/lib/parsers/VariantExtractor.js +21 -18
  88. package/lib/parsers/VariantExtractor.js.map +1 -1
  89. package/lib/types/index.d.ts +5 -0
  90. package/lib/url-redirect/URLRedirectExtractor.js +8 -2
  91. package/lib/url-redirect/URLRedirectExtractor.js.map +1 -1
  92. package/lib/url-redirect/URLRedirectMatcher.d.ts +3 -0
  93. package/lib/url-redirect/URLRedirectMatcher.js +130 -0
  94. package/lib/url-redirect/URLRedirectMatcher.js.map +1 -1
  95. package/lib/url-redirect/URLRedirectPlugin.js +13 -4
  96. package/lib/url-redirect/URLRedirectPlugin.js.map +1 -1
  97. package/lib/url-redirect/types.d.ts +1 -1
  98. package/lib/utils/URLMatcher.d.ts +1 -7
  99. package/lib/utils/URLMatcher.js.map +1 -1
  100. package/lib/utils/debug.d.ts +5 -0
  101. package/lib/utils/debug.js +12 -0
  102. package/lib/utils/debug.js.map +1 -1
  103. package/lib/utils/persistence.js +143 -75
  104. package/lib/utils/persistence.js.map +1 -1
  105. package/lib/utils/plugin-registry.d.ts +1 -0
  106. package/lib/utils/plugin-registry.js.map +1 -1
  107. package/lib/vitals/WebVitalsPlugin.js +9 -4
  108. package/lib/vitals/WebVitalsPlugin.js.map +1 -1
  109. package/package.json +13 -3
  110. package/types/analytics/AnalyticsPlugin.d.ts +8 -0
  111. package/types/analytics/index.d.ts +2 -0
  112. package/types/analytics/types.d.ts +5 -0
  113. package/types/core/DOMChangesPluginLite.d.ts +5 -2
  114. package/types/core/DOMManipulatorLite.d.ts +24 -0
  115. package/types/core/HTMLInjector.d.ts +1 -0
  116. package/types/generated/buildInfo.d.ts +1 -1
  117. package/types/index.d.ts +2 -0
  118. package/types/overrides/OverridesPluginLite.d.ts +5 -1
  119. package/types/types/index.d.ts +5 -0
  120. package/types/url-redirect/URLRedirectMatcher.d.ts +3 -0
  121. package/types/url-redirect/types.d.ts +1 -1
  122. package/types/utils/URLMatcher.d.ts +1 -7
  123. package/types/utils/debug.d.ts +5 -0
  124. package/types/utils/plugin-registry.d.ts +1 -0
@@ -97,6 +97,9 @@ var DOMChangesPluginLite = /** @class */ (function () {
97
97
  this.persistenceManager = null;
98
98
  this.antiFlickerTimeout = null;
99
99
  this.antiFlickerStyleId = 'absmartly-antiflicker';
100
+ this.originalPushState = null;
101
+ this.originalReplaceState = null;
102
+ this.popstateHandler = null;
100
103
  this.config = {
101
104
  context: config.context,
102
105
  autoApply: (_a = config.autoApply) !== null && _a !== void 0 ? _a : true,
@@ -112,6 +115,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
112
115
  throw new Error('[ABsmartly] Context is required');
113
116
  }
114
117
  console.log("[ABsmartly] DOMChangesPluginLite v".concat(DOMChangesPluginLite.VERSION, " initialized"));
118
+ // Publish presence markers synchronously so detection tools (e.g. the
119
+ // browser extension) can see the plugin is loaded even while
120
+ // context.ready() is still pending or if initialize() later throws.
121
+ // initialize() will re-register with initialized=true on success.
122
+ this.registerWithContext(false);
123
+ this.registerGlobally(false);
115
124
  if (this.config.hideUntilReady) {
116
125
  this.hideContent();
117
126
  }
@@ -203,6 +212,10 @@ var DOMChangesPluginLite = /** @class */ (function () {
203
212
  case 4:
204
213
  error_1 = _a.sent();
205
214
  (0, debug_1.logDebug)('[ABsmartly] Failed to initialize plugin:', error_1);
215
+ this.emit('error', {
216
+ type: 'initialization_error',
217
+ error: (error_1 === null || error_1 === void 0 ? void 0 : error_1.message) || String(error_1),
218
+ });
206
219
  throw error_1;
207
220
  case 5: return [2 /*return*/];
208
221
  }
@@ -212,45 +225,96 @@ var DOMChangesPluginLite = /** @class */ (function () {
212
225
  DOMChangesPluginLite.prototype.setupMutationObserver = function () {
213
226
  var _this = this;
214
227
  var observer = new MutationObserver(function (mutations) {
215
- // Re-apply ALL changes to elements that were replaced by React (hydration mismatch)
216
- mutations.forEach(function (mutation) {
217
- if (mutation.type === 'childList') {
218
- // Check if any added nodes match our applied change selectors
219
- mutation.addedNodes.forEach(function (node) {
220
- var _a;
221
- if (node.nodeType === Node.ELEMENT_NODE) {
222
- var element_1 = node;
223
- // Check all experiments with applied changes (not just style changes)
224
- var appliedChanges = ((_a = _this.persistenceManager) === null || _a === void 0 ? void 0 : _a.getAppliedChanges()) || new Map();
225
- appliedChanges.forEach(function (changes, experimentName) {
226
- changes.forEach(function (change) {
228
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e;
229
+ var _f;
230
+ try {
231
+ // Re-apply ALL changes to elements that were replaced by React (hydration mismatch)
232
+ for (var mutations_1 = __values(mutations), mutations_1_1 = mutations_1.next(); !mutations_1_1.done; mutations_1_1 = mutations_1.next()) {
233
+ var mutation = mutations_1_1.value;
234
+ if (mutation.type === 'childList') {
235
+ try {
236
+ // Check if any added nodes match our applied change selectors
237
+ for (var _g = (e_2 = void 0, __values(mutation.addedNodes)), _h = _g.next(); !_h.done; _h = _g.next()) {
238
+ var node = _h.value;
239
+ if (node.nodeType === Node.ELEMENT_NODE) {
240
+ var element = node;
241
+ // Check all experiments with applied changes (not just style changes)
242
+ var appliedChanges = ((_f = _this.persistenceManager) === null || _f === void 0 ? void 0 : _f.getAppliedChanges()) || new Map();
227
243
  try {
228
- // Check if this new element or any of its descendants match the selector
229
- var matchingElements = element_1.matches(change.selector)
230
- ? [element_1]
231
- : Array.from(element_1.querySelectorAll(change.selector));
232
- matchingElements.forEach(function (matchingEl) {
233
- if (_this.config.debug) {
234
- (0, debug_1.logDebug)('[SPA-REAPPLY] Re-applying change to newly added element (React hydration recovery)', {
235
- experimentName: experimentName,
236
- selector: change.selector,
237
- element: matchingEl.tagName,
238
- changeType: change.type,
239
- });
244
+ for (var appliedChanges_1 = (e_3 = void 0, __values(appliedChanges)), appliedChanges_1_1 = appliedChanges_1.next(); !appliedChanges_1_1.done; appliedChanges_1_1 = appliedChanges_1.next()) {
245
+ var _j = __read(appliedChanges_1_1.value, 2), experimentName = _j[0], changes = _j[1];
246
+ try {
247
+ for (var changes_1 = (e_4 = void 0, __values(changes)), changes_1_1 = changes_1.next(); !changes_1_1.done; changes_1_1 = changes_1.next()) {
248
+ var change = changes_1_1.value;
249
+ try {
250
+ // Check if this new element or any of its descendants match the selector
251
+ var matchingElements = element.matches(change.selector)
252
+ ? [element]
253
+ : Array.from(element.querySelectorAll(change.selector));
254
+ try {
255
+ for (var matchingElements_1 = (e_5 = void 0, __values(matchingElements)), matchingElements_1_1 = matchingElements_1.next(); !matchingElements_1_1.done; matchingElements_1_1 = matchingElements_1.next()) {
256
+ var matchingEl = matchingElements_1_1.value;
257
+ if (_this.config.debug) {
258
+ (0, debug_1.logDebug)('[SPA-REAPPLY] Re-applying change to newly added element (React hydration recovery)', {
259
+ experimentName: experimentName,
260
+ selector: change.selector,
261
+ element: matchingEl.tagName,
262
+ changeType: change.type,
263
+ });
264
+ }
265
+ // Re-apply the change to the new element (ALL types: style, class, attribute, html, text, etc.)
266
+ _this.domManipulator.applyChange(change, experimentName);
267
+ }
268
+ }
269
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
270
+ finally {
271
+ try {
272
+ if (matchingElements_1_1 && !matchingElements_1_1.done && (_e = matchingElements_1.return)) _e.call(matchingElements_1);
273
+ }
274
+ finally { if (e_5) throw e_5.error; }
275
+ }
276
+ }
277
+ catch (e) {
278
+ // Invalid selector, skip
279
+ }
280
+ }
240
281
  }
241
- // Re-apply the change to the new element (ALL types: style, class, attribute, html, text, etc.)
242
- _this.domManipulator.applyChange(change, experimentName);
243
- });
282
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
283
+ finally {
284
+ try {
285
+ if (changes_1_1 && !changes_1_1.done && (_d = changes_1.return)) _d.call(changes_1);
286
+ }
287
+ finally { if (e_4) throw e_4.error; }
288
+ }
289
+ }
244
290
  }
245
- catch (e) {
246
- // Invalid selector, skip
291
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
292
+ finally {
293
+ try {
294
+ if (appliedChanges_1_1 && !appliedChanges_1_1.done && (_c = appliedChanges_1.return)) _c.call(appliedChanges_1);
295
+ }
296
+ finally { if (e_3) throw e_3.error; }
247
297
  }
248
- });
249
- });
298
+ }
299
+ }
250
300
  }
251
- });
301
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
302
+ finally {
303
+ try {
304
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
305
+ }
306
+ finally { if (e_2) throw e_2.error; }
307
+ }
308
+ }
252
309
  }
253
- });
310
+ }
311
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
312
+ finally {
313
+ try {
314
+ if (mutations_1_1 && !mutations_1_1.done && (_a = mutations_1.return)) _a.call(mutations_1);
315
+ }
316
+ finally { if (e_1) throw e_1.error; }
317
+ }
254
318
  });
255
319
  // Wait for document.body to exist before observing
256
320
  // This prevents "parameter 1 is not of type 'Node'" errors when SDK loads in <head>
@@ -305,24 +369,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
305
369
  });
306
370
  }); };
307
371
  // Listen to popstate (back/forward navigation)
308
- window.addEventListener('popstate', handleURLChange);
372
+ this.popstateHandler = handleURLChange;
373
+ window.addEventListener('popstate', this.popstateHandler);
309
374
  // Intercept pushState and replaceState
310
- var originalPushState = history.pushState;
311
- var originalReplaceState = history.replaceState;
312
- history.pushState = function () {
313
- var args = [];
314
- for (var _i = 0; _i < arguments.length; _i++) {
315
- args[_i] = arguments[_i];
375
+ this.originalPushState = history.pushState;
376
+ this.originalReplaceState = history.replaceState;
377
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
378
+ var self = this;
379
+ history.pushState = function (data, unused, url) {
380
+ if (self.originalPushState) {
381
+ self.originalPushState.call(history, data, unused, url);
316
382
  }
317
- originalPushState.apply(history, args);
318
383
  handleURLChange();
319
384
  };
320
- history.replaceState = function () {
321
- var args = [];
322
- for (var _i = 0; _i < arguments.length; _i++) {
323
- args[_i] = arguments[_i];
385
+ history.replaceState = function (data, unused, url) {
386
+ if (self.originalReplaceState) {
387
+ self.originalReplaceState.call(history, data, unused, url);
324
388
  }
325
- originalReplaceState.apply(history, args);
326
389
  handleURLChange();
327
390
  };
328
391
  if (this.config.debug) {
@@ -336,18 +399,14 @@ var DOMChangesPluginLite = /** @class */ (function () {
336
399
  DOMChangesPluginLite.prototype.removeAllChanges = function () {
337
400
  return __awaiter(this, void 0, void 0, function () {
338
401
  return __generator(this, function (_a) {
339
- // Clear exposed experiments - ExposureTracker will re-register on next applyChanges
402
+ // ExposureTracker will re-register on next applyChanges
340
403
  this.exposedExperiments.clear();
341
- // Clear style managers - StyleSheetManager doesn't have a remove method
342
- // The stylesheets will be reused or cleared on next applyChanges
404
+ // StyleSheetManager doesn't have a remove method, stylesheets will be reused on next applyChanges
343
405
  this.styleManagers.clear();
344
- // Clear applied changes
345
406
  if (this.persistenceManager) {
346
407
  this.persistenceManager.clearAll();
347
408
  }
348
- // Clear HTML injections
349
409
  this.htmlInjector.destroy();
350
- // Clear variant extractor cache to force re-extraction
351
410
  this.variantExtractor.clearCache();
352
411
  if (this.config.debug) {
353
412
  (0, debug_1.logDebug)('[ABsmartly] All change tracking cleared for URL change');
@@ -427,10 +486,10 @@ var DOMChangesPluginLite = /** @class */ (function () {
427
486
  };
428
487
  DOMChangesPluginLite.prototype.applyChanges = function (experimentName) {
429
488
  return __awaiter(this, void 0, void 0, function () {
430
- 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;
431
- var e_1, _c, e_2, _d, e_3, _e, e_4, _f;
432
- return __generator(this, function (_g) {
433
- switch (_g.label) {
489
+ 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_2, changes_2_1, change, success, elements, hasAnyViewportTriggerInAnyVariant, hasAnyImmediateTriggerInAnyVariant, allVariantsData, allVariantsData_1, allVariantsData_1_1, _b, idx, data, allVariantsData_2, allVariantsData_2_1, _c, variantIndex, variantData_1, variantChanges, variantMatchesURL, config, urlFilterConfig, variantChanges_1, variantChanges_1_1, change, duration;
490
+ var e_6, _d, e_7, _e, e_8, _f, e_9, _g, e_10, _h;
491
+ return __generator(this, function (_j) {
492
+ switch (_j.label) {
434
493
  case 0:
435
494
  startTime = performance.now();
436
495
  currentURL = window.location.href;
@@ -445,15 +504,15 @@ var DOMChangesPluginLite = /** @class */ (function () {
445
504
  (0, debug_1.logDebug)('[ABsmartly] Current URL:', currentURL);
446
505
  (0, debug_1.logDebug)('[ABsmartly] Context ready:', true);
447
506
  }
448
- _g.label = 1;
507
+ _j.label = 1;
449
508
  case 1:
450
- _g.trys.push([1, 3, , 4]);
509
+ _j.trys.push([1, 3, , 4]);
451
510
  return [4 /*yield*/, this.config.context.ready()];
452
511
  case 2:
453
- _g.sent();
512
+ _j.sent();
454
513
  return [3 /*break*/, 4];
455
514
  case 3:
456
- error_3 = _g.sent();
515
+ error_3 = _j.sent();
457
516
  (0, debug_1.logDebug)('[ABsmartly] Failed to wait for context ready:', error_3);
458
517
  return [2 /*return*/];
459
518
  case 4:
@@ -539,8 +598,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
539
598
  // Apply visual changes only if URL matches for user's variant AND user has changes
540
599
  if (shouldApplyVisualChanges && changes && changes.length > 0) {
541
600
  try {
542
- for (changes_1 = (e_2 = void 0, __values(changes)), changes_1_1 = changes_1.next(); !changes_1_1.done; changes_1_1 = changes_1.next()) {
543
- change = changes_1_1.value;
601
+ for (changes_2 = (e_7 = void 0, __values(changes)), changes_2_1 = changes_2.next(); !changes_2_1.done; changes_2_1 = changes_2.next()) {
602
+ change = changes_2_1.value;
544
603
  // Skip delete changes with viewport triggers - they must be applied AFTER exposure
545
604
  // Otherwise the element is removed before it can be observed
546
605
  if (change.type === 'delete' && change.trigger_on_view) {
@@ -570,12 +629,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
570
629
  }
571
630
  }
572
631
  }
573
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
632
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
574
633
  finally {
575
634
  try {
576
- if (changes_1_1 && !changes_1_1.done && (_d = changes_1.return)) _d.call(changes_1);
635
+ if (changes_2_1 && !changes_2_1.done && (_e = changes_2.return)) _e.call(changes_2);
577
636
  }
578
- finally { if (e_2) throw e_2.error; }
637
+ finally { if (e_7) throw e_7.error; }
579
638
  }
580
639
  }
581
640
  else if (changes && changes.length > 0) {
@@ -589,21 +648,31 @@ var DOMChangesPluginLite = /** @class */ (function () {
589
648
  allVariantsDataSize: allVariantsData.size,
590
649
  allVariantChangesLength: allVariantChanges.length,
591
650
  });
592
- // Log the structure of each variant's data
593
- allVariantsData.forEach(function (data, idx) {
594
- (0, debug_1.logDebug)("[ABsmartly] Variant ".concat(idx, " data structure:"), {
595
- isArray: Array.isArray(data),
596
- isObject: typeof data === 'object',
597
- hasUrlFilter: data && typeof data === 'object' && !Array.isArray(data) && 'urlFilter' in data,
598
- keys: data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data) : 'N/A',
599
- });
600
- });
651
+ try {
652
+ // Log the structure of each variant's data
653
+ for (allVariantsData_1 = (e_8 = void 0, __values(allVariantsData)), allVariantsData_1_1 = allVariantsData_1.next(); !allVariantsData_1_1.done; allVariantsData_1_1 = allVariantsData_1.next()) {
654
+ _b = __read(allVariantsData_1_1.value, 2), idx = _b[0], data = _b[1];
655
+ (0, debug_1.logDebug)("[ABsmartly] Variant ".concat(idx, " data structure:"), {
656
+ isArray: Array.isArray(data),
657
+ isObject: typeof data === 'object',
658
+ hasUrlFilter: data && typeof data === 'object' && !Array.isArray(data) && 'urlFilter' in data,
659
+ keys: data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data) : 'N/A',
660
+ });
661
+ }
662
+ }
663
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
664
+ finally {
665
+ try {
666
+ if (allVariantsData_1_1 && !allVariantsData_1_1.done && (_f = allVariantsData_1.return)) _f.call(allVariantsData_1);
667
+ }
668
+ finally { if (e_8) throw e_8.error; }
669
+ }
601
670
  }
602
671
  try {
603
672
  // Loop through ALL variants (not just ones with changes)
604
673
  // We need to check URL filters from the raw data, which includes variants without changes
605
- 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()) {
606
- _b = __read(allVariantsData_1_1.value, 2), variantIndex = _b[0], variantData_1 = _b[1];
674
+ for (allVariantsData_2 = (e_9 = void 0, __values(allVariantsData)), allVariantsData_2_1 = allVariantsData_2.next(); !allVariantsData_2_1.done; allVariantsData_2_1 = allVariantsData_2.next()) {
675
+ _c = __read(allVariantsData_2_1.value, 2), variantIndex = _c[0], variantData_1 = _c[1];
607
676
  variantChanges = allVariantChanges[variantIndex];
608
677
  if (!variantChanges || variantChanges.length === 0) {
609
678
  continue;
@@ -623,7 +692,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
623
692
  // Only collect trigger types from variants whose URL filters match
624
693
  if (variantMatchesURL) {
625
694
  try {
626
- 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()) {
695
+ for (variantChanges_1 = (e_10 = void 0, __values(variantChanges)), variantChanges_1_1 = variantChanges_1.next(); !variantChanges_1_1.done; variantChanges_1_1 = variantChanges_1.next()) {
627
696
  change = variantChanges_1_1.value;
628
697
  if (change.trigger_on_view) {
629
698
  hasAnyViewportTriggerInAnyVariant = true;
@@ -637,12 +706,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
637
706
  }
638
707
  }
639
708
  }
640
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
709
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
641
710
  finally {
642
711
  try {
643
- if (variantChanges_1_1 && !variantChanges_1_1.done && (_f = variantChanges_1.return)) _f.call(variantChanges_1);
712
+ if (variantChanges_1_1 && !variantChanges_1_1.done && (_h = variantChanges_1.return)) _h.call(variantChanges_1);
644
713
  }
645
- finally { if (e_4) throw e_4.error; }
714
+ finally { if (e_10) throw e_10.error; }
646
715
  }
647
716
  if (this.config.debug) {
648
717
  (0, debug_1.logDebug)("[ABsmartly] Variant ".concat(variantIndex, " matches URL - hasImmediate: ").concat(hasAnyImmediateTriggerInAnyVariant, ", hasViewport: ").concat(hasAnyViewportTriggerInAnyVariant));
@@ -658,12 +727,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
658
727
  }
659
728
  }
660
729
  }
661
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
730
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
662
731
  finally {
663
732
  try {
664
- if (allVariantsData_1_1 && !allVariantsData_1_1.done && (_e = allVariantsData_1.return)) _e.call(allVariantsData_1);
733
+ if (allVariantsData_2_1 && !allVariantsData_2_1.done && (_g = allVariantsData_2.return)) _g.call(allVariantsData_2);
665
734
  }
666
- finally { if (e_3) throw e_3.error; }
735
+ finally { if (e_9) throw e_9.error; }
667
736
  }
668
737
  if (this.config.debug) {
669
738
  (0, debug_1.logDebug)("[TRIGGER-DETECTION] [".concat(expName, "] Final trigger decision for '").concat(expName, "':"), {
@@ -709,12 +778,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
709
778
  (0, debug_1.logExperimentSummary)(expName, stats.total, stats.success, stats.pending);
710
779
  }
711
780
  }
712
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
781
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
713
782
  finally {
714
783
  try {
715
- if (allExperiments_1_1 && !allExperiments_1_1.done && (_c = allExperiments_1.return)) _c.call(allExperiments_1);
784
+ if (allExperiments_1_1 && !allExperiments_1_1.done && (_d = allExperiments_1.return)) _d.call(allExperiments_1);
716
785
  }
717
- finally { if (e_1) throw e_1.error; }
786
+ finally { if (e_6) throw e_6.error; }
718
787
  }
719
788
  duration = performance.now() - startTime;
720
789
  (0, debug_1.logPerformance)('Apply changes', duration, {
@@ -754,7 +823,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
754
823
  * Get all experiments with their variant data and metadata
755
824
  */
756
825
  DOMChangesPluginLite.prototype.getAllExperimentsData = function () {
757
- var e_5, _a;
826
+ var e_11, _a;
758
827
  var experiments = new Map();
759
828
  var allVariants = this.variantExtractor.extractAllChanges();
760
829
  (0, debug_1.logDebug)('[GET-EXPERIMENTS] Extracting experiment data from context', {
@@ -806,6 +875,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
806
875
  globalDefaults = {
807
876
  waitForElement: config.waitForElement,
808
877
  persistStyle: config.persistStyle,
878
+ persistAttribute: config.persistAttribute,
879
+ persistScript: config.persistScript,
809
880
  important: config.important,
810
881
  observerRoot: config.observerRoot,
811
882
  };
@@ -813,12 +884,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
813
884
  experiments.set(expName, { variantData: variantData, urlFilter: urlFilter, globalDefaults: globalDefaults });
814
885
  }
815
886
  }
816
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
887
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
817
888
  finally {
818
889
  try {
819
890
  if (allVariants_1_1 && !allVariants_1_1.done && (_a = allVariants_1.return)) _a.call(allVariants_1);
820
891
  }
821
- finally { if (e_5) throw e_5.error; }
892
+ finally { if (e_11) throw e_11.error; }
822
893
  }
823
894
  return experiments;
824
895
  };
@@ -842,8 +913,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
842
913
  }
843
914
  // Apply global defaults to each change
844
915
  return changes.map(function (change) {
845
- var _a, _b, _c, _d;
846
- return (__assign(__assign({}, change), { waitForElement: (_a = change.waitForElement) !== null && _a !== void 0 ? _a : globalDefaults.waitForElement, persistStyle: (_b = change.persistStyle) !== null && _b !== void 0 ? _b : globalDefaults.persistStyle, important: (_c = change.important) !== null && _c !== void 0 ? _c : globalDefaults.important, observerRoot: (_d = change.observerRoot) !== null && _d !== void 0 ? _d : globalDefaults.observerRoot }));
916
+ var _a, _b, _c, _d, _e, _f;
917
+ return (__assign(__assign({}, change), { waitForElement: (_a = change.waitForElement) !== null && _a !== void 0 ? _a : globalDefaults.waitForElement, persistStyle: (_b = change.persistStyle) !== null && _b !== void 0 ? _b : globalDefaults.persistStyle, persistAttribute: (_c = change.persistAttribute) !== null && _c !== void 0 ? _c : globalDefaults.persistAttribute, persistScript: (_d = change.persistScript) !== null && _d !== void 0 ? _d : globalDefaults.persistScript, important: (_e = change.important) !== null && _e !== void 0 ? _e : globalDefaults.important, observerRoot: (_f = change.observerRoot) !== null && _f !== void 0 ? _f : globalDefaults.observerRoot }));
847
918
  });
848
919
  };
849
920
  /**
@@ -871,14 +942,16 @@ var DOMChangesPluginLite = /** @class */ (function () {
871
942
  globalDefaults = {
872
943
  waitForElement: config.waitForElement,
873
944
  persistStyle: config.persistStyle,
945
+ persistAttribute: config.persistAttribute,
946
+ persistScript: config.persistScript,
874
947
  important: config.important,
875
948
  observerRoot: config.observerRoot,
876
949
  };
877
950
  }
878
951
  // Apply global defaults
879
952
  var processedChanges = variantChanges.map(function (change) {
880
- var _a, _b, _c, _d;
881
- return (__assign(__assign({}, change), { waitForElement: (_a = change.waitForElement) !== null && _a !== void 0 ? _a : globalDefaults.waitForElement, persistStyle: (_b = change.persistStyle) !== null && _b !== void 0 ? _b : globalDefaults.persistStyle, important: (_c = change.important) !== null && _c !== void 0 ? _c : globalDefaults.important, observerRoot: (_d = change.observerRoot) !== null && _d !== void 0 ? _d : globalDefaults.observerRoot }));
953
+ var _a, _b, _c, _d, _e, _f;
954
+ return (__assign(__assign({}, change), { waitForElement: (_a = change.waitForElement) !== null && _a !== void 0 ? _a : globalDefaults.waitForElement, persistStyle: (_b = change.persistStyle) !== null && _b !== void 0 ? _b : globalDefaults.persistStyle, persistAttribute: (_c = change.persistAttribute) !== null && _c !== void 0 ? _c : globalDefaults.persistAttribute, persistScript: (_d = change.persistScript) !== null && _d !== void 0 ? _d : globalDefaults.persistScript, important: (_e = change.important) !== null && _e !== void 0 ? _e : globalDefaults.important, observerRoot: (_f = change.observerRoot) !== null && _f !== void 0 ? _f : globalDefaults.observerRoot }));
882
955
  });
883
956
  processedVariants.push(processedChanges);
884
957
  };
@@ -923,12 +996,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
923
996
  change: change,
924
997
  });
925
998
  }
999
+ else {
1000
+ this.emit('change_failed', {
1001
+ experimentName: experimentName,
1002
+ change: change,
1003
+ reason: 'selector_not_found_or_apply_failed',
1004
+ });
1005
+ }
926
1006
  return success;
927
1007
  }
928
1008
  catch (error) {
929
- if (this.config.debug) {
930
- (0, debug_1.logDebug)('[ABsmartly] Error applying change:', error);
931
- }
1009
+ (0, debug_1.logDebug)('[ABsmartly] Error applying change:', error);
1010
+ this.emit('error', {
1011
+ type: 'change_apply_error',
1012
+ experimentName: experimentName,
1013
+ change: change,
1014
+ error: (error === null || error === void 0 ? void 0 : error.message) || String(error),
1015
+ });
932
1016
  return false;
933
1017
  }
934
1018
  };
@@ -950,7 +1034,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
950
1034
  }
951
1035
  };
952
1036
  DOMChangesPluginLite.prototype.emit = function (event, data) {
953
- var e_6, _a;
1037
+ var e_12, _a;
954
1038
  var listeners = this.eventListeners.get(event) || [];
955
1039
  try {
956
1040
  for (var listeners_1 = __values(listeners), listeners_1_1 = listeners_1.next(); !listeners_1_1.done; listeners_1_1 = listeners_1.next()) {
@@ -963,12 +1047,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
963
1047
  }
964
1048
  }
965
1049
  }
966
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
1050
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
967
1051
  finally {
968
1052
  try {
969
1053
  if (listeners_1_1 && !listeners_1_1.done && (_a = listeners_1.return)) _a.call(listeners_1);
970
1054
  }
971
- finally { if (e_6) throw e_6.error; }
1055
+ finally { if (e_12) throw e_12.error; }
972
1056
  }
973
1057
  };
974
1058
  DOMChangesPluginLite.prototype.getStyleManager = function (experimentName) {
@@ -1019,10 +1103,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
1019
1103
  }
1020
1104
  };
1021
1105
  DOMChangesPluginLite.prototype.destroy = function () {
1106
+ var e_13, _a;
1022
1107
  this.domManipulator.destroy();
1023
1108
  this.exposureTracker.destroy();
1024
1109
  this.htmlInjector.destroy();
1025
- this.styleManagers.forEach(function (manager) { return manager.destroy(); });
1110
+ try {
1111
+ for (var _b = __values(this.styleManagers.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
1112
+ var manager = _c.value;
1113
+ manager.destroy();
1114
+ }
1115
+ }
1116
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
1117
+ finally {
1118
+ try {
1119
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1120
+ }
1121
+ finally { if (e_13) throw e_13.error; }
1122
+ }
1026
1123
  this.styleManagers.clear();
1027
1124
  if (this.mutationObserver) {
1028
1125
  this.mutationObserver.disconnect();
@@ -1041,6 +1138,18 @@ var DOMChangesPluginLite = /** @class */ (function () {
1041
1138
  if (antiFlickerStyle) {
1042
1139
  antiFlickerStyle.remove();
1043
1140
  }
1141
+ // Restore history methods
1142
+ if (this.originalPushState) {
1143
+ history.pushState = this.originalPushState;
1144
+ }
1145
+ if (this.originalReplaceState) {
1146
+ history.replaceState = this.originalReplaceState;
1147
+ }
1148
+ // Remove popstate listener
1149
+ if (this.popstateHandler) {
1150
+ window.removeEventListener('popstate', this.popstateHandler);
1151
+ this.popstateHandler = null;
1152
+ }
1044
1153
  this.eventListeners.clear();
1045
1154
  this.exposedExperiments.clear();
1046
1155
  this.unregisterFromContext();
@@ -1050,7 +1159,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
1050
1159
  (0, debug_1.logDebug)('[ABsmartly] DOM Changes Plugin Lite destroyed');
1051
1160
  }
1052
1161
  };
1053
- DOMChangesPluginLite.prototype.registerWithContext = function () {
1162
+ DOMChangesPluginLite.prototype.registerWithContext = function (initialized) {
1163
+ if (initialized === void 0) { initialized = true; }
1054
1164
  if (this.config.context) {
1055
1165
  if (!this.config.context.__plugins) {
1056
1166
  this.config.context.__plugins = {};
@@ -1058,14 +1168,14 @@ var DOMChangesPluginLite = /** @class */ (function () {
1058
1168
  this.config.context.__plugins.domPlugin = {
1059
1169
  name: 'DOMChangesPluginLite',
1060
1170
  version: DOMChangesPluginLite.VERSION,
1061
- initialized: true,
1171
+ initialized: initialized,
1062
1172
  capabilities: ['spa', 'visibility'],
1063
1173
  instance: this,
1064
1174
  timestamp: Date.now(),
1065
1175
  };
1066
1176
  this.config.context.__domPlugin = this.config.context.__plugins.domPlugin;
1067
1177
  if (this.config.debug) {
1068
- (0, debug_1.logDebug)('[ABsmartly] DOMChangesPluginLite registered with context at __plugins.domPlugin');
1178
+ (0, debug_1.logDebug)("[ABsmartly] DOMChangesPluginLite registered with context at __plugins.domPlugin (initialized=".concat(initialized, ")"));
1069
1179
  }
1070
1180
  }
1071
1181
  };
@@ -1086,17 +1196,18 @@ var DOMChangesPluginLite = /** @class */ (function () {
1086
1196
  /**
1087
1197
  * Register plugin in global registry for detection
1088
1198
  */
1089
- DOMChangesPluginLite.prototype.registerGlobally = function () {
1199
+ DOMChangesPluginLite.prototype.registerGlobally = function (initialized) {
1200
+ if (initialized === void 0) { initialized = true; }
1090
1201
  (0, plugin_registry_1.registerPlugin)('dom', {
1091
1202
  name: 'DOMChangesPluginLite',
1092
1203
  version: DOMChangesPluginLite.VERSION,
1093
- initialized: true,
1204
+ initialized: initialized,
1094
1205
  timestamp: Date.now(),
1095
1206
  capabilities: ['spa', 'visibility', 'auto-apply'],
1096
1207
  instance: this,
1097
1208
  });
1098
1209
  if (this.config.debug) {
1099
- (0, debug_1.logDebug)('[ABsmartly] DOMChangesPluginLite registered in global window.__ABSMARTLY_PLUGINS__');
1210
+ (0, debug_1.logDebug)("[ABsmartly] DOMChangesPluginLite registered in global window.__ABSMARTLY_PLUGINS__ (initialized=".concat(initialized, ")"));
1100
1211
  }
1101
1212
  };
1102
1213
  /**