@pendo/agent 2.314.0 → 2.315.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.
@@ -3422,7 +3422,7 @@ var ConfigReader = (function () {
3422
3422
  * @default false
3423
3423
  * @type {boolean}
3424
3424
  */
3425
- addOption('guides.delay', [SNIPPET_SRC], undefined, undefined, ['delayGuides']);
3425
+ addOption('guides.delay', [SNIPPET_SRC], false, undefined, ['delayGuides']);
3426
3426
  /**
3427
3427
  * Completely disables guides (this option has been moved from `disableGuides`).
3428
3428
  * Alias: `disableGuides`
@@ -3433,7 +3433,7 @@ var ConfigReader = (function () {
3433
3433
  * @default false
3434
3434
  * @type {boolean}
3435
3435
  */
3436
- addOption('guides.disabled', [SNIPPET_SRC], undefined, undefined, ['disableGuides']);
3436
+ addOption('guides.disabled', [SNIPPET_SRC], false, undefined, ['disableGuides']);
3437
3437
  /**
3438
3438
  * If 'true', guides with slow selectors will be removed from guide display processing.
3439
3439
  * This will improve application performance, but slow guides will not be shown to users.
@@ -3945,8 +3945,8 @@ let SERVER = '';
3945
3945
  let ASSET_HOST = '';
3946
3946
  let ASSET_PATH = '';
3947
3947
  let DESIGNER_SERVER = '';
3948
- let VERSION = '2.314.0_';
3949
- let PACKAGE_VERSION = '2.314.0';
3948
+ let VERSION = '2.315.0_';
3949
+ let PACKAGE_VERSION = '2.315.0';
3950
3950
  let LOADER = 'xhr';
3951
3951
  /* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
3952
3952
  /**
@@ -5569,6 +5569,7 @@ var Events = (function () {
5569
5569
  new EventType('deliverablesLoaded', [DEBUG, LIFECYCLE]),
5570
5570
  new EventType('guidesFailed', [DEBUG, LIFECYCLE]),
5571
5571
  new EventType('guidesLoaded', [DEBUG, LIFECYCLE]),
5572
+ new EventType('segmentFlagsUpdated', [DEBUG, LIFECYCLE]),
5572
5573
  new EventType('guideListChanged', [DEBUG, LIFECYCLE]),
5573
5574
  new EventType('guideSeen', [DEBUG, LIFECYCLE]),
5574
5575
  new EventType('guideNotSeen', [DEBUG, LIFECYCLE]),
@@ -14201,9 +14202,31 @@ var activeGuides = [];
14201
14202
  var activeElements = [];
14202
14203
  var badgesShown = {};
14203
14204
  let _displayableGuides = {};
14205
+ const Channel = {
14206
+ ALL: '*',
14207
+ DEFAULT: 'default'
14208
+ };
14204
14209
  function setBadgesShown(badges) {
14205
14210
  badgesShown = badges;
14206
14211
  }
14212
+ function createChannelMatcher(options = {}) {
14213
+ let channel = options.channel;
14214
+ if (!options.hasOwnProperty('channel')) {
14215
+ channel = Channel.ALL;
14216
+ }
14217
+ else if (channel == null) {
14218
+ channel = Channel.DEFAULT;
14219
+ }
14220
+ if (channel === Channel.ALL) {
14221
+ return () => true;
14222
+ }
14223
+ else if (channel === Channel.DEFAULT) {
14224
+ return (guide) => guide.channel == null;
14225
+ }
14226
+ else {
14227
+ return (guide) => guide.channel == channel;
14228
+ }
14229
+ }
14207
14230
  /**
14208
14231
  * Returns an array of all guides available on the current page to the current user.
14209
14232
  * If multiple frames on a pages, `pendo.getActiveGuides()` will return the list of eligible
@@ -14211,15 +14234,18 @@ function setBadgesShown(badges) {
14211
14234
  *
14212
14235
  * @access public
14213
14236
  * @category Guides
14237
+ * @param {object} options - Options for filtering guides
14238
+ * @param {string} options.channel - Channel to filter guides by
14214
14239
  * @returns {Guide[]}
14215
14240
  * @example
14216
14241
  * pendo.getActiveGuides() => [{ Pendo Guide Object }, ...]
14217
14242
  */
14218
- function getActiveGuides() {
14219
- return activeGuides;
14243
+ function getActiveGuides(options) {
14244
+ const hasChannel = createChannelMatcher(options);
14245
+ return _.filter(activeGuides, hasChannel);
14220
14246
  }
14221
- function getLocalActiveGuides() {
14222
- return frameLocalGuides(getActiveGuides());
14247
+ function getLocalActiveGuides(options) {
14248
+ return frameLocalGuides(getActiveGuides(options));
14223
14249
  }
14224
14250
  function frameLocalGuides(guideList) {
14225
14251
  return _.filter(guideList, function (guide) {
@@ -14362,6 +14388,10 @@ function getGuideAttachPoint(doc = document) {
14362
14388
  return attachPoint || getBody(doc);
14363
14389
  }
14364
14390
  var findBadgeForStep = function (step) {
14391
+ var guide = step.getGuide();
14392
+ if (!guide)
14393
+ return;
14394
+ guide.placeBadge();
14365
14395
  var badge = badgesShown[step.guideId];
14366
14396
  if (!badge)
14367
14397
  return;
@@ -14501,10 +14531,12 @@ const internalEvents = {
14501
14531
  deliverablesLoaded: 1,
14502
14532
  guidesFailed: 1,
14503
14533
  guidesLoaded: 1,
14504
- onClickCaptured: 1
14534
+ onClickCaptured: 1,
14535
+ segmentFlagsUpdated: 1
14505
14536
  };
14506
14537
  const browserEvents = {
14507
- ready: 1
14538
+ ready: 1,
14539
+ segmentFlagsUpdated: 1
14508
14540
  };
14509
14541
  const supportedPublicEvents = [
14510
14542
  'ready',
@@ -14512,6 +14544,7 @@ const supportedPublicEvents = [
14512
14544
  'deliverablesLoaded',
14513
14545
  'guidesFailed',
14514
14546
  'guidesLoaded',
14547
+ 'segmentFlagsUpdated',
14515
14548
  'validateGuide',
14516
14549
  'validateLauncher',
14517
14550
  'validateGlobalScript'
@@ -20641,6 +20674,11 @@ var BuildingBlockResourceCenter = (function () {
20641
20674
 
20642
20675
  var GUIDE_STATE_TTL = 10000; // 10 seconds
20643
20676
  var LAST_STEP_ADVANCED_COOKIE = 'lastStepAdvanced';
20677
+ var THROTTLING_STATE = {
20678
+ DISMISSED: 'latestDismissedAutoAt',
20679
+ SNOOZED: 'latestSnoozedAutoAt',
20680
+ ADVANCED: 'finalAdvancedAutoAt'
20681
+ };
20644
20682
  function writeLastStepSeenCache(lastSeen) {
20645
20683
  store.dispatch('guideState/updateLastGuideStepSeen', lastSeen);
20646
20684
  store.dispatch('guideState/write');
@@ -20665,6 +20703,18 @@ function regainFocus() {
20665
20703
  function getLastGuideStepSeen() {
20666
20704
  return store.state.guideState.lastGuideStepSeen;
20667
20705
  }
20706
+ function applyTimerCache(timerValue, cachedTimerValue) {
20707
+ cachedTimerValue = parseInt(cachedTimerValue, 10);
20708
+ if (isNaN(cachedTimerValue) || !_.isNumber(cachedTimerValue))
20709
+ return timerValue;
20710
+ if (_.isNumber(timerValue) && cachedTimerValue > timerValue) {
20711
+ return cachedTimerValue;
20712
+ }
20713
+ if (!_.isNumber(timerValue)) {
20714
+ return cachedTimerValue;
20715
+ }
20716
+ return timerValue;
20717
+ }
20668
20718
  var GuideStateModule = (function () {
20669
20719
  var state = {
20670
20720
  steps: {},
@@ -20701,19 +20751,25 @@ var GuideStateModule = (function () {
20701
20751
  }
20702
20752
  });
20703
20753
  },
20704
- load(context, storedValue) {
20705
- if (!storedValue)
20706
- return;
20707
- var parsedValue;
20708
- try {
20709
- parsedValue = JSON.parse(storedValue);
20710
- }
20711
- catch (e) {
20754
+ load(context) {
20755
+ const storage = context.getters.storage();
20756
+ let storedValue = storage.read(LAST_STEP_ADVANCED_COOKIE, false, context.getters.cookieSuffix());
20757
+ if (storedValue) {
20758
+ var parsedValue;
20759
+ try {
20760
+ parsedValue = JSON.parse(storedValue);
20761
+ }
20762
+ catch (e) {
20763
+ }
20764
+ if (parsedValue) {
20765
+ _.each([].concat(parsedValue), function (stepState) {
20766
+ context.commit('setStepState', stepState);
20767
+ });
20768
+ }
20712
20769
  }
20713
- if (!parsedValue)
20714
- return;
20715
- _.each([].concat(parsedValue), function (stepState) {
20716
- context.commit('setStepState', stepState);
20770
+ _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20771
+ const value = storage.read(throttlingStorageKey);
20772
+ context.dispatch('updateThrottlingState', { name: throttlingStorageKey, value });
20717
20773
  });
20718
20774
  },
20719
20775
  forceExpire(context) {
@@ -20768,6 +20824,14 @@ var GuideStateModule = (function () {
20768
20824
  }
20769
20825
  log.info('making sure that dismissCount = \'' + step.dismissCount + '\' for ' + storageKey + ': ' + stepId);
20770
20826
  }
20827
+ if (stepState.destinationStepId !== undefined && step.destinationStepId != stepState.destinationStepId) {
20828
+ log.info('making sure that destinationStepId = \'' + stepState.destinationStepId + '\' for ' + storageKey + ': ' + stepId);
20829
+ step.destinationStepId = stepState.destinationStepId;
20830
+ }
20831
+ if (step.lastSeenAt != stepState.time) {
20832
+ log.info('making sure that lastSeenAt = \'' + stepState.time + '\' for ' + storageKey + ': ' + stepId);
20833
+ step.lastSeenAt = stepState.time;
20834
+ }
20771
20835
  var stepIndex = _.indexOf(guide.steps, step);
20772
20836
  _.each(guide.steps.slice(0, stepIndex), function (step) {
20773
20837
  if (!_.contains(['advanced', 'dismissed'], step.seenState)) {
@@ -20783,6 +20847,10 @@ var GuideStateModule = (function () {
20783
20847
  if (mostRecentLastGuideStepSeen) {
20784
20848
  context.dispatch('updateLastGuideStepSeen', _.extend({}, context.state.lastGuideStepSeen, mostRecentLastGuideStepSeen));
20785
20849
  }
20850
+ _.each(THROTTLING_STATE, function (throttlingStorageKey) {
20851
+ pendo$1[throttlingStorageKey] = applyTimerCache(pendo$1[throttlingStorageKey], context.state[throttlingStorageKey]);
20852
+ context.dispatch('updateThrottlingState', { name: throttlingStorageKey, value: pendo$1[throttlingStorageKey] });
20853
+ });
20786
20854
  },
20787
20855
  receiveLastGuideStepSeen(context, lastGuideStepSeen) {
20788
20856
  context.commit('setReceivedLastGuideStepSeen', lastGuideStepSeen);
@@ -20793,8 +20861,8 @@ var GuideStateModule = (function () {
20793
20861
  return;
20794
20862
  // Embedded guides should not update the lastGuideStepSeen in order to not interfere with auto guide display
20795
20863
  // Embedded guides are not included in getters.guideList
20796
- const shouldUpdateLastGuideStepSeen = _.some(context.getters.guideList(), function ({ id }) {
20797
- return id === lastGuideStepSeen.guideId;
20864
+ const shouldUpdateLastGuideStepSeen = _.some(context.getters.guideList(), function ({ id, channel }) {
20865
+ return id === lastGuideStepSeen.guideId && !channel;
20798
20866
  });
20799
20867
  if (lastGuideStepSeen.guideStepId) {
20800
20868
  context.commit('setStepState', lastGuideStepSeen);
@@ -20838,7 +20906,7 @@ var GuideStateModule = (function () {
20838
20906
  }
20839
20907
  if (context.getters.storageChangedInOtherTab()(newValue)) {
20840
20908
  clearLoopTimer();
20841
- context.dispatch('load', rawNewValue);
20909
+ context.dispatch('load');
20842
20910
  context.dispatch('apply');
20843
20911
  if (!context.state.receivedStateChangeAt) {
20844
20912
  context.commit('setReceivedStateChange', context.getters.now());
@@ -21160,15 +21228,27 @@ var Permalink = _.memoize(function () {
21160
21228
  return PermalinkConstructor(findGuideById);
21161
21229
  });
21162
21230
 
21231
+ function shouldNotResumeWalkthrough(walkthrough) {
21232
+ return walkthrough && walkthrough.attributes && walkthrough.attributes.doNotResume;
21233
+ }
21163
21234
  function findInProgressWalkthrough(guidesList, lastGuideStepSeen) {
21164
- var walkthrough = _.find(guidesList, function (guide) {
21235
+ const walkthrough = _.find(guidesList, function (guide) {
21165
21236
  return guide.isContinuation(lastGuideStepSeen);
21166
21237
  });
21167
- var shouldNotResume = walkthrough && walkthrough.attributes && walkthrough.attributes.doNotResume;
21168
- if (walkthrough && !shouldNotResume) {
21238
+ if (walkthrough && !shouldNotResumeWalkthrough(walkthrough)) {
21169
21239
  return walkthrough;
21170
21240
  }
21171
21241
  }
21242
+ function findInProgressChannelWalkthroughs(guidesList) {
21243
+ return _.filter(guidesList, function (guide) {
21244
+ return guide.channel && !shouldNotResumeWalkthrough(guide) && guide.isContinuation();
21245
+ });
21246
+ }
21247
+ const AutoDisplayType = {
21248
+ permalink: 'permalink',
21249
+ continuation: 'continuation',
21250
+ auto: 'auto'
21251
+ };
21172
21252
  class AutoDisplayPhase {
21173
21253
  constructor() {
21174
21254
  this.name = 'autoDisplay';
@@ -21177,33 +21257,45 @@ class AutoDisplayPhase {
21177
21257
  markDirty() {
21178
21258
  if (!isLeader())
21179
21259
  return;
21180
- this.queue.push('permalink', 'continuation');
21181
- this.queue.push(...AutoDisplay.sortAndFilter(getActiveGuides(), pendo$1.autoOrdering));
21260
+ this.queue.push({ type: AutoDisplayType.permalink });
21261
+ const activeGuides = getActiveGuides();
21262
+ const walkthrough = findInProgressWalkthrough(activeGuides, getLastGuideStepSeen());
21263
+ if (walkthrough) {
21264
+ this.queue.push({
21265
+ type: AutoDisplayType.continuation,
21266
+ guide: walkthrough
21267
+ });
21268
+ }
21269
+ for (const channelWalkthrough of findInProgressChannelWalkthroughs(activeGuides)) {
21270
+ this.queue.push({
21271
+ type: AutoDisplayType.continuation,
21272
+ guide: channelWalkthrough
21273
+ });
21274
+ }
21275
+ const allAutoGuides = AutoDisplay.sortAndFilter(activeGuides, pendo$1.autoOrdering);
21276
+ const filteredAutoGuides = walkthrough ? _.filter(allAutoGuides, guide => guide.channel) : allAutoGuides;
21277
+ this.queue.push(..._.map(filteredAutoGuides, guide => ({ type: AutoDisplayType.auto, guide })));
21182
21278
  }
21183
21279
  process(monitor) {
21184
- if (isGuideShown()) {
21185
- this.cancel();
21186
- return;
21187
- }
21188
- var next = this.queue.shift();
21189
- if (next === 'permalink') {
21190
- return Permalink().tryDisplay();
21280
+ const next = this.queue.shift();
21281
+ if (next.type === AutoDisplayType.permalink) {
21282
+ if (!isGuideShown()) {
21283
+ return Permalink().tryDisplay();
21284
+ }
21191
21285
  }
21192
- else if (next === 'continuation') {
21193
- // check for in-progress walkthroughs
21194
- var walkthrough = findInProgressWalkthrough(getActiveGuides(), getLastGuideStepSeen());
21195
- if (walkthrough) {
21196
- monitor.saveContext(walkthrough);
21197
- return walkthrough.show('continue');
21286
+ else if (next.type === AutoDisplayType.continuation) {
21287
+ const { guide } = next;
21288
+ if (!isGuideShown({ channel: guide.channel })) {
21289
+ monitor.saveContext(guide);
21290
+ return guide.show('continue');
21198
21291
  }
21199
21292
  }
21200
- else if (next) {
21201
- if (findInProgressWalkthrough(getActiveGuides(), getLastGuideStepSeen())) {
21202
- this.cancel();
21203
- return;
21293
+ else {
21294
+ const { guide } = next;
21295
+ if (!isGuideShown({ channel: guide.channel })) {
21296
+ monitor.saveContext(guide);
21297
+ return AutoDisplay.tryDisplayGuide(guide, pendo$1);
21204
21298
  }
21205
- monitor.saveContext(next);
21206
- return AutoDisplay.tryDisplayGuide(next, pendo$1);
21207
21299
  }
21208
21300
  }
21209
21301
  handleProcessTimeExceeded(monitor) {
@@ -24792,9 +24884,8 @@ function setSeenTime(time) {
24792
24884
  function getSeenTime() {
24793
24885
  return seenTime;
24794
24886
  }
24795
- // Fix: this is a terrible name.
24796
- var isGuideShown = function () {
24797
- return _.any(getActiveGuides(), function (guide) {
24887
+ var isGuideShown = function (options = {}) {
24888
+ return _.any(getActiveGuides(options), function (guide) {
24798
24889
  return guide.isShown();
24799
24890
  });
24800
24891
  };
@@ -24879,8 +24970,8 @@ var getStepIdFromElement = function (element) {
24879
24970
  * @example
24880
24971
  * pendo.hideGuides({stayHidden: true})
24881
24972
  */
24882
- function hideGuides(hideOptions) {
24883
- _.each(getActiveGuides(), function (guide) {
24973
+ function hideGuides(hideOptions = {}) {
24974
+ _.each(getActiveGuides(hideOptions), function (guide) {
24884
24975
  if (_.isFunction(guide.isShown) && guide.isShown()) {
24885
24976
  guide.hide(hideOptions);
24886
24977
  }
@@ -25031,7 +25122,7 @@ var setFocusToActivationElement = function (guide) {
25031
25122
  }
25032
25123
  };
25033
25124
  function shouldAffectThrottling(guide, seenReason) {
25034
- return !guide.isMultiApp && (seenReason === 'auto' || seenReason === 'repeatGuide');
25125
+ return !guide.isMultiApp && !guide.channel && (seenReason === 'auto' || seenReason === 'repeatGuide');
25035
25126
  }
25036
25127
  /**
25037
25128
  * Hides the current guide and invokes the `guideDismissed` event. Dismissed guides will not
@@ -25638,7 +25729,7 @@ var showPreview = function () {
25638
25729
  };
25639
25730
  var isGuideRCType = _.partial(_.get, _, 'attributes.resourceCenter');
25640
25731
  var beforeShowGuide = function (guide) {
25641
- if (isGuideShown()) {
25732
+ if (isGuideShown({ channel: guide.channel })) {
25642
25733
  var guideStep = findStepForGuideEvent();
25643
25734
  removeGuideEventListeners(guideStep);
25644
25735
  if (isGuideRCType(guide)) {
@@ -25650,7 +25741,7 @@ var beforeShowGuide = function (guide) {
25650
25741
  }
25651
25742
  }
25652
25743
  else {
25653
- hideGuides();
25744
+ hideGuides({ channel: guide.channel });
25654
25745
  store.dispatch('frames/hideGuides');
25655
25746
  }
25656
25747
  }
@@ -25793,11 +25884,6 @@ function snoozeCanceledGuide(guideId, stepId, visitorId, seenReason, language) {
25793
25884
  stageGuideEvent(evt, null, true);
25794
25885
  Events.guideSnoozeCancelled.trigger(evt);
25795
25886
  }
25796
- var THROTTLING_STATE = {
25797
- DISMISSED: 'latestDismissedAutoAt',
25798
- SNOOZED: 'latestSnoozedAutoAt',
25799
- ADVANCED: 'finalAdvancedAutoAt'
25800
- };
25801
25887
  function writeThrottlingStateCache(time, cacheName) {
25802
25888
  _writeThrottlingStateCache(time, cacheName);
25803
25889
  var message = {};
@@ -25814,10 +25900,6 @@ function _writeThrottlingStateCache(time, cacheName) {
25814
25900
  agentStorage.write(cacheName, time, GUIDE_STATE_TTL);
25815
25901
  store.dispatch('guideState/updateThrottlingState', { name: cacheName, value: time });
25816
25902
  }
25817
- function readGuideStatusesFromStorage(cacheName) {
25818
- const cookieSuffix = ConfigReader.get('crossAppGuideStorageSuffix');
25819
- return agentStorage.read(cacheName, false, cookieSuffix);
25820
- }
25821
25903
  function createGuideEvent(name, guideId, stepId, visitorId, reason, language) {
25822
25904
  var params = name;
25823
25905
  if (typeof params !== 'object') {
@@ -25927,18 +26009,6 @@ var showGuideById = function (id, reason) {
25927
26009
  }
25928
26010
  return false;
25929
26011
  };
25930
- function applyTimerCache(timerValue, cachedTimerValue) {
25931
- cachedTimerValue = parseInt(cachedTimerValue, 10);
25932
- if (isNaN(cachedTimerValue) || !_.isNumber(cachedTimerValue))
25933
- return timerValue;
25934
- if (_.isNumber(timerValue) && cachedTimerValue > timerValue) {
25935
- return cachedTimerValue;
25936
- }
25937
- if (!_.isNumber(timerValue)) {
25938
- return cachedTimerValue;
25939
- }
25940
- return timerValue;
25941
- }
25942
26012
  var resetPendoUI = function () {
25943
26013
  stopGuides();
25944
26014
  clearLoopTimer();
@@ -25964,6 +26034,15 @@ function handleDoNotProcess() {
25964
26034
  store.commit('debugger/doNotProcess', true);
25965
26035
  log.info('not tracking visitor due to 451 response');
25966
26036
  }
26037
+ function clearDoNotProcess() {
26038
+ if (!pendo$1.doNotProcess)
26039
+ return;
26040
+ delete pendo$1.doNotProcess;
26041
+ unlockEvents();
26042
+ startGuides();
26043
+ store.commit('debugger/doNotProcess', false);
26044
+ log.info('cleared do not process flag');
26045
+ }
25967
26046
  function guidesPayload(guidesJson) {
25968
26047
  if (!mostRecentGuideRequest)
25969
26048
  return;
@@ -25973,6 +26052,9 @@ function guidesPayload(guidesJson) {
25973
26052
  }
25974
26053
  if (_.isString(guidesJson.id) && guidesJson.id !== mostRecentGuideRequest.id)
25975
26054
  return;
26055
+ if (ConfigReader.get('requestSegmentFlags')) {
26056
+ delete guidesJson.segmentFlags; // This is temporary until the BE stops sending segment flags in the guides payload, at which point this can be removed
26057
+ }
25976
26058
  _.extend(pendo$1, guidesJson);
25977
26059
  pendo$1.guides = _.map(pendo$1.guides, function (guide) {
25978
26060
  if (_.keys(guide).length == 1 && guide.id) {
@@ -26238,15 +26320,8 @@ var loadGuides = function (apiKey, visitorId, page, callback) {
26238
26320
  const activeGuides = buildActiveGuideList(pendo$1.guides);
26239
26321
  setActiveGuides(activeGuides);
26240
26322
  const displayableGuides = getDisplayableGuides();
26241
- store.dispatch('guideState/load', readGuideStatusesFromStorage(LAST_STEP_ADVANCED_COOKIE));
26323
+ store.dispatch('guideState/load');
26242
26324
  store.dispatch('guideState/apply');
26243
- pendo$1.latestDismissedAutoAt = applyTimerCache(pendo$1.latestDismissedAutoAt, agentStorage.read('latestDismissedAutoAt'));
26244
- store.dispatch('guideState/updateThrottlingState', { name: 'latestDismissedAutoAt', value: pendo$1.latestDismissedAutoAt });
26245
- pendo$1.finalAdvancedAutoAt = applyTimerCache(pendo$1.finalAdvancedAutoAt, agentStorage.read('finalAdvancedAutoAt'));
26246
- store.dispatch('guideState/updateThrottlingState', { name: 'finalAdvancedAutoAt', value: pendo$1.finalAdvancedAutoAt });
26247
- // APP-40144
26248
- pendo$1.latestSnoozedAutoAt = applyTimerCache(pendo$1.latestSnoozedAutoAt, agentStorage.read('latestSnoozedAutoAt'));
26249
- store.dispatch('guideState/updateThrottlingState', { name: 'latestSnoozedAutoAt', value: pendo$1.latestSnoozedAutoAt });
26250
26325
  store.dispatch('healthCheck/init', activeGuides);
26251
26326
  // This needs to run *immediately* when pendo.guides changes
26252
26327
  // so Events.guidesLoaded.trigger() doesn't cut it, since it
@@ -26528,6 +26603,7 @@ var initGuides = function (observer) {
26528
26603
  }
26529
26604
  });
26530
26605
  Events.identify.on(function () {
26606
+ clearDoNotProcess();
26531
26607
  queueGuideReload();
26532
26608
  });
26533
26609
  Events.urlChanged.on(function () {
@@ -26845,9 +26921,9 @@ function removeGuideProcessor(callback) {
26845
26921
  * @returns {Object | null}
26846
26922
  */
26847
26923
  // TODO: this needs to be updated to support an array of steps
26848
- function getActiveGuide() {
26924
+ function getActiveGuide(options) {
26849
26925
  var currentStep, currentSteps, stepIndex;
26850
- var currentGuide = _.find(getActiveGuides(), function (guide) { return guide.isShown(); });
26926
+ var currentGuide = _.find(getActiveGuides(options), function (guide) { return guide.isShown(); });
26851
26927
  if (!currentGuide)
26852
26928
  return null;
26853
26929
  if (_.get(currentGuide, 'attributes.resourceCenter.isModule')) {
@@ -28076,8 +28152,7 @@ var GuideActivity = (function () {
28076
28152
  return guide;
28077
28153
  }
28078
28154
  const stepId = getStepIdFromAppData(appData);
28079
- const activeGuide = getActiveGuide();
28080
- if (stepId && activeGuide && activeGuide.step && stepId != activeGuide.step.id) {
28155
+ if (stepId) {
28081
28156
  let step;
28082
28157
  const guide = _.find(getLocalActiveGuides(), function (guide) {
28083
28158
  step = _.find(guide.steps, (step) => step.id === stepId);
@@ -28087,7 +28162,7 @@ var GuideActivity = (function () {
28087
28162
  return { guide, step };
28088
28163
  }
28089
28164
  }
28090
- return activeGuide;
28165
+ return getActiveGuide();
28091
28166
  }
28092
28167
  })();
28093
28168
 
@@ -28126,6 +28201,11 @@ const PluginAPI = {
28126
28201
  removeGlobalScript: GuideRuntime.removeGlobalScript
28127
28202
  },
28128
28203
  GuideActivity,
28204
+ GuideEvents: {
28205
+ stageGuideEvent,
28206
+ createGuideEvent,
28207
+ getSeenTime
28208
+ },
28129
28209
  GuideLoop: {
28130
28210
  addUpdatePhase,
28131
28211
  removeUpdatePhase
@@ -28134,7 +28214,9 @@ const PluginAPI = {
28134
28214
  addProcessor: addGuideProcessor,
28135
28215
  removeProcessor: removeGuideProcessor,
28136
28216
  registerDisplayableGuides,
28137
- removeDisplayableGuides
28217
+ removeDisplayableGuides,
28218
+ GuideFactory,
28219
+ GuideStepFactory
28138
28220
  },
28139
28221
  hosts: {
28140
28222
  SERVER
@@ -28157,7 +28239,8 @@ const PluginAPI = {
28157
28239
  base64EncodeString,
28158
28240
  parseUrl,
28159
28241
  addInlineStyles: _.partial(addInlineStyles, ConfigReader),
28160
- getNow
28242
+ getNow,
28243
+ escapeRegExp
28161
28244
  },
28162
28245
  constants: {
28163
28246
  URL_MAX_LENGTH
@@ -28923,6 +29006,9 @@ function teardown() {
28923
29006
  initializeCounter = 0;
28924
29007
  }
28925
29008
 
29009
+ function getActiveDefaultGuide(options = { channel: Channel.DEFAULT }) {
29010
+ return getActiveGuide(options);
29011
+ }
28926
29012
  // CANDIDATES for behaviors to add to guides
28927
29013
  // Starting to expose some useful utilities from service experiences
28928
29014
  var smartNextStep = function (delay) {
@@ -28930,7 +29016,7 @@ var smartNextStep = function (delay) {
28930
29016
  // if it's not, skip that step.
28931
29017
  // need to know:
28932
29018
  // -- this steps' index
28933
- var activeObj = getActiveGuide();
29019
+ var activeObj = getActiveDefaultGuide();
28934
29020
  if (!activeObj)
28935
29021
  return;
28936
29022
  // var stepIndex = _.last(_.map(activeObj.steps, function(s){ return _.indexOf(activeObj.guide.steps, s); }));
@@ -28949,7 +29035,7 @@ var smartNextStep = function (delay) {
28949
29035
  setTimeout$1(checkNext, delay);
28950
29036
  };
28951
29037
  var advanceOn = function (eventType, elementPath) {
28952
- var obj = getActiveGuide();
29038
+ var obj = getActiveDefaultGuide();
28953
29039
  elementPath = elementPath || obj.step.elementPathRule;
28954
29040
  var btn = dom(elementPath)[0];
28955
29041
  var onEvent = function () {
@@ -28962,7 +29048,7 @@ var smartFirstStep = function () {
28962
29048
  dom('._pendo-guide_').css('display:none;');
28963
29049
  // look through steps to see which are applicable for the current url.
28964
29050
  var url = getNormalizedUrl();
28965
- var activeObj = getActiveGuide();
29051
+ var activeObj = getActiveDefaultGuide();
28966
29052
  var steps = activeObj.guide.steps;
28967
29053
  var testSteps = _.filter(_.rest(steps), function (step) {
28968
29054
  return !!step.pageId;
@@ -29002,7 +29088,7 @@ var renderStepPosition = function (template, guide, step) {
29002
29088
  return template(posObj);
29003
29089
  };
29004
29090
  var guideDev = {
29005
- getActiveGuide,
29091
+ getActiveGuide: getActiveDefaultGuide,
29006
29092
  smartNextStep,
29007
29093
  smartFirstStep,
29008
29094
  advanceOn,
@@ -30893,12 +30979,17 @@ function exportPublicApi(pendo) {
30893
30979
  pendo.startGuides = exportPendoCoreOnly(manuallyStartGuides);
30894
30980
  pendo.stopGuides = exportPendoCoreOnly(manuallyStopGuides);
30895
30981
  pendo.defaultCssUrl = exportPendoCoreOnly(getDefaultCssUrl());
30896
- pendo.getActiveGuides = getActiveGuides;
30897
- pendo.getActiveGuide = getActiveGuide;
30982
+ pendo.getActiveGuides = function (options = { channel: Channel.DEFAULT }) {
30983
+ return getActiveGuides(options);
30984
+ };
30985
+ pendo.getActiveGuide = function (options = { channel: Channel.DEFAULT }) {
30986
+ return getActiveGuide(options);
30987
+ };
30898
30988
  pendo.guideSeenTimeoutLength = StepTimeoutMonitor.getGuideSeenTimeoutLength();
30899
30989
  pendo.guidesPayload = guidesPayload;
30900
30990
  pendo.areGuidesDisabled = exportPendoCoreOnly(areGuidesDisabled);
30901
30991
  pendo.setGuidesDisabled = exportPendoCoreOnly(setGuidesDisabled);
30992
+ pendo.areGuidesDelayed = exportPendoCoreOnly(areGuidesDelayed);
30902
30993
  pendo.buildNodeFromJSON = BuildingBlockGuides.buildNodeFromJSON;
30903
30994
  pendo.flexElement = exportPendoCoreOnly(BuildingBlockGuides.flexElement);
30904
30995
  pendo.GuideFactory = exportPendoCoreOnly(GuideFactory);
@@ -31685,44 +31776,48 @@ function WalkthroughGuide() {
31685
31776
  // Do not continue a snoozed guide
31686
31777
  if (currentGuide.isGuideSnoozed())
31687
31778
  return null;
31688
- lastSeenObj = lastSeenObj || {};
31689
- for (var j = 0; j < currentGuide.steps.length; j++) {
31690
- if (currentGuide.steps[j].id === lastSeenObj.guideStepId) {
31691
- if (lastSeenObj.state === 'dismissed') {
31692
- // The guide was dismissed
31693
- break;
31694
- }
31695
- else if (lastSeenObj.state === 'active' || lastSeenObj.state === 'snoozed') {
31696
- // This is current.
31697
- nextStep = currentGuide.steps[j];
31698
- break;
31699
- }
31700
- else if (lastSeenObj.state === 'advanced' && lastSeenObj.destinationStepId) {
31701
- nextStep = _.find(currentGuide.steps, function (step) {
31702
- return step.id === lastSeenObj.destinationStepId;
31703
- });
31704
- break;
31705
- }
31706
- else if ((j + 1) < currentGuide.steps.length) {
31707
- // Get the step after that last one seen
31708
- nextStep = currentGuide.steps[j + 1];
31709
- break;
31779
+ if (lastSeenObj != null) {
31780
+ for (var j = 0; j < currentGuide.steps.length; j++) {
31781
+ if (currentGuide.steps[j].id === lastSeenObj.guideStepId) {
31782
+ if (lastSeenObj.state === 'dismissed') {
31783
+ // The guide was dismissed
31784
+ break;
31785
+ }
31786
+ else if (lastSeenObj.state === 'active' || lastSeenObj.state === 'snoozed') {
31787
+ // This is current.
31788
+ nextStep = currentGuide.steps[j];
31789
+ break;
31790
+ }
31791
+ else if (lastSeenObj.state === 'advanced' && lastSeenObj.destinationStepId) {
31792
+ nextStep = _.find(currentGuide.steps, function (step) {
31793
+ return step.id === lastSeenObj.destinationStepId;
31794
+ });
31795
+ break;
31796
+ }
31797
+ else if ((j + 1) < currentGuide.steps.length) {
31798
+ // Get the step after that last one seen
31799
+ nextStep = currentGuide.steps[j + 1];
31800
+ break;
31801
+ }
31710
31802
  }
31711
31803
  }
31712
- }
31713
- if (nextStep) {
31714
- var now = new Date().getTime();
31715
- var lastSeenTime = lastSeenObj.time;
31716
- if (lastSeenTime &&
31717
- ((now - lastSeenTime) > MULTISTEP_CONTINUATION_TIME_LIMIT) &&
31718
- !isOB(currentGuide)) {
31719
- if (!didLogContinuationExpired) {
31720
- log.info('Multi-step continuation has expired', { contexts: ['guides', 'info'] });
31721
- didLogContinuationExpired = true;
31804
+ if (nextStep) {
31805
+ var now = new Date().getTime();
31806
+ var lastSeenTime = lastSeenObj.time;
31807
+ if (lastSeenTime &&
31808
+ ((now - lastSeenTime) > MULTISTEP_CONTINUATION_TIME_LIMIT) &&
31809
+ !isOB(currentGuide)) {
31810
+ if (!didLogContinuationExpired) {
31811
+ log.info('Multi-step continuation has expired', { contexts: ['guides', 'info'] });
31812
+ didLogContinuationExpired = true;
31813
+ }
31814
+ return null;
31722
31815
  }
31723
- return null;
31816
+ return nextStep;
31724
31817
  }
31725
- return nextStep;
31818
+ }
31819
+ else {
31820
+ return findNextStepFromState(currentGuide);
31726
31821
  }
31727
31822
  return null;
31728
31823
  };
@@ -31772,6 +31867,40 @@ function WalkthroughGuide() {
31772
31867
  }
31773
31868
  return this;
31774
31869
  }
31870
+ /*
31871
+ * Finds next step in guide based on seen state/time of steps (instead of pendo.lastGuideStepSeen)
31872
+ */
31873
+ function findNextStepFromState(guide) {
31874
+ const { steps } = guide;
31875
+ if (!steps || !steps.length)
31876
+ return null;
31877
+ // find the step with the most recent lastSeenAt
31878
+ const { currentStep, currentIndex } = _.reduce(steps, (memo, currentStep, currentIndex) => {
31879
+ const { lastSeenAt } = memo.currentStep;
31880
+ if (lastSeenAt == null)
31881
+ return memo;
31882
+ return currentStep.lastSeenAt > lastSeenAt ? { currentStep, currentIndex } : memo;
31883
+ }, { currentStep: steps[0], currentIndex: 0 });
31884
+ if (currentStep.seenState === 'dismissed')
31885
+ return null;
31886
+ if (typeof currentStep.isSnoozed === 'function' && currentStep.isSnoozed()) {
31887
+ return null;
31888
+ }
31889
+ if (currentStep.seenState === 'active' || currentStep.seenState === 'snoozed')
31890
+ return currentStep;
31891
+ if (currentStep.seenState === 'advanced') {
31892
+ const { destinationStepId } = currentStep;
31893
+ if (destinationStepId) {
31894
+ return _.find(steps, function (step) {
31895
+ return step.id === destinationStepId;
31896
+ });
31897
+ }
31898
+ else {
31899
+ return steps[currentIndex + 1] || null;
31900
+ }
31901
+ }
31902
+ return null;
31903
+ }
31775
31904
 
31776
31905
  /*
31777
31906
  * Traps and logs errors that occur while displaying a guide. If the
@@ -33842,7 +33971,7 @@ function updateMasterGuideList(state) {
33842
33971
  })
33843
33972
  .map(GuideFactory)
33844
33973
  .value();
33845
- var mergedGuideList = _.toArray(guidesInThisFrame).concat(guidesInOtherFrames).filter(runGuideProcessors);
33974
+ var mergedGuideList = _.filter(_.toArray(guidesInThisFrame).concat(guidesInOtherFrames), runGuideProcessors);
33846
33975
  sortGuidesByPriority(mergedGuideList);
33847
33976
  initializeResourceCenter(mergedGuideList);
33848
33977
  setActiveGuides(mergedGuideList);
@@ -34430,7 +34559,7 @@ const DebuggerModule = (() => {
34430
34559
  store.commit('debugger/stepEligibilitySet', stepElg);
34431
34560
  }
34432
34561
  function guidesLoadedFn(evt) {
34433
- const autoOrdering = _.map(AutoDisplay.sortAndFilter(getActiveGuides(), pendo$1.autoOrdering), guide => guide.id);
34562
+ const autoOrdering = _.map(AutoDisplay.sortAndFilter(getActiveGuides({ channel: Channel.DEFAULT }), pendo$1.autoOrdering), guide => guide.id);
34434
34563
  store.commit('debugger/autoOrdering', autoOrdering || []);
34435
34564
  store.commit('debugger/excludedGuides', pendo$1.excludedGuides || []);
34436
34565
  store.commit('debugger/throttling', pendo$1.throttling || {});
@@ -37946,14 +38075,15 @@ const OemAccountId = (function () {
37946
38075
 
37947
38076
  var debugging;
37948
38077
  function debuggerExports() {
38078
+ const getActiveDefaultGuides = () => getActiveGuides({ channel: Channel.DEFAULT });
37949
38079
  return {
37950
38080
  store,
37951
38081
  ConfigReader,
37952
38082
  getState() { return JSON.stringify(store.state); },
37953
38083
  getEventCache() { return [].concat(eventCache); },
37954
- getAllGuides() { return [].concat(getActiveGuides()); },
37955
- getAutoGuides() { return AutoDisplay.sortAndFilter(getActiveGuides(), pendo$1.autoOrdering); },
37956
- getBadgeGuides() { return _.filter(getActiveGuides(), isBadge); },
38084
+ getAllGuides() { return [].concat(getActiveDefaultGuides()); },
38085
+ getAutoGuides() { return AutoDisplay.sortAndFilter(getActiveDefaultGuides(), pendo$1.autoOrdering); },
38086
+ getBadgeGuides() { return _.filter(getActiveDefaultGuides(), isBadge); },
37957
38087
  getLauncherGuides() { return []; },
37958
38088
  getEventHistory() { return []; },
37959
38089
  getAllFrames() { return store.getters['frames/allFrames'](); },
@@ -37962,7 +38092,6 @@ function debuggerExports() {
37962
38092
  setActiveGuides,
37963
38093
  getBody: dom.getBody,
37964
38094
  isMobileUserAgent: sniffer.isMobileUserAgent,
37965
- areGuidesDelayed,
37966
38095
  doesElementMatchContainsRules,
37967
38096
  getMetadata,
37968
38097
  isStagingServer,
@@ -38928,6 +39057,7 @@ class SessionManager {
38928
39057
  }
38929
39058
  var SessionManager$1 = new SessionManager();
38930
39059
 
39060
+ const SEGMENT_FLAGS_CACHE = 'segmentFlagsCache';
38931
39061
  class SegmentFlags {
38932
39062
  constructor() {
38933
39063
  this.name = 'SegmentFlags';
@@ -38945,26 +39075,57 @@ class SegmentFlags {
38945
39075
  if (!this.segmentFlagsEnabled)
38946
39076
  return;
38947
39077
  this.mostRecentSegmentsRequest = null;
39078
+ /**
39079
+ * Stores the cached segment flags for the current visitor.
39080
+ * Cleared on identity change and refreshed from server on page load.
39081
+ *
39082
+ * @name _pendo_segmentFlagsCache
39083
+ * @category Cookies/localStorage
39084
+ * @access public
39085
+ * @label SEGMENT_FLAGS_CACHE
39086
+ */
39087
+ PluginAPI.agentStorage.registry.addLocal(SEGMENT_FLAGS_CACHE, {
39088
+ isSecure: true,
39089
+ serializer: JSON.stringify,
39090
+ deserializer: SafeJsonDeserializer
39091
+ });
39092
+ if (shouldPersist()) {
39093
+ try {
39094
+ const cached = PluginAPI.agentStorage.read(SEGMENT_FLAGS_CACHE);
39095
+ if (cached) {
39096
+ this.pendo.segmentFlags = cached;
39097
+ }
39098
+ }
39099
+ catch (e) {
39100
+ // ignore read errors
39101
+ }
39102
+ }
38948
39103
  this.pendo.segmentsPayload = this.pendo._.bind(this.segmentsPayload, this);
38949
- this.handleMetadataChange = this.pendo._.debounce(this.pendo._.bind(this.requestSegmentFlags, this), 50);
38950
39104
  this.handleReadyBound = this.pendo._.bind(this.handleReady, this);
39105
+ this.handleIdentityChangeBound = this.pendo._.bind(this.handleIdentityChange, this);
38951
39106
  this.api.Events.ready.on(this.handleReadyBound);
38952
- this.api.Events.metadata.on(this.handleMetadataChange);
38953
- this.api.Events.identify.on(this.handleMetadataChange);
39107
+ this.api.Events.identify.on(this.handleIdentityChangeBound);
39108
+ this.api.Events.metadata.on(this.handleIdentityChangeBound);
38954
39109
  }
38955
39110
  teardown() {
38956
39111
  if (!this.segmentFlagsEnabled)
38957
39112
  return;
38958
39113
  this.pendo.segmentsPayload = this.pendo._.noop;
38959
- this.handleMetadataChange.cancel();
38960
39114
  this.api.Events.ready.off(this.handleReadyBound);
38961
- this.api.Events.metadata.off(this.handleMetadataChange);
38962
- this.api.Events.identify.off(this.handleMetadataChange);
39115
+ this.api.Events.identify.off(this.handleIdentityChangeBound);
39116
+ this.api.Events.metadata.off(this.handleIdentityChangeBound);
38963
39117
  }
38964
39118
  handleReady() {
38965
39119
  this.ready = true;
38966
39120
  this.requestSegmentFlags();
38967
39121
  }
39122
+ handleIdentityChange(event) {
39123
+ if (this.pendo._.get(event, 'data[0].wasCleared')) {
39124
+ this.api.agentStorage.clear(SEGMENT_FLAGS_CACHE);
39125
+ delete this.pendo.segmentFlags;
39126
+ }
39127
+ this.requestSegmentFlags();
39128
+ }
38968
39129
  requestSegmentFlags() {
38969
39130
  if (!this.ready)
38970
39131
  return;
@@ -39013,10 +39174,23 @@ class SegmentFlags {
39013
39174
  return;
39014
39175
  if (this.pendo._.isString(payload.id) && payload.id !== this.mostRecentSegmentsRequest)
39015
39176
  return;
39177
+ const changed = this.flagsChanged(this.pendo.segmentFlags, payload.segmentFlags);
39016
39178
  this.pendo.segmentFlags = payload.segmentFlags;
39179
+ if (shouldPersist()) {
39180
+ this.api.agentStorage.write(SEGMENT_FLAGS_CACHE, payload.segmentFlags);
39181
+ }
39182
+ if (changed) {
39183
+ this.api.Events.segmentFlagsUpdated.trigger(this.pendo.segmentFlags);
39184
+ }
39017
39185
  this.api.log.info('successfully loaded segment flags');
39018
39186
  this.mostRecentSegmentsRequest = null;
39019
39187
  }
39188
+ flagsChanged(oldFlags = [], newFlags = []) {
39189
+ if (oldFlags.length !== newFlags.length)
39190
+ return true;
39191
+ const intersection = this.pendo._.intersection(oldFlags, newFlags);
39192
+ return intersection.length !== oldFlags.length;
39193
+ }
39020
39194
  scriptLoad(url) {
39021
39195
  this.pendo.loadResource(url, this.pendo._.noop);
39022
39196
  }
@@ -40541,18 +40715,30 @@ function TextCapture() {
40541
40715
  function guideActivity(pendo, event) {
40542
40716
  if (!isEnabled())
40543
40717
  return;
40544
- var eventData = event.data[0];
40718
+ const { _ } = pendo;
40719
+ const eventData = event.data[0];
40545
40720
  if (eventData && eventData.type === 'guideActivity') {
40546
- var activeGuideObj = pendo.getActiveGuide();
40547
- if (!activeGuideObj)
40721
+ const shownSteps = _.reduce(pendo.getActiveGuides({ channel: '*' }), (shown, guide) => {
40722
+ if (guide.isShown()) {
40723
+ return shown.concat(_.filter(guide.steps, (step) => step.isShown()));
40724
+ }
40725
+ return shown;
40726
+ }, []);
40727
+ if (!shownSteps.length)
40548
40728
  return;
40549
- var findDomBlockInDomJson = pendo.BuildingBlocks.BuildingBlockGuides.findDomBlockInDomJson;
40550
- var element = findDomBlockInDomJson(activeGuideObj.step.domJson, function (domJson) {
40551
- return domJson.props && domJson.props.id && domJson.props.id === eventData.props.ui_element_id;
40729
+ const findDomBlockInDomJson = pendo.BuildingBlocks.BuildingBlockGuides.findDomBlockInDomJson;
40730
+ let elementJson;
40731
+ _.find(shownSteps, (step) => {
40732
+ if (!step.domJson)
40733
+ return false;
40734
+ elementJson = findDomBlockInDomJson(step.domJson, function (domJson) {
40735
+ return domJson.props && domJson.props.id && domJson.props.id === eventData.props.ui_element_id;
40736
+ });
40737
+ return elementJson;
40552
40738
  });
40553
- if (!element)
40739
+ if (!elementJson)
40554
40740
  return;
40555
- eventData.props.ui_element_text = element.content;
40741
+ eventData.props.ui_element_text = elementJson.content;
40556
40742
  }
40557
40743
  }
40558
40744
  function isEnabled() {
@@ -40815,6 +41001,30 @@ const MetadataSubstitution = {
40815
41001
  },
40816
41002
  designerListener(pendo) {
40817
41003
  const target = pendo.dom.getBody();
41004
+ if (pendo.designerv2) {
41005
+ pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
41006
+ var _a;
41007
+ if (!document.querySelector(guideMarkdownUtil.containerSelector))
41008
+ return;
41009
+ const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41010
+ if (!step)
41011
+ return;
41012
+ const placeholderData = findSubstitutableElements(pendo);
41013
+ if (step.buildingBlocks) {
41014
+ findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
41015
+ }
41016
+ if (pendo._.size(placeholderData)) {
41017
+ pendo._.each(placeholderData, function (placeholder) {
41018
+ if (pendo._.isUndefined(placeholder))
41019
+ return;
41020
+ processPlaceholder(placeholder, pendo);
41021
+ });
41022
+ const containerId = `pendo-g-${step.id}`;
41023
+ const context = step.guideElement;
41024
+ updateGuideContainer(containerId, context, pendo);
41025
+ }
41026
+ };
41027
+ }
40818
41028
  const config = {
40819
41029
  attributeFilter: ['data-layout'],
40820
41030
  attributes: true,
@@ -40859,8 +41069,14 @@ function processPlaceholder(placeholder, pendo) {
40859
41069
  const { data, target } = placeholder;
40860
41070
  const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
40861
41071
  while ((match = matchPlaceholder(placeholder, subRegex))) {
40862
- let matched = subRegex.exec(match);
40863
- let mdValue = getSubstituteValue(matched, pendo);
41072
+ const usedArrayPath = Array.isArray(match) && match.length >= 2;
41073
+ const currentStr = target === 'textContent'
41074
+ ? data[target]
41075
+ : decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
41076
+ const matched = usedArrayPath ? match : subRegex.exec(currentStr);
41077
+ if (!matched)
41078
+ continue;
41079
+ const mdValue = getSubstituteValue(matched, pendo);
40864
41080
  substituteMetadataByTarget(data, target, mdValue, matched);
40865
41081
  }
40866
41082
  }
@@ -40869,29 +41085,52 @@ function matchPlaceholder(placeholder, regex) {
40869
41085
  return placeholder.data[placeholder.target].match(regex);
40870
41086
  }
40871
41087
  else {
40872
- return decodeURI(placeholder.data[placeholder.target]).match(regex);
41088
+ const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
41089
+ ? (placeholder.data.getAttribute(placeholder.target) || '')
41090
+ : placeholder.data[placeholder.target];
41091
+ return decodeURI(raw).match(regex);
41092
+ }
41093
+ }
41094
+ function getMetadataValueCaseInsensitive(metadata, type, property) {
41095
+ const kind = metadata && metadata[type];
41096
+ if (!kind || typeof kind !== 'object')
41097
+ return undefined;
41098
+ const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
41099
+ if (direct !== undefined) {
41100
+ return direct;
40873
41101
  }
41102
+ const propLower = property.toLowerCase();
41103
+ const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
41104
+ const value = key !== undefined ? kind[key] : undefined;
41105
+ return value;
40874
41106
  }
40875
41107
  function getSubstituteValue(match, pendo) {
40876
- if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2]))
41108
+ if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
40877
41109
  return;
41110
+ }
40878
41111
  let type = match[1];
40879
41112
  let property = match[2];
40880
41113
  let defaultValue = match[3];
40881
41114
  if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
40882
41115
  return;
40883
41116
  }
40884
- let mdValue = pendo._.get(pendo.getSerializedMetadata(), `${type}.${property}`) || defaultValue || '';
41117
+ const metadata = pendo.getSerializedMetadata();
41118
+ let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
41119
+ if (mdValue === undefined || mdValue === null)
41120
+ mdValue = defaultValue || '';
40885
41121
  return mdValue;
40886
41122
  }
40887
41123
  function substituteMetadataByTarget(data, target, mdValue, matched) {
41124
+ const isElement = data && typeof data.getAttribute === 'function';
41125
+ const current = (target === 'href' || target === 'value') && isElement
41126
+ ? (data.getAttribute(target) || '')
41127
+ : data[target];
40888
41128
  if (target === 'href' || target === 'value') {
40889
- data[target] = decodeURI(data[target])
40890
- .replace(matched[0], window.encodeURI(mdValue));
41129
+ const safeValue = window.encodeURIComponent(String(mdValue === undefined || mdValue === null ? '' : mdValue));
41130
+ data[target] = decodeURI(current).replace(matched[0], safeValue);
40891
41131
  }
40892
41132
  else {
40893
- data[target] = data[target]
40894
- .replace(matched[0], mdValue);
41133
+ data[target] = current.replace(matched[0], mdValue);
40895
41134
  }
40896
41135
  }
40897
41136
  function updateGuideContainer(containerId, context, pendo) {
@@ -53771,6 +54010,7 @@ const RECORDING_CONFIG_TREAT_IFRAME_AS_ROOT = 'recording.treatIframeAsRoot';
53771
54010
  const RECORDING_CONFIG_DISABLE_UNLOAD = 'recording.disableUnload';
53772
54011
  const RESOURCE_CACHING = 'resourceCaching';
53773
54012
  const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
54013
+ const ONE_MINUTE_IN_MILLISECONDS = 60 * 1000;
53774
54014
  const THIRTY_MINUTES = 1000 * 60 * 30;
53775
54015
  const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
53776
54016
  const SESSION_RECORDING_ID = 'pendo_srId';
@@ -53893,6 +54133,7 @@ class SessionRecorder {
53893
54133
  this.transport.onWorkerMessage = bind(this.onWorkerMessage, this);
53894
54134
  this.sendQueue = new SendQueue(bind(this.transport.send, this.transport));
53895
54135
  this.sendQueue.onTimeout = bind(this.sendFailure, this, 'SEND_TIMEOUT');
54136
+ this.errorHandler = this.pendo._.throttle(bind(this.logStopReason, this, 'RRWEB_ERROR'), ONE_MINUTE_IN_MILLISECONDS, { trailing: false });
53896
54137
  this.isNewSession = false;
53897
54138
  this.isCheckingVisitorEligibility = false;
53898
54139
  this.pageLifecycleListeners = [];
@@ -54187,7 +54428,7 @@ class SessionRecorder {
54187
54428
  var config = this.recordingConfig(visitorConfig);
54188
54429
  this._stop = this.record(this.pendo._.extend({
54189
54430
  emit: bind(this.emit, this),
54190
- errorHandler: bind(this.errorHandler, this)
54431
+ errorHandler: this.errorHandler
54191
54432
  }, config));
54192
54433
  this._refreshIds();
54193
54434
  this.onRecordingStart();
@@ -54299,9 +54540,6 @@ class SessionRecorder {
54299
54540
  return null;
54300
54541
  }
54301
54542
  }
54302
- errorHandler(error) {
54303
- this.logStopReason('RRWEB_ERROR', error);
54304
- }
54305
54543
  /**
54306
54544
  * Handle new rrweb events coming in. This will also make sure that we are properly sending a "keyframe"
54307
54545
  * as the BE expects it. A "keyframe" should consist of only the events needed to start a recording. This includes
@@ -54609,7 +54847,7 @@ class SessionRecorder {
54609
54847
  recordingPayload: [],
54610
54848
  sequence: 0,
54611
54849
  recordingPayloadCount: 0,
54612
- props: Object.assign({ reason }, (error && { error }))
54850
+ props: Object.assign({ reason }, (error && { error: error instanceof Error ? error === null || error === void 0 ? void 0 : error.message : error }))
54613
54851
  }, tracer);
54614
54852
  var jzb = this.pendo.compress(payload);
54615
54853
  var url = this.buildRequestUrl(`${this.pendo.HOST}/data/rec/${this.pendo.apiKey}`, {
@@ -57032,7 +57270,7 @@ var ConfigReader = (function () {
57032
57270
  * @default false
57033
57271
  * @type {boolean}
57034
57272
  */
57035
- addOption('guides.delay', [SNIPPET_SRC], undefined, undefined, ['delayGuides']);
57273
+ addOption('guides.delay', [SNIPPET_SRC], false, undefined, ['delayGuides']);
57036
57274
  /**
57037
57275
  * Completely disables guides (this option has been moved from `disableGuides`).
57038
57276
  * Alias: `disableGuides`
@@ -57043,7 +57281,7 @@ var ConfigReader = (function () {
57043
57281
  * @default false
57044
57282
  * @type {boolean}
57045
57283
  */
57046
- addOption('guides.disabled', [SNIPPET_SRC], undefined, undefined, ['disableGuides']);
57284
+ addOption('guides.disabled', [SNIPPET_SRC], false, undefined, ['disableGuides']);
57047
57285
  /**
57048
57286
  * If 'true', guides with slow selectors will be removed from guide display processing.
57049
57287
  * This will improve application performance, but slow guides will not be shown to users.
@@ -58304,6 +58542,7 @@ function NetworkCapture() {
58304
58542
  let responseBodyCb;
58305
58543
  let pendoDevlogBaseUrl;
58306
58544
  let isCapturingNetworkLogs = false;
58545
+ let excludeRequestUrls = [];
58307
58546
  const CAPTURE_NETWORK_CONFIG = 'captureNetworkRequests';
58308
58547
  const NETWORK_SUB_TYPE = 'network';
58309
58548
  const NETWORK_LOGS_CONFIG = 'networkLogs';
@@ -58311,6 +58550,7 @@ function NetworkCapture() {
58311
58550
  const NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS = 'networkLogs.allowedResponseHeaders';
58312
58551
  const NETWORK_LOGS_CONFIG_CAPTURE_REQUEST_BODY = 'networkLogs.captureRequestBody';
58313
58552
  const NETWORK_LOGS_CONFIG_CAPTURE_RESPONSE_BODY = 'networkLogs.captureResponseBody';
58553
+ const NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS = 'networkLogs.excludeRequestUrls';
58314
58554
  const allowedRequestHeaders = {
58315
58555
  'content-type': true, 'content-length': true, 'accept': true, 'accept-language': true
58316
58556
  };
@@ -58341,6 +58581,8 @@ function NetworkCapture() {
58341
58581
  processBody,
58342
58582
  processRequestBody,
58343
58583
  processResponseBody,
58584
+ buildExcludeRequestUrls,
58585
+ isUrlExcluded,
58344
58586
  get isCapturingNetworkLogs() {
58345
58587
  return isCapturingNetworkLogs;
58346
58588
  },
@@ -58367,6 +58609,9 @@ function NetworkCapture() {
58367
58609
  },
58368
58610
  get responseBodyCb() {
58369
58611
  return responseBodyCb;
58612
+ },
58613
+ get excludeRequestUrls() {
58614
+ return excludeRequestUrls;
58370
58615
  }
58371
58616
  };
58372
58617
  function initialize(pendo, PluginAPI) {
@@ -58384,6 +58629,7 @@ function NetworkCapture() {
58384
58629
  processHeaderConfig(NETWORK_LOGS_CONFIG_ALLOWED_REQUEST_HEADERS, allowedRequestHeaders);
58385
58630
  processHeaderConfig(NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS, allowedResponseHeaders);
58386
58631
  setupBodyCallbacks();
58632
+ buildExcludeRequestUrls();
58387
58633
  sendInterval = setInterval(() => {
58388
58634
  if (!sendQueue.failed()) {
58389
58635
  send();
@@ -58444,13 +58690,26 @@ function NetworkCapture() {
58444
58690
  * @type {function}
58445
58691
  */
58446
58692
  ConfigReader.addOption(NETWORK_LOGS_CONFIG_CAPTURE_RESPONSE_BODY, [ConfigReader.sources.SNIPPET_SRC], undefined);
58693
+ /**
58694
+ * A list of request URL patterns to exclude from network capture.
58695
+ * String patterns must match the full URL, including query parameters and fragments.
58696
+ * Use RegExp for flexible or partial matching.
58697
+ *
58698
+ * Example: `['https://example.com', new RegExp('https://test\\.com\\/.*'), /.*\\.domain\\.com/]`
58699
+ * @access public
58700
+ * @category Config/Network Logs
58701
+ * @name networkLogs.excludeRequestUrls
58702
+ * @default []
58703
+ * @type {Array<string|RegExp>}
58704
+ */
58705
+ ConfigReader.addOption(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS, [ConfigReader.sources.SNIPPET_SRC], []);
58447
58706
  }
58448
58707
  function processHeaderConfig(configHeaderName, targetHeaders) {
58449
58708
  const configHeaders = pluginAPI.ConfigReader.get(configHeaderName);
58450
58709
  if (!configHeaders || configHeaders.length === 0)
58451
58710
  return;
58452
58711
  globalPendo._.each(configHeaders, (header) => {
58453
- if (!header || typeof header !== 'string')
58712
+ if (!header || !globalPendo._.isString(header))
58454
58713
  return;
58455
58714
  targetHeaders[header.toLowerCase()] = true;
58456
58715
  });
@@ -58466,6 +58725,28 @@ function NetworkCapture() {
58466
58725
  responseBodyCb = config.captureResponseBody;
58467
58726
  }
58468
58727
  }
58728
+ function buildExcludeRequestUrls() {
58729
+ const requestUrls = pluginAPI.ConfigReader.get(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS);
58730
+ if (!requestUrls || requestUrls.length === 0)
58731
+ return;
58732
+ globalPendo._.each(requestUrls, (requestUrl) => {
58733
+ const processedRequestUrl = processUrlPattern(requestUrl);
58734
+ if (!processedRequestUrl)
58735
+ return;
58736
+ excludeRequestUrls.push(processedRequestUrl);
58737
+ });
58738
+ }
58739
+ function processUrlPattern(url) {
58740
+ if (!url)
58741
+ return;
58742
+ const isRegex = globalPendo._.isRegExp(url);
58743
+ if (!globalPendo._.isString(url) && !isRegex)
58744
+ return;
58745
+ if (isRegex)
58746
+ return url;
58747
+ const escapedUrl = pluginAPI.util.escapeRegExp(url);
58748
+ return new RegExp(`^${escapedUrl}$`);
58749
+ }
58469
58750
  function onPtmPaused() {
58470
58751
  isPtmPaused = true;
58471
58752
  }
@@ -58518,8 +58799,17 @@ function NetworkCapture() {
58518
58799
  pluginAPI.Events['recording:unpaused'].off(recordingStarted);
58519
58800
  pluginAPI.Events['recording:paused'].off(recordingStopped);
58520
58801
  }
58802
+ function isUrlExcluded(url) {
58803
+ if (!url || !globalPendo._.isString(url))
58804
+ return false;
58805
+ if (excludeRequestUrls.length === 0)
58806
+ return false;
58807
+ return globalPendo._.some(excludeRequestUrls, (excludeRequestUrl) => {
58808
+ return excludeRequestUrl.test(url);
58809
+ });
58810
+ }
58521
58811
  function handleRequest(request) {
58522
- if (!isCapturingNetworkLogs)
58812
+ if (!isCapturingNetworkLogs || !request || isUrlExcluded(request.url))
58523
58813
  return;
58524
58814
  requestMap[request.requestId] = request;
58525
58815
  }
@@ -58576,7 +58866,7 @@ function NetworkCapture() {
58576
58866
  }, []);
58577
58867
  }
58578
58868
  function processBody(body, contentType) {
58579
- if (!body || typeof body !== 'string')
58869
+ if (!body || !globalPendo._.isString(body))
58580
58870
  return '';
58581
58871
  const processedBody = maskSensitiveFields({ string: body, contentType, _: globalPendo._ });
58582
58872
  return truncate(processedBody, true);