@amplitude/session-replay-browser 1.51.4 → 1.52.0-codexsemantic-review-integration.0

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 (87) hide show
  1. package/lib/cjs/config/joined-config.d.ts.map +1 -1
  2. package/lib/cjs/config/joined-config.js +25 -18
  3. package/lib/cjs/config/joined-config.js.map +1 -1
  4. package/lib/cjs/config/local-config.d.ts +3 -0
  5. package/lib/cjs/config/local-config.d.ts.map +1 -1
  6. package/lib/cjs/config/local-config.js +2 -0
  7. package/lib/cjs/config/local-config.js.map +1 -1
  8. package/lib/cjs/config/types.d.ts +6 -0
  9. package/lib/cjs/config/types.d.ts.map +1 -1
  10. package/lib/cjs/config/types.js.map +1 -1
  11. package/lib/cjs/hooks/click.d.ts +8 -2
  12. package/lib/cjs/hooks/click.d.ts.map +1 -1
  13. package/lib/cjs/hooks/click.js +42 -3
  14. package/lib/cjs/hooks/click.js.map +1 -1
  15. package/lib/cjs/plugins/url-tracking-plugin.d.ts +3 -0
  16. package/lib/cjs/plugins/url-tracking-plugin.d.ts.map +1 -1
  17. package/lib/cjs/plugins/url-tracking-plugin.js +16 -9
  18. package/lib/cjs/plugins/url-tracking-plugin.js.map +1 -1
  19. package/lib/cjs/semantic-identity.d.ts +5 -0
  20. package/lib/cjs/semantic-identity.d.ts.map +1 -0
  21. package/lib/cjs/semantic-identity.js +67 -0
  22. package/lib/cjs/semantic-identity.js.map +1 -0
  23. package/lib/cjs/semantic.d.ts +24 -0
  24. package/lib/cjs/semantic.d.ts.map +1 -0
  25. package/lib/cjs/semantic.js +131 -0
  26. package/lib/cjs/semantic.js.map +1 -0
  27. package/lib/cjs/session-replay.d.ts +4 -1
  28. package/lib/cjs/session-replay.d.ts.map +1 -1
  29. package/lib/cjs/session-replay.js +155 -80
  30. package/lib/cjs/session-replay.js.map +1 -1
  31. package/lib/cjs/utils/rrweb.d.ts +3 -0
  32. package/lib/cjs/utils/rrweb.d.ts.map +1 -1
  33. package/lib/cjs/utils/rrweb.js.map +1 -1
  34. package/lib/cjs/version.d.ts +1 -1
  35. package/lib/cjs/version.d.ts.map +1 -1
  36. package/lib/cjs/version.js +1 -1
  37. package/lib/cjs/version.js.map +1 -1
  38. package/lib/esm/config/joined-config.d.ts.map +1 -1
  39. package/lib/esm/config/joined-config.js +25 -18
  40. package/lib/esm/config/joined-config.js.map +1 -1
  41. package/lib/esm/config/local-config.d.ts +3 -0
  42. package/lib/esm/config/local-config.d.ts.map +1 -1
  43. package/lib/esm/config/local-config.js +2 -0
  44. package/lib/esm/config/local-config.js.map +1 -1
  45. package/lib/esm/config/types.d.ts +6 -0
  46. package/lib/esm/config/types.d.ts.map +1 -1
  47. package/lib/esm/config/types.js.map +1 -1
  48. package/lib/esm/hooks/click.d.ts +8 -2
  49. package/lib/esm/hooks/click.d.ts.map +1 -1
  50. package/lib/esm/hooks/click.js +42 -3
  51. package/lib/esm/hooks/click.js.map +1 -1
  52. package/lib/esm/plugins/url-tracking-plugin.d.ts +3 -0
  53. package/lib/esm/plugins/url-tracking-plugin.d.ts.map +1 -1
  54. package/lib/esm/plugins/url-tracking-plugin.js +16 -9
  55. package/lib/esm/plugins/url-tracking-plugin.js.map +1 -1
  56. package/lib/esm/semantic-identity.d.ts +5 -0
  57. package/lib/esm/semantic-identity.d.ts.map +1 -0
  58. package/lib/esm/semantic-identity.js +63 -0
  59. package/lib/esm/semantic-identity.js.map +1 -0
  60. package/lib/esm/semantic.d.ts +24 -0
  61. package/lib/esm/semantic.d.ts.map +1 -0
  62. package/lib/esm/semantic.js +128 -0
  63. package/lib/esm/semantic.js.map +1 -0
  64. package/lib/esm/session-replay.d.ts +4 -1
  65. package/lib/esm/session-replay.d.ts.map +1 -1
  66. package/lib/esm/session-replay.js +155 -80
  67. package/lib/esm/session-replay.js.map +1 -1
  68. package/lib/esm/utils/rrweb.d.ts +3 -0
  69. package/lib/esm/utils/rrweb.d.ts.map +1 -1
  70. package/lib/esm/utils/rrweb.js.map +1 -1
  71. package/lib/esm/version.d.ts +1 -1
  72. package/lib/esm/version.d.ts.map +1 -1
  73. package/lib/esm/version.js +1 -1
  74. package/lib/esm/version.js.map +1 -1
  75. package/lib/scripts/console-plugin-min.js +1 -1
  76. package/lib/scripts/console-plugin-min.js.gz +0 -0
  77. package/lib/scripts/console-plugin-min.js.map +1 -1
  78. package/lib/scripts/index-min.js +1 -1
  79. package/lib/scripts/index-min.js.gz +0 -0
  80. package/lib/scripts/index-min.js.map +1 -1
  81. package/lib/scripts/rrweb-record-min.js +1 -1
  82. package/lib/scripts/rrweb-record-min.js.gz +0 -0
  83. package/lib/scripts/rrweb-record-min.js.map +1 -1
  84. package/lib/scripts/session-replay-browser-min.js +1 -1
  85. package/lib/scripts/session-replay-browser-min.js.gz +0 -0
  86. package/lib/scripts/session-replay-browser-min.js.map +1 -1
  87. package/package.json +7 -6
@@ -1,4 +1,7 @@
1
1
  import { __assign, __awaiter, __generator, __read, __spreadArray, __values } from "tslib";
2
+ import { ReplaySemanticAdapter } from './semantic';
3
+ import { getSemanticIdentity } from './semantic-identity';
4
+ import { finder } from './libs/finder';
2
5
  import { createPrivacyRecorderOptions, getBlockSelectors, getMaskTextSelectors, } from '@amplitude/session-replay-dom-privacy';
3
6
  import { getAnalyticsConnector, getGlobalScope, Logger, returnWrapper, SpecialEventType, generateHashCode, getOrCreateWindowMessenger, enableBackgroundCapture, AMPLITUDE_ORIGINS_MAP, } from '@amplitude/analytics-core';
4
7
  // Import only specific types to avoid pulling in the entire rrweb-types package
@@ -261,18 +264,21 @@ var SessionReplay = /** @class */ (function () {
261
264
  });
262
265
  });
263
266
  };
264
- this.stopRecordingEvents = function () {
265
- var _a, _b, _c;
267
+ this.stopRecordingEvents = function (reason, state) {
268
+ var _a, _b, _c, _d;
269
+ if (reason === void 0) { reason = 'targeting'; }
270
+ if (state === void 0) { state = 'stop'; }
266
271
  try {
272
+ (_a = _this.semanticAdapter) === null || _a === void 0 ? void 0 : _a.stop(reason, state);
267
273
  _this.loggerProvider.log('Session Replay capture stopping.');
268
274
  _this.recordCancelCallback && _this.recordCancelCallback();
269
275
  _this.recordCancelCallback = null;
270
- (_a = _this.networkObservers) === null || _a === void 0 ? void 0 : _a.stop();
271
- (_b = _this.crossOriginIframeCoordinator) === null || _b === void 0 ? void 0 : _b.stop();
276
+ (_b = _this.networkObservers) === null || _b === void 0 ? void 0 : _b.stop();
277
+ (_c = _this.crossOriginIframeCoordinator) === null || _c === void 0 ? void 0 : _c.stop();
272
278
  _this.crossOriginIframeCoordinator = null;
273
279
  // Remove the child-mode parent signal listener so a later mode change
274
280
  // (e.g. crossOriginIframes disabled) does not leave a stale listener.
275
- (_c = _this.crossOriginParentSignalCleanup) === null || _c === void 0 ? void 0 : _c.call(_this);
281
+ (_d = _this.crossOriginParentSignalCleanup) === null || _d === void 0 ? void 0 : _d.call(_this);
276
282
  _this.crossOriginParentSignalCleanup = null;
277
283
  }
278
284
  catch (error) {
@@ -343,17 +349,19 @@ var SessionReplay = /** @class */ (function () {
343
349
  return currentUrl != null ? { url: currentUrl } : undefined;
344
350
  };
345
351
  SessionReplay.prototype._init = function (apiKey, options) {
346
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
352
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
347
353
  return __awaiter(this, void 0, void 0, function () {
348
- var now, _q, _r, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, compressionWorkerScript, trackDestinationWorkerScript, globalScope, _s, compressionScript, trackDestinationScript, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError, onFullSnapshotProcessed, pending_2, pending_1, pending_1_1, _t, event_1, sessionId, messenger, needsUrlTracking;
349
- var e_2, _u;
354
+ var now, _r, _s, joinedConfig, localConfig, remoteConfig, scrollWatcher, managers, storeType, compressionWorkerScript, trackDestinationWorkerScript, globalScope, _t, compressionScript, trackDestinationScript, rrwebEventManager, error_1, typedError, payloadBatcher, interactionEventManager, error_2, typedError, onFullSnapshotProcessed, pending_2, pending_1, pending_1_1, _u, event_1, sessionId, messenger, needsUrlTracking;
355
+ var e_2, _v;
350
356
  var _this = this;
351
- return __generator(this, function (_v) {
352
- switch (_v.label) {
357
+ return __generator(this, function (_w) {
358
+ switch (_w.label) {
353
359
  case 0:
354
360
  // Re-init should always tear down any previous URL-change subscription, even when the
355
361
  // next config has no targeting config and we don't subscribe again.
356
362
  (_a = this.urlChangeCleanup) === null || _a === void 0 ? void 0 : _a.call(this);
363
+ (_b = this.semanticAdapter) === null || _b === void 0 ? void 0 : _b.stop('customer_stop');
364
+ this.semanticAdapter = undefined;
357
365
  // A new init always allows capture again. `stop()` only pauses the current instance.
358
366
  this.recordingEnabled = true;
359
367
  this.startChildRecordingOnSetup = false;
@@ -366,19 +374,19 @@ var SessionReplay = /** @class */ (function () {
366
374
  pruneStaleReplayStartTimes(apiKey, now, this.loggerProvider);
367
375
  this.sessionStartTime =
368
376
  options.sessionId !== undefined
369
- ? (_b = getOrInitReplayStartTime(apiKey, options.sessionId, now, this.loggerProvider)) !== null && _b !== void 0 ? _b : now
377
+ ? (_c = getOrInitReplayStartTime(apiKey, options.sessionId, now, this.loggerProvider)) !== null && _c !== void 0 ? _c : now
370
378
  : now;
371
- _q = this;
379
+ _r = this;
372
380
  return [4 /*yield*/, createSessionReplayJoinedConfigGenerator(apiKey, options)];
373
381
  case 1:
374
- _q.joinedConfigGenerator = _v.sent();
382
+ _r.joinedConfigGenerator = _w.sent();
375
383
  return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig()];
376
384
  case 2:
377
- _r = _v.sent(), joinedConfig = _r.joinedConfig, localConfig = _r.localConfig, remoteConfig = _r.remoteConfig;
385
+ _s = _w.sent(), joinedConfig = _s.joinedConfig, localConfig = _s.localConfig, remoteConfig = _s.remoteConfig;
378
386
  this.config = joinedConfig;
379
- this.setMetadata(options.sessionId, joinedConfig, localConfig, remoteConfig, (_c = options.version) === null || _c === void 0 ? void 0 : _c.version, VERSION, (_d = options.version) === null || _d === void 0 ? void 0 : _d.type);
387
+ this.setMetadata(options.sessionId, joinedConfig, localConfig, remoteConfig, (_d = options.version) === null || _d === void 0 ? void 0 : _d.version, VERSION, (_e = options.version) === null || _e === void 0 ? void 0 : _e.type);
380
388
  this.pageLeaveFns = [];
381
- if (options.sessionId && ((_e = this.config.interactionConfig) === null || _e === void 0 ? void 0 : _e.enabled)) {
389
+ if (options.sessionId && ((_f = this.config.interactionConfig) === null || _f === void 0 ? void 0 : _f.enabled)) {
382
390
  scrollWatcher = ScrollWatcher.default({
383
391
  sessionId: options.sessionId,
384
392
  type: 'interaction',
@@ -389,7 +397,7 @@ var SessionReplay = /** @class */ (function () {
389
397
  }
390
398
  managers = [];
391
399
  storeType = this.config.storeType;
392
- if (storeType === 'idb' && !((_f = getGlobalScope()) === null || _f === void 0 ? void 0 : _f.indexedDB)) {
400
+ if (storeType === 'idb' && !((_g = getGlobalScope()) === null || _g === void 0 ? void 0 : _g.indexedDB)) {
393
401
  storeType = 'memory';
394
402
  this.loggerProvider.warn('Could not use preferred indexedDB storage, reverting to in memory option.');
395
403
  }
@@ -398,42 +406,42 @@ var SessionReplay = /** @class */ (function () {
398
406
  if (!(this.config.useWebWorker && globalScope && globalScope.Worker)) return [3 /*break*/, 4];
399
407
  return [4 /*yield*/, import('./worker')];
400
408
  case 3:
401
- _s = _v.sent(), compressionScript = _s.compressionScript, trackDestinationScript = _s.trackDestinationScript;
409
+ _t = _w.sent(), compressionScript = _t.compressionScript, trackDestinationScript = _t.trackDestinationScript;
402
410
  compressionWorkerScript = compressionScript;
403
411
  trackDestinationWorkerScript = trackDestinationScript;
404
- _v.label = 4;
412
+ _w.label = 4;
405
413
  case 4:
406
- _v.trys.push([4, 6, , 7]);
414
+ _w.trys.push([4, 6, , 7]);
407
415
  return [4 /*yield*/, createEventsManager({
408
416
  config: this.config,
409
417
  type: 'replay',
410
- minInterval: (_g = this.config.flushIntervalConfig) === null || _g === void 0 ? void 0 : _g.minIntervalMs,
411
- maxInterval: (_h = this.config.flushIntervalConfig) === null || _h === void 0 ? void 0 : _h.maxIntervalMs,
418
+ minInterval: (_h = this.config.flushIntervalConfig) === null || _h === void 0 ? void 0 : _h.minIntervalMs,
419
+ maxInterval: (_j = this.config.flushIntervalConfig) === null || _j === void 0 ? void 0 : _j.maxIntervalMs,
412
420
  maxPersistedEventsSize: this.config.maxPersistedEventsSizeBytes,
413
421
  storeType: storeType,
414
422
  trackDestinationWorkerScript: trackDestinationWorkerScript,
415
423
  shouldSend: function () { return !_this.isBelowMinSessionDuration(); },
416
424
  })];
417
425
  case 5:
418
- rrwebEventManager = _v.sent();
426
+ rrwebEventManager = _w.sent();
419
427
  this.rrwebEventManager = rrwebEventManager;
420
428
  managers.push({ name: 'replay', manager: rrwebEventManager });
421
429
  return [3 /*break*/, 7];
422
430
  case 6:
423
- error_1 = _v.sent();
431
+ error_1 = _w.sent();
424
432
  typedError = error_1;
425
433
  this.loggerProvider.warn("Error occurred while creating replay events manager: ".concat(typedError.toString()));
426
434
  return [3 /*break*/, 7];
427
435
  case 7:
428
- if (!((_j = this.config.interactionConfig) === null || _j === void 0 ? void 0 : _j.enabled)) return [3 /*break*/, 11];
436
+ if (!((_k = this.config.interactionConfig) === null || _k === void 0 ? void 0 : _k.enabled)) return [3 /*break*/, 11];
429
437
  payloadBatcher = this.config.interactionConfig.batch ? clickBatcher : clickNonBatcher;
430
- _v.label = 8;
438
+ _w.label = 8;
431
439
  case 8:
432
- _v.trys.push([8, 10, , 11]);
440
+ _w.trys.push([8, 10, , 11]);
433
441
  return [4 /*yield*/, createEventsManager({
434
442
  config: this.config,
435
443
  type: 'interaction',
436
- minInterval: (_k = this.config.interactionConfig.trackEveryNms) !== null && _k !== void 0 ? _k : INTERACTION_MIN_INTERVAL,
444
+ minInterval: (_l = this.config.interactionConfig.trackEveryNms) !== null && _l !== void 0 ? _l : INTERACTION_MIN_INTERVAL,
437
445
  maxInterval: INTERACTION_MAX_INTERVAL,
438
446
  maxPersistedEventsSize: this.config.maxPersistedEventsSizeBytes,
439
447
  payloadBatcher: payloadBatcher,
@@ -441,11 +449,11 @@ var SessionReplay = /** @class */ (function () {
441
449
  trackDestinationWorkerScript: trackDestinationWorkerScript,
442
450
  })];
443
451
  case 9:
444
- interactionEventManager = _v.sent();
452
+ interactionEventManager = _w.sent();
445
453
  managers.push({ name: 'interaction', manager: interactionEventManager });
446
454
  return [3 /*break*/, 11];
447
455
  case 10:
448
- error_2 = _v.sent();
456
+ error_2 = _w.sent();
449
457
  typedError = error_2;
450
458
  this.loggerProvider.warn("Error occurred while creating interaction events manager: ".concat(typedError.toString()));
451
459
  return [3 /*break*/, 11];
@@ -463,14 +471,14 @@ var SessionReplay = /** @class */ (function () {
463
471
  pending_2 = this.pendingEmitEvents.splice(0);
464
472
  try {
465
473
  for (pending_1 = __values(pending_2), pending_1_1 = pending_1.next(); !pending_1_1.done; pending_1_1 = pending_1.next()) {
466
- _t = pending_1_1.value, event_1 = _t.event, sessionId = _t.sessionId;
474
+ _u = pending_1_1.value, event_1 = _u.event, sessionId = _u.sessionId;
467
475
  this.eventCompressor.enqueueEvent(event_1, sessionId);
468
476
  }
469
477
  }
470
478
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
471
479
  finally {
472
480
  try {
473
- if (pending_1_1 && !pending_1_1.done && (_u = pending_1.return)) _u.call(pending_1);
481
+ if (pending_1_1 && !pending_1_1.done && (_v = pending_1.return)) _v.call(pending_1);
474
482
  }
475
483
  finally { if (e_2) throw e_2.error; }
476
484
  }
@@ -507,11 +515,11 @@ var SessionReplay = /** @class */ (function () {
507
515
  ], false);
508
516
  return [4 /*yield*/, this.initializeNetworkObservers()];
509
517
  case 12:
510
- _v.sent();
518
+ _w.sent();
511
519
  // Enable background capture when this page is opened by the Amplitude app
512
520
  // (window.opener exists). Uses the shared messenger singleton so that if
513
521
  // autocapture is also loaded, both share a single messenger and script load.
514
- if ((_l = getGlobalScope()) === null || _l === void 0 ? void 0 : _l.opener) {
522
+ if ((_m = getGlobalScope()) === null || _m === void 0 ? void 0 : _m.opener) {
515
523
  messenger = getOrCreateWindowMessenger();
516
524
  enableBackgroundCapture(messenger);
517
525
  messenger.setup(__assign({ logger: this.loggerProvider }, (this.config.serverZone && { endpoint: AMPLITUDE_ORIGINS_MAP[this.config.serverZone] })));
@@ -520,8 +528,8 @@ var SessionReplay = /** @class */ (function () {
520
528
  this.teardownEventListeners(false);
521
529
  return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options.userProperties, page: this.getCurrentPageForTargeting() }, true)];
522
530
  case 13:
523
- _v.sent();
524
- needsUrlTracking = this.config.targetingConfig || ((_p = (_o = (_m = this.config.privacyConfig) === null || _m === void 0 ? void 0 : _m.urlMaskLevels) === null || _o === void 0 ? void 0 : _o.length) !== null && _p !== void 0 ? _p : 0) > 0;
531
+ _w.sent();
532
+ needsUrlTracking = this.config.targetingConfig || ((_q = (_p = (_o = this.config.privacyConfig) === null || _o === void 0 ? void 0 : _o.urlMaskLevels) === null || _p === void 0 ? void 0 : _p.length) !== null && _q !== void 0 ? _q : 0) > 0;
525
533
  if (needsUrlTracking) {
526
534
  this.setupUrlChangeListener();
527
535
  }
@@ -534,11 +542,11 @@ var SessionReplay = /** @class */ (function () {
534
542
  return returnWrapper(this.asyncSetSessionId(sessionId, deviceId));
535
543
  };
536
544
  SessionReplay.prototype.asyncSetSessionId = function (sessionId, deviceId, options) {
537
- var _a, _b, _c, _d;
545
+ var _a, _b, _c, _d, _e, _f;
538
546
  return __awaiter(this, void 0, void 0, function () {
539
547
  var previousSessionId, currentDeviceId, isSessionChange, deviceIdForReplayId, joinedConfig;
540
- return __generator(this, function (_e) {
541
- switch (_e.label) {
548
+ return __generator(this, function (_g) {
549
+ switch (_g.label) {
542
550
  case 0:
543
551
  previousSessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
544
552
  currentDeviceId = this.getDeviceId();
@@ -561,13 +569,16 @@ var SessionReplay = /** @class */ (function () {
561
569
  this.sendEvents(previousSessionId);
562
570
  }
563
571
  isSessionChange = previousSessionId !== sessionId;
572
+ if (isSessionChange && ((_c = (_b = this.config) === null || _b === void 0 ? void 0 : _b.semanticCapture) === null || _c === void 0 ? void 0 : _c.enabled) && this.semanticAdapter) {
573
+ this.stopRecordingEvents('new_session');
574
+ }
564
575
  // Drop any beacon-buffered events from the previous session BEFORE installing the
565
576
  // new identifiers / start time. Otherwise the page-leave beacon path could attribute
566
577
  // old-session events to the new session id, and the gate (using the new start time)
567
578
  // would compute the wrong elapsed duration. Skip on a redundant same-sessionId call —
568
579
  // the buffer belongs to the *continuing* session and should ship via beacon as normal.
569
580
  if (isSessionChange) {
570
- (_b = this.rrwebEventManager) === null || _b === void 0 ? void 0 : _b.dropPendingBeaconEvents();
581
+ (_d = this.rrwebEventManager) === null || _d === void 0 ? void 0 : _d.dropPendingBeaconEvents();
571
582
  }
572
583
  deviceIdForReplayId = deviceId || this.getDeviceId();
573
584
  this.identifiers = new SessionIdentifiers({
@@ -582,7 +593,7 @@ var SessionReplay = /** @class */ (function () {
582
593
  this.sessionStartTime = Date.now();
583
594
  this.suppressedSendCount = 0;
584
595
  this.hasEmittedGateDecision = false;
585
- if ((_c = this.config) === null || _c === void 0 ? void 0 : _c.apiKey) {
596
+ if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.apiKey) {
586
597
  setReplayStartTime(this.config.apiKey, sessionId, this.sessionStartTime, this.loggerProvider);
587
598
  if (previousSessionId !== undefined) {
588
599
  removeReplayStartTime(this.config.apiKey, previousSessionId, this.loggerProvider);
@@ -592,19 +603,19 @@ var SessionReplay = /** @class */ (function () {
592
603
  if (!(this.joinedConfigGenerator && previousSessionId)) return [3 /*break*/, 2];
593
604
  return [4 /*yield*/, this.joinedConfigGenerator.generateJoinedConfig()];
594
605
  case 1:
595
- joinedConfig = (_e.sent()).joinedConfig;
606
+ joinedConfig = (_g.sent()).joinedConfig;
596
607
  this.config = joinedConfig;
597
- _e.label = 2;
608
+ _g.label = 2;
598
609
  case 2:
599
- if (!((_d = this.config) === null || _d === void 0 ? void 0 : _d.targetingConfig)) return [3 /*break*/, 4];
610
+ if (!((_f = this.config) === null || _f === void 0 ? void 0 : _f.targetingConfig)) return [3 /*break*/, 4];
600
611
  return [4 /*yield*/, this.evaluateTargetingAndCapture({ userProperties: options === null || options === void 0 ? void 0 : options.userProperties, page: this.getCurrentPageForTargeting() }, false, true)];
601
612
  case 3:
602
- _e.sent();
613
+ _g.sent();
603
614
  return [3 /*break*/, 6];
604
615
  case 4: return [4 /*yield*/, this.recordEvents()];
605
616
  case 5:
606
- _e.sent();
607
- _e.label = 6;
617
+ _g.sent();
618
+ _g.label = 6;
608
619
  case 6: return [2 /*return*/];
609
620
  }
610
621
  });
@@ -888,65 +899,71 @@ var SessionReplay = /** @class */ (function () {
888
899
  return !this.recordingEnabled || generation !== this.recordingGeneration;
889
900
  };
890
901
  SessionReplay.prototype._recordEvents = function (shouldLogMetadata) {
891
- var _a, _b, _c, _d, _e, _f, _g, _h;
902
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
892
903
  if (shouldLogMetadata === void 0) { shouldLogMetadata = true; }
893
904
  return __awaiter(this, void 0, void 0, function () {
894
- var config, shouldRecord, sessionId, generation, recordFunction, networkLoggingConfig, trackUrl, ignoredUrls, interactionConfig, loggingConfig, hooks, ugcFilterRules, crossOriginIframesEnabled, coordinateChildren, childMode, plugins, error_5;
905
+ var config, shouldRecord, sessionId, generation, recordFunction, networkLoggingConfig, trackUrl, ignoredUrls, interactionConfig, loggingConfig, heatmapHook, sharedSemanticClicks, mouseInteraction, clickHandler, hooks, ugcFilterRules, crossOriginIframesEnabled, coordinateChildren, childMode, plugins, error_5;
895
906
  var _this = this;
896
- return __generator(this, function (_j) {
897
- switch (_j.label) {
907
+ return __generator(this, function (_p) {
908
+ switch (_p.label) {
898
909
  case 0:
899
910
  config = this.config;
900
911
  shouldRecord = this.getShouldRecord();
901
912
  sessionId = (_a = this.identifiers) === null || _a === void 0 ? void 0 : _a.sessionId;
902
913
  if (!shouldRecord || !sessionId || !config) {
914
+ if (((_b = config === null || config === void 0 ? void 0 : config.semanticCapture) === null || _b === void 0 ? void 0 : _b.enabled) && this.semanticAdapter && this.recordCancelCallback) {
915
+ this.stopRecordingEvents(this.shouldOptOut() ? 'opt_out' : config.targetingConfig ? 'targeting' : 'sampled_out');
916
+ }
903
917
  return [2 /*return*/];
904
918
  }
905
- this.stopRecordingEvents();
919
+ this.stopRecordingEvents('focus', 'pause');
906
920
  generation = this.recordingGeneration;
907
921
  return [4 /*yield*/, this.getRecordFunction()];
908
922
  case 1:
909
- recordFunction = _j.sent();
923
+ recordFunction = _p.sent();
910
924
  // May be undefined if cannot import rrweb-record
911
925
  if (!recordFunction || this.shouldAbandonRecordStart(generation)) {
912
926
  return [2 /*return*/];
913
927
  }
914
928
  return [4 /*yield*/, this.initializeNetworkObservers()];
915
929
  case 2:
916
- _j.sent();
930
+ _p.sent();
917
931
  if (this.shouldAbandonRecordStart(generation)) {
918
932
  return [2 /*return*/];
919
933
  }
920
- networkLoggingConfig = (_b = config.loggingConfig) === null || _b === void 0 ? void 0 : _b.network;
934
+ networkLoggingConfig = (_c = config.loggingConfig) === null || _c === void 0 ? void 0 : _c.network;
921
935
  trackUrl = getServerUrl(config.serverZone, config.trackServerUrl);
922
936
  ignoredUrls = [SESSION_REPLAY_SERVER_URL, SESSION_REPLAY_EU_URL, SESSION_REPLAY_STAGING_URL, trackUrl];
923
- (_c = this.networkObservers) === null || _c === void 0 ? void 0 : _c.start(function (event) {
937
+ (_d = this.networkObservers) === null || _d === void 0 ? void 0 : _d.start(function (event) {
924
938
  if (ignoredUrls.some(function (url) { return event.url.startsWith(url); }))
925
939
  return;
926
940
  void _this.addCustomRRWebEvent(CustomRRwebEvent.FETCH_REQUEST, event);
927
941
  }, networkLoggingConfig);
928
942
  interactionConfig = config.interactionConfig, loggingConfig = config.loggingConfig;
929
- hooks = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled)
930
- ? {
931
- mouseInteraction: this.eventsManager &&
932
- ((_d = this.clickHandler) === null || _d === void 0 ? void 0 : _d.createHook({
933
- eventsManager: this.eventsManager,
934
- sessionId: sessionId,
935
- deviceIdFn: this.getDeviceId.bind(this),
936
- mirror: recordFunction.mirror,
937
- ugcFilterRules: (_e = interactionConfig.ugcFilterRules) !== null && _e !== void 0 ? _e : [],
938
- performanceOptions: (_f = config.performanceConfig) === null || _f === void 0 ? void 0 : _f.interaction,
939
- })),
940
- scroll: this.scrollHook,
941
- }
942
- : {};
943
+ heatmapHook = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && this.eventsManager
944
+ ? (_e = this.clickHandler) === null || _e === void 0 ? void 0 : _e.createHook({
945
+ eventsManager: this.eventsManager,
946
+ sessionId: sessionId,
947
+ deviceIdFn: this.getDeviceId.bind(this),
948
+ mirror: recordFunction.mirror,
949
+ ugcFilterRules: (_f = interactionConfig.ugcFilterRules) !== null && _f !== void 0 ? _f : [],
950
+ performanceOptions: (_g = config.performanceConfig) === null || _g === void 0 ? void 0 : _g.interaction,
951
+ })
952
+ : undefined;
953
+ sharedSemanticClicks = ((_h = config.semanticCapture) === null || _h === void 0 ? void 0 : _h.enabled) && recordFunction.supportsNativeMouseInteraction;
954
+ mouseInteraction = heatmapHook;
955
+ if (sharedSemanticClicks) {
956
+ clickHandler = (_j = this.clickHandler) !== null && _j !== void 0 ? _j : (this.clickHandler = new ClickHandler(this.loggerProvider));
957
+ mouseInteraction = clickHandler.createSharedHook(heatmapHook, function (event) { var _a; return (_a = _this.semanticAdapter) === null || _a === void 0 ? void 0 : _a.click(event); });
958
+ }
959
+ hooks = __assign(__assign({}, (mouseInteraction ? { mouseInteraction: mouseInteraction } : {})), ((interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) ? { scroll: this.scrollHook } : {}));
943
960
  ugcFilterRules = (interactionConfig === null || interactionConfig === void 0 ? void 0 : interactionConfig.enabled) && interactionConfig.ugcFilterRules ? interactionConfig.ugcFilterRules : [];
944
961
  this.loggerProvider.log("Session Replay capture beginning for ".concat(sessionId, "."));
945
- _j.label = 3;
962
+ _p.label = 3;
946
963
  case 3:
947
- _j.trys.push([3, 5, , 6]);
948
- crossOriginIframesEnabled = !!((_g = config.crossOriginIframes) === null || _g === void 0 ? void 0 : _g.enabled);
949
- coordinateChildren = ((_h = config.crossOriginIframes) === null || _h === void 0 ? void 0 : _h.coordinateChildren) !== false;
964
+ _p.trys.push([3, 5, , 6]);
965
+ crossOriginIframesEnabled = !!((_k = config.crossOriginIframes) === null || _k === void 0 ? void 0 : _k.enabled);
966
+ coordinateChildren = ((_l = config.crossOriginIframes) === null || _l === void 0 ? void 0 : _l.coordinateChildren) !== false;
950
967
  childMode = crossOriginIframesEnabled && isInIframe();
951
968
  if (childMode && coordinateChildren) {
952
969
  // Child mode: don't self-start; wait for a start signal from the parent.
@@ -983,16 +1000,24 @@ var SessionReplay = /** @class */ (function () {
983
1000
  this.startChildRecordingOnSetup = false;
984
1001
  return [4 /*yield*/, this.getRecordingPlugins(loggingConfig)];
985
1002
  case 4:
986
- plugins = _j.sent();
1003
+ plugins = _p.sent();
987
1004
  if (this.shouldAbandonRecordStart(generation)) {
988
1005
  return [2 /*return*/];
989
1006
  }
1007
+ this.prepareSemanticCapture(config, sessionId);
990
1008
  this.recordCancelCallback = recordFunction(__assign(__assign({}, this.buildRRWebRecordOptions(config, hooks, function (event) {
991
- if (_this.shouldOptOut() || !_this.recordingEnabled) {
1009
+ var _a, _b, _c, _d;
1010
+ // The terminal state contains no page or user data and must land before rrweb stops.
1011
+ var semanticStop = ((_b = (_a = _this.config) === null || _a === void 0 ? void 0 : _a.semanticCapture) === null || _b === void 0 ? void 0 : _b.enabled) &&
1012
+ _this.semanticAdapter &&
1013
+ event.type === RRWebEventType.Custom &&
1014
+ event.data.tag === 'amp-semantic/recording' &&
1015
+ ((_c = event.data.payload) === null || _c === void 0 ? void 0 : _c.state) === 'stop';
1016
+ if ((_this.shouldOptOut() || !_this.recordingEnabled) && !semanticStop) {
992
1017
  _this.loggerProvider.log(_this.shouldOptOut()
993
1018
  ? "Opting session ".concat(sessionId, " out of recording due to optOut config.")
994
1019
  : "Session Replay capture stopping for ".concat(sessionId, "."));
995
- _this.stopRecordingEvents();
1020
+ _this.stopRecordingEvents(_this.shouldOptOut() ? 'opt_out' : 'customer_stop');
996
1021
  _this.sendEvents();
997
1022
  return;
998
1023
  }
@@ -1008,7 +1033,10 @@ var SessionReplay = /** @class */ (function () {
1008
1033
  // Buffer the event so it can be flushed once the compressor is initialized.
1009
1034
  _this.pendingEmitEvents.push({ event: event, sessionId: sessionId });
1010
1035
  }
1036
+ (_d = _this.semanticAdapter) === null || _d === void 0 ? void 0 : _d.event(event);
1011
1037
  }, 'Error while capturing replay: ')), { plugins: plugins, recordCrossOriginIframes: crossOriginIframesEnabled }));
1038
+ if (this.recordCancelCallback)
1039
+ (_m = this.semanticAdapter) === null || _m === void 0 ? void 0 : _m.recordingReady();
1012
1040
  if (crossOriginIframesEnabled && !childMode && coordinateChildren) {
1013
1041
  if (!this.crossOriginIframeCoordinator) {
1014
1042
  this.crossOriginIframeCoordinator = new CrossOriginIframeCoordinator();
@@ -1021,7 +1049,8 @@ var SessionReplay = /** @class */ (function () {
1021
1049
  }
1022
1050
  return [3 /*break*/, 6];
1023
1051
  case 5:
1024
- error_5 = _j.sent();
1052
+ error_5 = _p.sent();
1053
+ (_o = this.semanticAdapter) === null || _o === void 0 ? void 0 : _o.stop('error');
1025
1054
  this.loggerProvider.warn('Failed to initialize session replay:', error_5);
1026
1055
  return [3 /*break*/, 6];
1027
1056
  case 6: return [2 /*return*/];
@@ -1029,6 +1058,52 @@ var SessionReplay = /** @class */ (function () {
1029
1058
  });
1030
1059
  });
1031
1060
  };
1061
+ SessionReplay.prototype.prepareSemanticCapture = function (config, sessionId) {
1062
+ var _this = this;
1063
+ var _a, _b, _c, _d;
1064
+ var scope = getGlobalScope();
1065
+ if (!(scope === null || scope === void 0 ? void 0 : scope.document))
1066
+ return;
1067
+ if (!((_a = config.semanticCapture) === null || _a === void 0 ? void 0 : _a.enabled)) {
1068
+ (_b = this.semanticAdapter) === null || _b === void 0 ? void 0 : _b.stop('targeting');
1069
+ (_c = this.semanticAdapter) === null || _c === void 0 ? void 0 : _c.prepare({ enabled: false }, sessionId);
1070
+ return;
1071
+ }
1072
+ if (!this.semanticAdapter) {
1073
+ this.semanticAdapter = new ReplaySemanticAdapter({
1074
+ document: scope.document,
1075
+ window: scope,
1076
+ sdk: "@amplitude/session-replay-browser@".concat(VERSION),
1077
+ externalClicks: ((_d = this.recordFunction) === null || _d === void 0 ? void 0 : _d.supportsNativeMouseInteraction) === true,
1078
+ // rrweb does not report auxiliary clicks through its mouseInteraction hook.
1079
+ externalAuxClicks: false,
1080
+ getNodeId: function (node) { var _a, _b, _c, _d; return (_d = (_c = (_a = _this.recordFunction) === null || _a === void 0 ? void 0 : (_b = _a.mirror).getId) === null || _c === void 0 ? void 0 : _c.call(_b, node)) !== null && _d !== void 0 ? _d : -1; },
1081
+ getNode: function (id) { var _a, _b; return (_b = (_a = _this.recordFunction) === null || _a === void 0 ? void 0 : _a.mirror.getNode(id)) !== null && _b !== void 0 ? _b : null; },
1082
+ getPrivacy: function () { var _a, _b; return (_b = (_a = _this.config) === null || _a === void 0 ? void 0 : _a.privacyConfig) !== null && _b !== void 0 ? _b : {}; },
1083
+ getUrl: function () { return scope.location.href; },
1084
+ getIdentity: function () { return getSemanticIdentity(scope); },
1085
+ getAnalyticsContext: function () { var _a, _b; return (_b = (_a = _this.config) === null || _a === void 0 ? void 0 : _a.semanticAnalyticsContext) !== null && _b !== void 0 ? _b : { present: false, autocapture: [] }; },
1086
+ inlineStylesheet: config.shouldInlineStylesheet,
1087
+ getSelector: function (element) {
1088
+ var _a, _b;
1089
+ try {
1090
+ var options = __assign(__assign({}, (_b = (_a = _this.config) === null || _a === void 0 ? void 0 : _a.performanceConfig) === null || _b === void 0 ? void 0 : _b.interaction), { timeoutMs: 1 });
1091
+ return _this.clickHandler ? _this.clickHandler.getSelector(element, options) : finder(element, options);
1092
+ }
1093
+ catch (_c) {
1094
+ return null;
1095
+ }
1096
+ },
1097
+ emit: function (event) {
1098
+ if (_this.recordCancelCallback && _this.recordFunction) {
1099
+ _this.recordFunction.addCustomEvent("amp-semantic/".concat(event.name), event.payload);
1100
+ }
1101
+ },
1102
+ onError: function (error) { return _this.loggerProvider.debug('Semantic capture error:', error); },
1103
+ });
1104
+ }
1105
+ this.semanticAdapter.prepare(config.semanticCapture, sessionId);
1106
+ };
1032
1107
  SessionReplay.prototype.buildRRWebRecordOptions = function (config, hooks, emit, errorLogPrefix) {
1033
1108
  var _this = this;
1034
1109
  var privacyConfig = config.privacyConfig;
@@ -1113,7 +1188,7 @@ var SessionReplay = /** @class */ (function () {
1113
1188
  this.recordingEnabled = false;
1114
1189
  this.startChildRecordingOnSetup = false;
1115
1190
  this.recordingGeneration++;
1116
- this.stopRecordingEvents();
1191
+ this.stopRecordingEvents('customer_stop');
1117
1192
  this.sendEvents();
1118
1193
  };
1119
1194
  SessionReplay.prototype.flush = function (useRetry) {
@@ -1139,7 +1214,7 @@ var SessionReplay = /** @class */ (function () {
1139
1214
  (_b = this.crossOriginParentSignalCleanup) === null || _b === void 0 ? void 0 : _b.call(this);
1140
1215
  this.crossOriginParentSignalCleanup = null;
1141
1216
  this.teardownEventListeners(true);
1142
- this.stopRecordingEvents();
1217
+ this.stopRecordingEvents(this.semanticAdapter && this.shouldOptOut() ? 'opt_out' : 'customer_stop');
1143
1218
  this.sendEvents();
1144
1219
  };
1145
1220
  SessionReplay.prototype.mapSDKType = function (sdkType) {