@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
@@ -94,6 +94,9 @@ var DOMChangesPluginLite = /** @class */ (function () {
94
94
  this.persistenceManager = null;
95
95
  this.antiFlickerTimeout = null;
96
96
  this.antiFlickerStyleId = 'absmartly-antiflicker';
97
+ this.originalPushState = null;
98
+ this.originalReplaceState = null;
99
+ this.popstateHandler = null;
97
100
  this.config = {
98
101
  context: config.context,
99
102
  autoApply: (_a = config.autoApply) !== null && _a !== void 0 ? _a : true,
@@ -109,6 +112,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
109
112
  throw new Error('[ABsmartly] Context is required');
110
113
  }
111
114
  console.log("[ABsmartly] DOMChangesPluginLite v".concat(DOMChangesPluginLite.VERSION, " initialized"));
115
+ // Publish presence markers synchronously so detection tools (e.g. the
116
+ // browser extension) can see the plugin is loaded even while
117
+ // context.ready() is still pending or if initialize() later throws.
118
+ // initialize() will re-register with initialized=true on success.
119
+ this.registerWithContext(false);
120
+ this.registerGlobally(false);
112
121
  if (this.config.hideUntilReady) {
113
122
  this.hideContent();
114
123
  }
@@ -200,6 +209,10 @@ var DOMChangesPluginLite = /** @class */ (function () {
200
209
  case 4:
201
210
  error_1 = _a.sent();
202
211
  logDebug('[ABsmartly] Failed to initialize plugin:', error_1);
212
+ this.emit('error', {
213
+ type: 'initialization_error',
214
+ error: (error_1 === null || error_1 === void 0 ? void 0 : error_1.message) || String(error_1),
215
+ });
203
216
  throw error_1;
204
217
  case 5: return [2 /*return*/];
205
218
  }
@@ -209,45 +222,96 @@ var DOMChangesPluginLite = /** @class */ (function () {
209
222
  DOMChangesPluginLite.prototype.setupMutationObserver = function () {
210
223
  var _this = this;
211
224
  var observer = new MutationObserver(function (mutations) {
212
- // Re-apply ALL changes to elements that were replaced by React (hydration mismatch)
213
- mutations.forEach(function (mutation) {
214
- if (mutation.type === 'childList') {
215
- // Check if any added nodes match our applied change selectors
216
- mutation.addedNodes.forEach(function (node) {
217
- var _a;
218
- if (node.nodeType === Node.ELEMENT_NODE) {
219
- var element_1 = node;
220
- // Check all experiments with applied changes (not just style changes)
221
- var appliedChanges = ((_a = _this.persistenceManager) === null || _a === void 0 ? void 0 : _a.getAppliedChanges()) || new Map();
222
- appliedChanges.forEach(function (changes, experimentName) {
223
- changes.forEach(function (change) {
225
+ var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e;
226
+ var _f;
227
+ try {
228
+ // Re-apply ALL changes to elements that were replaced by React (hydration mismatch)
229
+ for (var mutations_1 = __values(mutations), mutations_1_1 = mutations_1.next(); !mutations_1_1.done; mutations_1_1 = mutations_1.next()) {
230
+ var mutation = mutations_1_1.value;
231
+ if (mutation.type === 'childList') {
232
+ try {
233
+ // Check if any added nodes match our applied change selectors
234
+ for (var _g = (e_2 = void 0, __values(mutation.addedNodes)), _h = _g.next(); !_h.done; _h = _g.next()) {
235
+ var node = _h.value;
236
+ if (node.nodeType === Node.ELEMENT_NODE) {
237
+ var element = node;
238
+ // Check all experiments with applied changes (not just style changes)
239
+ var appliedChanges = ((_f = _this.persistenceManager) === null || _f === void 0 ? void 0 : _f.getAppliedChanges()) || new Map();
224
240
  try {
225
- // Check if this new element or any of its descendants match the selector
226
- var matchingElements = element_1.matches(change.selector)
227
- ? [element_1]
228
- : Array.from(element_1.querySelectorAll(change.selector));
229
- matchingElements.forEach(function (matchingEl) {
230
- if (_this.config.debug) {
231
- logDebug('[SPA-REAPPLY] Re-applying change to newly added element (React hydration recovery)', {
232
- experimentName: experimentName,
233
- selector: change.selector,
234
- element: matchingEl.tagName,
235
- changeType: change.type,
236
- });
241
+ 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()) {
242
+ var _j = __read(appliedChanges_1_1.value, 2), experimentName = _j[0], changes = _j[1];
243
+ try {
244
+ 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()) {
245
+ var change = changes_1_1.value;
246
+ try {
247
+ // Check if this new element or any of its descendants match the selector
248
+ var matchingElements = element.matches(change.selector)
249
+ ? [element]
250
+ : Array.from(element.querySelectorAll(change.selector));
251
+ try {
252
+ 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()) {
253
+ var matchingEl = matchingElements_1_1.value;
254
+ if (_this.config.debug) {
255
+ logDebug('[SPA-REAPPLY] Re-applying change to newly added element (React hydration recovery)', {
256
+ experimentName: experimentName,
257
+ selector: change.selector,
258
+ element: matchingEl.tagName,
259
+ changeType: change.type,
260
+ });
261
+ }
262
+ // Re-apply the change to the new element (ALL types: style, class, attribute, html, text, etc.)
263
+ _this.domManipulator.applyChange(change, experimentName);
264
+ }
265
+ }
266
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
267
+ finally {
268
+ try {
269
+ if (matchingElements_1_1 && !matchingElements_1_1.done && (_e = matchingElements_1.return)) _e.call(matchingElements_1);
270
+ }
271
+ finally { if (e_5) throw e_5.error; }
272
+ }
273
+ }
274
+ catch (e) {
275
+ // Invalid selector, skip
276
+ }
277
+ }
237
278
  }
238
- // Re-apply the change to the new element (ALL types: style, class, attribute, html, text, etc.)
239
- _this.domManipulator.applyChange(change, experimentName);
240
- });
279
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
280
+ finally {
281
+ try {
282
+ if (changes_1_1 && !changes_1_1.done && (_d = changes_1.return)) _d.call(changes_1);
283
+ }
284
+ finally { if (e_4) throw e_4.error; }
285
+ }
286
+ }
241
287
  }
242
- catch (e) {
243
- // Invalid selector, skip
288
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
289
+ finally {
290
+ try {
291
+ if (appliedChanges_1_1 && !appliedChanges_1_1.done && (_c = appliedChanges_1.return)) _c.call(appliedChanges_1);
292
+ }
293
+ finally { if (e_3) throw e_3.error; }
244
294
  }
245
- });
246
- });
295
+ }
296
+ }
247
297
  }
248
- });
298
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
299
+ finally {
300
+ try {
301
+ if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
302
+ }
303
+ finally { if (e_2) throw e_2.error; }
304
+ }
305
+ }
249
306
  }
250
- });
307
+ }
308
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
309
+ finally {
310
+ try {
311
+ if (mutations_1_1 && !mutations_1_1.done && (_a = mutations_1.return)) _a.call(mutations_1);
312
+ }
313
+ finally { if (e_1) throw e_1.error; }
314
+ }
251
315
  });
252
316
  // Wait for document.body to exist before observing
253
317
  // This prevents "parameter 1 is not of type 'Node'" errors when SDK loads in <head>
@@ -302,24 +366,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
302
366
  });
303
367
  }); };
304
368
  // Listen to popstate (back/forward navigation)
305
- window.addEventListener('popstate', handleURLChange);
369
+ this.popstateHandler = handleURLChange;
370
+ window.addEventListener('popstate', this.popstateHandler);
306
371
  // Intercept pushState and replaceState
307
- var originalPushState = history.pushState;
308
- var originalReplaceState = history.replaceState;
309
- history.pushState = function () {
310
- var args = [];
311
- for (var _i = 0; _i < arguments.length; _i++) {
312
- args[_i] = arguments[_i];
372
+ this.originalPushState = history.pushState;
373
+ this.originalReplaceState = history.replaceState;
374
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
375
+ var self = this;
376
+ history.pushState = function (data, unused, url) {
377
+ if (self.originalPushState) {
378
+ self.originalPushState.call(history, data, unused, url);
313
379
  }
314
- originalPushState.apply(history, args);
315
380
  handleURLChange();
316
381
  };
317
- history.replaceState = function () {
318
- var args = [];
319
- for (var _i = 0; _i < arguments.length; _i++) {
320
- args[_i] = arguments[_i];
382
+ history.replaceState = function (data, unused, url) {
383
+ if (self.originalReplaceState) {
384
+ self.originalReplaceState.call(history, data, unused, url);
321
385
  }
322
- originalReplaceState.apply(history, args);
323
386
  handleURLChange();
324
387
  };
325
388
  if (this.config.debug) {
@@ -333,18 +396,14 @@ var DOMChangesPluginLite = /** @class */ (function () {
333
396
  DOMChangesPluginLite.prototype.removeAllChanges = function () {
334
397
  return __awaiter(this, void 0, void 0, function () {
335
398
  return __generator(this, function (_a) {
336
- // Clear exposed experiments - ExposureTracker will re-register on next applyChanges
399
+ // ExposureTracker will re-register on next applyChanges
337
400
  this.exposedExperiments.clear();
338
- // Clear style managers - StyleSheetManager doesn't have a remove method
339
- // The stylesheets will be reused or cleared on next applyChanges
401
+ // StyleSheetManager doesn't have a remove method, stylesheets will be reused on next applyChanges
340
402
  this.styleManagers.clear();
341
- // Clear applied changes
342
403
  if (this.persistenceManager) {
343
404
  this.persistenceManager.clearAll();
344
405
  }
345
- // Clear HTML injections
346
406
  this.htmlInjector.destroy();
347
- // Clear variant extractor cache to force re-extraction
348
407
  this.variantExtractor.clearCache();
349
408
  if (this.config.debug) {
350
409
  logDebug('[ABsmartly] All change tracking cleared for URL change');
@@ -424,10 +483,10 @@ var DOMChangesPluginLite = /** @class */ (function () {
424
483
  };
425
484
  DOMChangesPluginLite.prototype.applyChanges = function (experimentName) {
426
485
  return __awaiter(this, void 0, void 0, function () {
427
- 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;
428
- var e_1, _c, e_2, _d, e_3, _e, e_4, _f;
429
- return __generator(this, function (_g) {
430
- switch (_g.label) {
486
+ 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;
487
+ var e_6, _d, e_7, _e, e_8, _f, e_9, _g, e_10, _h;
488
+ return __generator(this, function (_j) {
489
+ switch (_j.label) {
431
490
  case 0:
432
491
  startTime = performance.now();
433
492
  currentURL = window.location.href;
@@ -442,15 +501,15 @@ var DOMChangesPluginLite = /** @class */ (function () {
442
501
  logDebug('[ABsmartly] Current URL:', currentURL);
443
502
  logDebug('[ABsmartly] Context ready:', true);
444
503
  }
445
- _g.label = 1;
504
+ _j.label = 1;
446
505
  case 1:
447
- _g.trys.push([1, 3, , 4]);
506
+ _j.trys.push([1, 3, , 4]);
448
507
  return [4 /*yield*/, this.config.context.ready()];
449
508
  case 2:
450
- _g.sent();
509
+ _j.sent();
451
510
  return [3 /*break*/, 4];
452
511
  case 3:
453
- error_3 = _g.sent();
512
+ error_3 = _j.sent();
454
513
  logDebug('[ABsmartly] Failed to wait for context ready:', error_3);
455
514
  return [2 /*return*/];
456
515
  case 4:
@@ -536,8 +595,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
536
595
  // Apply visual changes only if URL matches for user's variant AND user has changes
537
596
  if (shouldApplyVisualChanges && changes && changes.length > 0) {
538
597
  try {
539
- 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()) {
540
- change = changes_1_1.value;
598
+ 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()) {
599
+ change = changes_2_1.value;
541
600
  // Skip delete changes with viewport triggers - they must be applied AFTER exposure
542
601
  // Otherwise the element is removed before it can be observed
543
602
  if (change.type === 'delete' && change.trigger_on_view) {
@@ -567,12 +626,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
567
626
  }
568
627
  }
569
628
  }
570
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
629
+ catch (e_7_1) { e_7 = { error: e_7_1 }; }
571
630
  finally {
572
631
  try {
573
- if (changes_1_1 && !changes_1_1.done && (_d = changes_1.return)) _d.call(changes_1);
632
+ if (changes_2_1 && !changes_2_1.done && (_e = changes_2.return)) _e.call(changes_2);
574
633
  }
575
- finally { if (e_2) throw e_2.error; }
634
+ finally { if (e_7) throw e_7.error; }
576
635
  }
577
636
  }
578
637
  else if (changes && changes.length > 0) {
@@ -586,21 +645,31 @@ var DOMChangesPluginLite = /** @class */ (function () {
586
645
  allVariantsDataSize: allVariantsData.size,
587
646
  allVariantChangesLength: allVariantChanges.length,
588
647
  });
589
- // Log the structure of each variant's data
590
- allVariantsData.forEach(function (data, idx) {
591
- logDebug("[ABsmartly] Variant ".concat(idx, " data structure:"), {
592
- isArray: Array.isArray(data),
593
- isObject: typeof data === 'object',
594
- hasUrlFilter: data && typeof data === 'object' && !Array.isArray(data) && 'urlFilter' in data,
595
- keys: data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data) : 'N/A',
596
- });
597
- });
648
+ try {
649
+ // Log the structure of each variant's data
650
+ 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()) {
651
+ _b = __read(allVariantsData_1_1.value, 2), idx = _b[0], data = _b[1];
652
+ logDebug("[ABsmartly] Variant ".concat(idx, " data structure:"), {
653
+ isArray: Array.isArray(data),
654
+ isObject: typeof data === 'object',
655
+ hasUrlFilter: data && typeof data === 'object' && !Array.isArray(data) && 'urlFilter' in data,
656
+ keys: data && typeof data === 'object' && !Array.isArray(data) ? Object.keys(data) : 'N/A',
657
+ });
658
+ }
659
+ }
660
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
661
+ finally {
662
+ try {
663
+ if (allVariantsData_1_1 && !allVariantsData_1_1.done && (_f = allVariantsData_1.return)) _f.call(allVariantsData_1);
664
+ }
665
+ finally { if (e_8) throw e_8.error; }
666
+ }
598
667
  }
599
668
  try {
600
669
  // Loop through ALL variants (not just ones with changes)
601
670
  // We need to check URL filters from the raw data, which includes variants without changes
602
- 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()) {
603
- _b = __read(allVariantsData_1_1.value, 2), variantIndex = _b[0], variantData_1 = _b[1];
671
+ 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()) {
672
+ _c = __read(allVariantsData_2_1.value, 2), variantIndex = _c[0], variantData_1 = _c[1];
604
673
  variantChanges = allVariantChanges[variantIndex];
605
674
  if (!variantChanges || variantChanges.length === 0) {
606
675
  continue;
@@ -620,7 +689,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
620
689
  // Only collect trigger types from variants whose URL filters match
621
690
  if (variantMatchesURL) {
622
691
  try {
623
- 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()) {
692
+ 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()) {
624
693
  change = variantChanges_1_1.value;
625
694
  if (change.trigger_on_view) {
626
695
  hasAnyViewportTriggerInAnyVariant = true;
@@ -634,12 +703,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
634
703
  }
635
704
  }
636
705
  }
637
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
706
+ catch (e_10_1) { e_10 = { error: e_10_1 }; }
638
707
  finally {
639
708
  try {
640
- if (variantChanges_1_1 && !variantChanges_1_1.done && (_f = variantChanges_1.return)) _f.call(variantChanges_1);
709
+ if (variantChanges_1_1 && !variantChanges_1_1.done && (_h = variantChanges_1.return)) _h.call(variantChanges_1);
641
710
  }
642
- finally { if (e_4) throw e_4.error; }
711
+ finally { if (e_10) throw e_10.error; }
643
712
  }
644
713
  if (this.config.debug) {
645
714
  logDebug("[ABsmartly] Variant ".concat(variantIndex, " matches URL - hasImmediate: ").concat(hasAnyImmediateTriggerInAnyVariant, ", hasViewport: ").concat(hasAnyViewportTriggerInAnyVariant));
@@ -655,12 +724,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
655
724
  }
656
725
  }
657
726
  }
658
- catch (e_3_1) { e_3 = { error: e_3_1 }; }
727
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
659
728
  finally {
660
729
  try {
661
- if (allVariantsData_1_1 && !allVariantsData_1_1.done && (_e = allVariantsData_1.return)) _e.call(allVariantsData_1);
730
+ if (allVariantsData_2_1 && !allVariantsData_2_1.done && (_g = allVariantsData_2.return)) _g.call(allVariantsData_2);
662
731
  }
663
- finally { if (e_3) throw e_3.error; }
732
+ finally { if (e_9) throw e_9.error; }
664
733
  }
665
734
  if (this.config.debug) {
666
735
  logDebug("[TRIGGER-DETECTION] [".concat(expName, "] Final trigger decision for '").concat(expName, "':"), {
@@ -706,12 +775,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
706
775
  logExperimentSummary(expName, stats.total, stats.success, stats.pending);
707
776
  }
708
777
  }
709
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
778
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
710
779
  finally {
711
780
  try {
712
- if (allExperiments_1_1 && !allExperiments_1_1.done && (_c = allExperiments_1.return)) _c.call(allExperiments_1);
781
+ if (allExperiments_1_1 && !allExperiments_1_1.done && (_d = allExperiments_1.return)) _d.call(allExperiments_1);
713
782
  }
714
- finally { if (e_1) throw e_1.error; }
783
+ finally { if (e_6) throw e_6.error; }
715
784
  }
716
785
  duration = performance.now() - startTime;
717
786
  logPerformance('Apply changes', duration, {
@@ -751,7 +820,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
751
820
  * Get all experiments with their variant data and metadata
752
821
  */
753
822
  DOMChangesPluginLite.prototype.getAllExperimentsData = function () {
754
- var e_5, _a;
823
+ var e_11, _a;
755
824
  var experiments = new Map();
756
825
  var allVariants = this.variantExtractor.extractAllChanges();
757
826
  logDebug('[GET-EXPERIMENTS] Extracting experiment data from context', {
@@ -803,6 +872,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
803
872
  globalDefaults = {
804
873
  waitForElement: config.waitForElement,
805
874
  persistStyle: config.persistStyle,
875
+ persistAttribute: config.persistAttribute,
876
+ persistScript: config.persistScript,
806
877
  important: config.important,
807
878
  observerRoot: config.observerRoot,
808
879
  };
@@ -810,12 +881,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
810
881
  experiments.set(expName, { variantData: variantData, urlFilter: urlFilter, globalDefaults: globalDefaults });
811
882
  }
812
883
  }
813
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
884
+ catch (e_11_1) { e_11 = { error: e_11_1 }; }
814
885
  finally {
815
886
  try {
816
887
  if (allVariants_1_1 && !allVariants_1_1.done && (_a = allVariants_1.return)) _a.call(allVariants_1);
817
888
  }
818
- finally { if (e_5) throw e_5.error; }
889
+ finally { if (e_11) throw e_11.error; }
819
890
  }
820
891
  return experiments;
821
892
  };
@@ -839,8 +910,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
839
910
  }
840
911
  // Apply global defaults to each change
841
912
  return changes.map(function (change) {
842
- var _a, _b, _c, _d;
843
- 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 }));
913
+ var _a, _b, _c, _d, _e, _f;
914
+ 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 }));
844
915
  });
845
916
  };
846
917
  /**
@@ -868,14 +939,16 @@ var DOMChangesPluginLite = /** @class */ (function () {
868
939
  globalDefaults = {
869
940
  waitForElement: config.waitForElement,
870
941
  persistStyle: config.persistStyle,
942
+ persistAttribute: config.persistAttribute,
943
+ persistScript: config.persistScript,
871
944
  important: config.important,
872
945
  observerRoot: config.observerRoot,
873
946
  };
874
947
  }
875
948
  // Apply global defaults
876
949
  var processedChanges = variantChanges.map(function (change) {
877
- var _a, _b, _c, _d;
878
- 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 }));
950
+ var _a, _b, _c, _d, _e, _f;
951
+ 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 }));
879
952
  });
880
953
  processedVariants.push(processedChanges);
881
954
  };
@@ -920,12 +993,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
920
993
  change: change,
921
994
  });
922
995
  }
996
+ else {
997
+ this.emit('change_failed', {
998
+ experimentName: experimentName,
999
+ change: change,
1000
+ reason: 'selector_not_found_or_apply_failed',
1001
+ });
1002
+ }
923
1003
  return success;
924
1004
  }
925
1005
  catch (error) {
926
- if (this.config.debug) {
927
- logDebug('[ABsmartly] Error applying change:', error);
928
- }
1006
+ logDebug('[ABsmartly] Error applying change:', error);
1007
+ this.emit('error', {
1008
+ type: 'change_apply_error',
1009
+ experimentName: experimentName,
1010
+ change: change,
1011
+ error: (error === null || error === void 0 ? void 0 : error.message) || String(error),
1012
+ });
929
1013
  return false;
930
1014
  }
931
1015
  };
@@ -947,7 +1031,7 @@ var DOMChangesPluginLite = /** @class */ (function () {
947
1031
  }
948
1032
  };
949
1033
  DOMChangesPluginLite.prototype.emit = function (event, data) {
950
- var e_6, _a;
1034
+ var e_12, _a;
951
1035
  var listeners = this.eventListeners.get(event) || [];
952
1036
  try {
953
1037
  for (var listeners_1 = __values(listeners), listeners_1_1 = listeners_1.next(); !listeners_1_1.done; listeners_1_1 = listeners_1.next()) {
@@ -960,12 +1044,12 @@ var DOMChangesPluginLite = /** @class */ (function () {
960
1044
  }
961
1045
  }
962
1046
  }
963
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
1047
+ catch (e_12_1) { e_12 = { error: e_12_1 }; }
964
1048
  finally {
965
1049
  try {
966
1050
  if (listeners_1_1 && !listeners_1_1.done && (_a = listeners_1.return)) _a.call(listeners_1);
967
1051
  }
968
- finally { if (e_6) throw e_6.error; }
1052
+ finally { if (e_12) throw e_12.error; }
969
1053
  }
970
1054
  };
971
1055
  DOMChangesPluginLite.prototype.getStyleManager = function (experimentName) {
@@ -1016,10 +1100,23 @@ var DOMChangesPluginLite = /** @class */ (function () {
1016
1100
  }
1017
1101
  };
1018
1102
  DOMChangesPluginLite.prototype.destroy = function () {
1103
+ var e_13, _a;
1019
1104
  this.domManipulator.destroy();
1020
1105
  this.exposureTracker.destroy();
1021
1106
  this.htmlInjector.destroy();
1022
- this.styleManagers.forEach(function (manager) { return manager.destroy(); });
1107
+ try {
1108
+ for (var _b = __values(this.styleManagers.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
1109
+ var manager = _c.value;
1110
+ manager.destroy();
1111
+ }
1112
+ }
1113
+ catch (e_13_1) { e_13 = { error: e_13_1 }; }
1114
+ finally {
1115
+ try {
1116
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1117
+ }
1118
+ finally { if (e_13) throw e_13.error; }
1119
+ }
1023
1120
  this.styleManagers.clear();
1024
1121
  if (this.mutationObserver) {
1025
1122
  this.mutationObserver.disconnect();
@@ -1038,6 +1135,18 @@ var DOMChangesPluginLite = /** @class */ (function () {
1038
1135
  if (antiFlickerStyle) {
1039
1136
  antiFlickerStyle.remove();
1040
1137
  }
1138
+ // Restore history methods
1139
+ if (this.originalPushState) {
1140
+ history.pushState = this.originalPushState;
1141
+ }
1142
+ if (this.originalReplaceState) {
1143
+ history.replaceState = this.originalReplaceState;
1144
+ }
1145
+ // Remove popstate listener
1146
+ if (this.popstateHandler) {
1147
+ window.removeEventListener('popstate', this.popstateHandler);
1148
+ this.popstateHandler = null;
1149
+ }
1041
1150
  this.eventListeners.clear();
1042
1151
  this.exposedExperiments.clear();
1043
1152
  this.unregisterFromContext();
@@ -1047,7 +1156,8 @@ var DOMChangesPluginLite = /** @class */ (function () {
1047
1156
  logDebug('[ABsmartly] DOM Changes Plugin Lite destroyed');
1048
1157
  }
1049
1158
  };
1050
- DOMChangesPluginLite.prototype.registerWithContext = function () {
1159
+ DOMChangesPluginLite.prototype.registerWithContext = function (initialized) {
1160
+ if (initialized === void 0) { initialized = true; }
1051
1161
  if (this.config.context) {
1052
1162
  if (!this.config.context.__plugins) {
1053
1163
  this.config.context.__plugins = {};
@@ -1055,14 +1165,14 @@ var DOMChangesPluginLite = /** @class */ (function () {
1055
1165
  this.config.context.__plugins.domPlugin = {
1056
1166
  name: 'DOMChangesPluginLite',
1057
1167
  version: DOMChangesPluginLite.VERSION,
1058
- initialized: true,
1168
+ initialized: initialized,
1059
1169
  capabilities: ['spa', 'visibility'],
1060
1170
  instance: this,
1061
1171
  timestamp: Date.now(),
1062
1172
  };
1063
1173
  this.config.context.__domPlugin = this.config.context.__plugins.domPlugin;
1064
1174
  if (this.config.debug) {
1065
- logDebug('[ABsmartly] DOMChangesPluginLite registered with context at __plugins.domPlugin');
1175
+ logDebug("[ABsmartly] DOMChangesPluginLite registered with context at __plugins.domPlugin (initialized=".concat(initialized, ")"));
1066
1176
  }
1067
1177
  }
1068
1178
  };
@@ -1083,17 +1193,18 @@ var DOMChangesPluginLite = /** @class */ (function () {
1083
1193
  /**
1084
1194
  * Register plugin in global registry for detection
1085
1195
  */
1086
- DOMChangesPluginLite.prototype.registerGlobally = function () {
1196
+ DOMChangesPluginLite.prototype.registerGlobally = function (initialized) {
1197
+ if (initialized === void 0) { initialized = true; }
1087
1198
  registerPlugin('dom', {
1088
1199
  name: 'DOMChangesPluginLite',
1089
1200
  version: DOMChangesPluginLite.VERSION,
1090
- initialized: true,
1201
+ initialized: initialized,
1091
1202
  timestamp: Date.now(),
1092
1203
  capabilities: ['spa', 'visibility', 'auto-apply'],
1093
1204
  instance: this,
1094
1205
  });
1095
1206
  if (this.config.debug) {
1096
- logDebug('[ABsmartly] DOMChangesPluginLite registered in global window.__ABSMARTLY_PLUGINS__');
1207
+ logDebug("[ABsmartly] DOMChangesPluginLite registered in global window.__ABSMARTLY_PLUGINS__ (initialized=".concat(initialized, ")"));
1097
1208
  }
1098
1209
  };
1099
1210
  /**