@pendo/agent 2.314.1 → 2.315.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.1_';
3949
- let PACKAGE_VERSION = '2.314.1';
3948
+ let VERSION = '2.315.1_';
3949
+ let PACKAGE_VERSION = '2.315.1';
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
@@ -26523,6 +26598,7 @@ var initGuides = function (observer) {
26523
26598
  }
26524
26599
  });
26525
26600
  Events.identify.on(function () {
26601
+ clearDoNotProcess();
26526
26602
  queueGuideReload();
26527
26603
  });
26528
26604
  Events.urlChanged.on(function () {
@@ -26840,9 +26916,9 @@ function removeGuideProcessor(callback) {
26840
26916
  * @returns {Object | null}
26841
26917
  */
26842
26918
  // TODO: this needs to be updated to support an array of steps
26843
- function getActiveGuide() {
26919
+ function getActiveGuide(options) {
26844
26920
  var currentStep, currentSteps, stepIndex;
26845
- var currentGuide = _.find(getActiveGuides(), function (guide) { return guide.isShown(); });
26921
+ var currentGuide = _.find(getActiveGuides(options), function (guide) { return guide.isShown(); });
26846
26922
  if (!currentGuide)
26847
26923
  return null;
26848
26924
  if (_.get(currentGuide, 'attributes.resourceCenter.isModule')) {
@@ -28071,8 +28147,7 @@ var GuideActivity = (function () {
28071
28147
  return guide;
28072
28148
  }
28073
28149
  const stepId = getStepIdFromAppData(appData);
28074
- const activeGuide = getActiveGuide();
28075
- if (stepId && activeGuide && activeGuide.step && stepId != activeGuide.step.id) {
28150
+ if (stepId) {
28076
28151
  let step;
28077
28152
  const guide = _.find(getLocalActiveGuides(), function (guide) {
28078
28153
  step = _.find(guide.steps, (step) => step.id === stepId);
@@ -28082,7 +28157,7 @@ var GuideActivity = (function () {
28082
28157
  return { guide, step };
28083
28158
  }
28084
28159
  }
28085
- return activeGuide;
28160
+ return getActiveGuide();
28086
28161
  }
28087
28162
  })();
28088
28163
 
@@ -28121,6 +28196,11 @@ const PluginAPI = {
28121
28196
  removeGlobalScript: GuideRuntime.removeGlobalScript
28122
28197
  },
28123
28198
  GuideActivity,
28199
+ GuideEvents: {
28200
+ stageGuideEvent,
28201
+ createGuideEvent,
28202
+ getSeenTime
28203
+ },
28124
28204
  GuideLoop: {
28125
28205
  addUpdatePhase,
28126
28206
  removeUpdatePhase
@@ -28129,7 +28209,9 @@ const PluginAPI = {
28129
28209
  addProcessor: addGuideProcessor,
28130
28210
  removeProcessor: removeGuideProcessor,
28131
28211
  registerDisplayableGuides,
28132
- removeDisplayableGuides
28212
+ removeDisplayableGuides,
28213
+ GuideFactory,
28214
+ GuideStepFactory
28133
28215
  },
28134
28216
  hosts: {
28135
28217
  SERVER
@@ -28152,7 +28234,8 @@ const PluginAPI = {
28152
28234
  base64EncodeString,
28153
28235
  parseUrl,
28154
28236
  addInlineStyles: _.partial(addInlineStyles, ConfigReader),
28155
- getNow
28237
+ getNow,
28238
+ escapeRegExp
28156
28239
  },
28157
28240
  constants: {
28158
28241
  URL_MAX_LENGTH
@@ -28918,6 +29001,9 @@ function teardown() {
28918
29001
  initializeCounter = 0;
28919
29002
  }
28920
29003
 
29004
+ function getActiveDefaultGuide(options = { channel: Channel.DEFAULT }) {
29005
+ return getActiveGuide(options);
29006
+ }
28921
29007
  // CANDIDATES for behaviors to add to guides
28922
29008
  // Starting to expose some useful utilities from service experiences
28923
29009
  var smartNextStep = function (delay) {
@@ -28925,7 +29011,7 @@ var smartNextStep = function (delay) {
28925
29011
  // if it's not, skip that step.
28926
29012
  // need to know:
28927
29013
  // -- this steps' index
28928
- var activeObj = getActiveGuide();
29014
+ var activeObj = getActiveDefaultGuide();
28929
29015
  if (!activeObj)
28930
29016
  return;
28931
29017
  // var stepIndex = _.last(_.map(activeObj.steps, function(s){ return _.indexOf(activeObj.guide.steps, s); }));
@@ -28944,7 +29030,7 @@ var smartNextStep = function (delay) {
28944
29030
  setTimeout$1(checkNext, delay);
28945
29031
  };
28946
29032
  var advanceOn = function (eventType, elementPath) {
28947
- var obj = getActiveGuide();
29033
+ var obj = getActiveDefaultGuide();
28948
29034
  elementPath = elementPath || obj.step.elementPathRule;
28949
29035
  var btn = dom(elementPath)[0];
28950
29036
  var onEvent = function () {
@@ -28957,7 +29043,7 @@ var smartFirstStep = function () {
28957
29043
  dom('._pendo-guide_').css('display:none;');
28958
29044
  // look through steps to see which are applicable for the current url.
28959
29045
  var url = getNormalizedUrl();
28960
- var activeObj = getActiveGuide();
29046
+ var activeObj = getActiveDefaultGuide();
28961
29047
  var steps = activeObj.guide.steps;
28962
29048
  var testSteps = _.filter(_.rest(steps), function (step) {
28963
29049
  return !!step.pageId;
@@ -28997,7 +29083,7 @@ var renderStepPosition = function (template, guide, step) {
28997
29083
  return template(posObj);
28998
29084
  };
28999
29085
  var guideDev = {
29000
- getActiveGuide,
29086
+ getActiveGuide: getActiveDefaultGuide,
29001
29087
  smartNextStep,
29002
29088
  smartFirstStep,
29003
29089
  advanceOn,
@@ -30888,12 +30974,17 @@ function exportPublicApi(pendo) {
30888
30974
  pendo.startGuides = exportPendoCoreOnly(manuallyStartGuides);
30889
30975
  pendo.stopGuides = exportPendoCoreOnly(manuallyStopGuides);
30890
30976
  pendo.defaultCssUrl = exportPendoCoreOnly(getDefaultCssUrl());
30891
- pendo.getActiveGuides = getActiveGuides;
30892
- pendo.getActiveGuide = getActiveGuide;
30977
+ pendo.getActiveGuides = function (options = { channel: Channel.DEFAULT }) {
30978
+ return getActiveGuides(options);
30979
+ };
30980
+ pendo.getActiveGuide = function (options = { channel: Channel.DEFAULT }) {
30981
+ return getActiveGuide(options);
30982
+ };
30893
30983
  pendo.guideSeenTimeoutLength = StepTimeoutMonitor.getGuideSeenTimeoutLength();
30894
30984
  pendo.guidesPayload = guidesPayload;
30895
30985
  pendo.areGuidesDisabled = exportPendoCoreOnly(areGuidesDisabled);
30896
30986
  pendo.setGuidesDisabled = exportPendoCoreOnly(setGuidesDisabled);
30987
+ pendo.areGuidesDelayed = exportPendoCoreOnly(areGuidesDelayed);
30897
30988
  pendo.buildNodeFromJSON = BuildingBlockGuides.buildNodeFromJSON;
30898
30989
  pendo.flexElement = exportPendoCoreOnly(BuildingBlockGuides.flexElement);
30899
30990
  pendo.GuideFactory = exportPendoCoreOnly(GuideFactory);
@@ -31680,44 +31771,48 @@ function WalkthroughGuide() {
31680
31771
  // Do not continue a snoozed guide
31681
31772
  if (currentGuide.isGuideSnoozed())
31682
31773
  return null;
31683
- lastSeenObj = lastSeenObj || {};
31684
- for (var j = 0; j < currentGuide.steps.length; j++) {
31685
- if (currentGuide.steps[j].id === lastSeenObj.guideStepId) {
31686
- if (lastSeenObj.state === 'dismissed') {
31687
- // The guide was dismissed
31688
- break;
31689
- }
31690
- else if (lastSeenObj.state === 'active' || lastSeenObj.state === 'snoozed') {
31691
- // This is current.
31692
- nextStep = currentGuide.steps[j];
31693
- break;
31694
- }
31695
- else if (lastSeenObj.state === 'advanced' && lastSeenObj.destinationStepId) {
31696
- nextStep = _.find(currentGuide.steps, function (step) {
31697
- return step.id === lastSeenObj.destinationStepId;
31698
- });
31699
- break;
31700
- }
31701
- else if ((j + 1) < currentGuide.steps.length) {
31702
- // Get the step after that last one seen
31703
- nextStep = currentGuide.steps[j + 1];
31704
- break;
31774
+ if (lastSeenObj != null) {
31775
+ for (var j = 0; j < currentGuide.steps.length; j++) {
31776
+ if (currentGuide.steps[j].id === lastSeenObj.guideStepId) {
31777
+ if (lastSeenObj.state === 'dismissed') {
31778
+ // The guide was dismissed
31779
+ break;
31780
+ }
31781
+ else if (lastSeenObj.state === 'active' || lastSeenObj.state === 'snoozed') {
31782
+ // This is current.
31783
+ nextStep = currentGuide.steps[j];
31784
+ break;
31785
+ }
31786
+ else if (lastSeenObj.state === 'advanced' && lastSeenObj.destinationStepId) {
31787
+ nextStep = _.find(currentGuide.steps, function (step) {
31788
+ return step.id === lastSeenObj.destinationStepId;
31789
+ });
31790
+ break;
31791
+ }
31792
+ else if ((j + 1) < currentGuide.steps.length) {
31793
+ // Get the step after that last one seen
31794
+ nextStep = currentGuide.steps[j + 1];
31795
+ break;
31796
+ }
31705
31797
  }
31706
31798
  }
31707
- }
31708
- if (nextStep) {
31709
- var now = new Date().getTime();
31710
- var lastSeenTime = lastSeenObj.time;
31711
- if (lastSeenTime &&
31712
- ((now - lastSeenTime) > MULTISTEP_CONTINUATION_TIME_LIMIT) &&
31713
- !isOB(currentGuide)) {
31714
- if (!didLogContinuationExpired) {
31715
- log.info('Multi-step continuation has expired', { contexts: ['guides', 'info'] });
31716
- didLogContinuationExpired = true;
31799
+ if (nextStep) {
31800
+ var now = new Date().getTime();
31801
+ var lastSeenTime = lastSeenObj.time;
31802
+ if (lastSeenTime &&
31803
+ ((now - lastSeenTime) > MULTISTEP_CONTINUATION_TIME_LIMIT) &&
31804
+ !isOB(currentGuide)) {
31805
+ if (!didLogContinuationExpired) {
31806
+ log.info('Multi-step continuation has expired', { contexts: ['guides', 'info'] });
31807
+ didLogContinuationExpired = true;
31808
+ }
31809
+ return null;
31717
31810
  }
31718
- return null;
31811
+ return nextStep;
31719
31812
  }
31720
- return nextStep;
31813
+ }
31814
+ else {
31815
+ return findNextStepFromState(currentGuide);
31721
31816
  }
31722
31817
  return null;
31723
31818
  };
@@ -31767,6 +31862,40 @@ function WalkthroughGuide() {
31767
31862
  }
31768
31863
  return this;
31769
31864
  }
31865
+ /*
31866
+ * Finds next step in guide based on seen state/time of steps (instead of pendo.lastGuideStepSeen)
31867
+ */
31868
+ function findNextStepFromState(guide) {
31869
+ const { steps } = guide;
31870
+ if (!steps || !steps.length)
31871
+ return null;
31872
+ // find the step with the most recent lastSeenAt
31873
+ const { currentStep, currentIndex } = _.reduce(steps, (memo, currentStep, currentIndex) => {
31874
+ const { lastSeenAt } = memo.currentStep;
31875
+ if (lastSeenAt == null)
31876
+ return memo;
31877
+ return currentStep.lastSeenAt > lastSeenAt ? { currentStep, currentIndex } : memo;
31878
+ }, { currentStep: steps[0], currentIndex: 0 });
31879
+ if (currentStep.seenState === 'dismissed')
31880
+ return null;
31881
+ if (typeof currentStep.isSnoozed === 'function' && currentStep.isSnoozed()) {
31882
+ return null;
31883
+ }
31884
+ if (currentStep.seenState === 'active' || currentStep.seenState === 'snoozed')
31885
+ return currentStep;
31886
+ if (currentStep.seenState === 'advanced') {
31887
+ const { destinationStepId } = currentStep;
31888
+ if (destinationStepId) {
31889
+ return _.find(steps, function (step) {
31890
+ return step.id === destinationStepId;
31891
+ });
31892
+ }
31893
+ else {
31894
+ return steps[currentIndex + 1] || null;
31895
+ }
31896
+ }
31897
+ return null;
31898
+ }
31770
31899
 
31771
31900
  /*
31772
31901
  * Traps and logs errors that occur while displaying a guide. If the
@@ -33837,7 +33966,7 @@ function updateMasterGuideList(state) {
33837
33966
  })
33838
33967
  .map(GuideFactory)
33839
33968
  .value();
33840
- var mergedGuideList = _.toArray(guidesInThisFrame).concat(guidesInOtherFrames).filter(runGuideProcessors);
33969
+ var mergedGuideList = _.filter(_.toArray(guidesInThisFrame).concat(guidesInOtherFrames), runGuideProcessors);
33841
33970
  sortGuidesByPriority(mergedGuideList);
33842
33971
  initializeResourceCenter(mergedGuideList);
33843
33972
  setActiveGuides(mergedGuideList);
@@ -34425,7 +34554,7 @@ const DebuggerModule = (() => {
34425
34554
  store.commit('debugger/stepEligibilitySet', stepElg);
34426
34555
  }
34427
34556
  function guidesLoadedFn(evt) {
34428
- const autoOrdering = _.map(AutoDisplay.sortAndFilter(getActiveGuides(), pendo$1.autoOrdering), guide => guide.id);
34557
+ const autoOrdering = _.map(AutoDisplay.sortAndFilter(getActiveGuides({ channel: Channel.DEFAULT }), pendo$1.autoOrdering), guide => guide.id);
34429
34558
  store.commit('debugger/autoOrdering', autoOrdering || []);
34430
34559
  store.commit('debugger/excludedGuides', pendo$1.excludedGuides || []);
34431
34560
  store.commit('debugger/throttling', pendo$1.throttling || {});
@@ -37941,14 +38070,15 @@ const OemAccountId = (function () {
37941
38070
 
37942
38071
  var debugging;
37943
38072
  function debuggerExports() {
38073
+ const getActiveDefaultGuides = () => getActiveGuides({ channel: Channel.DEFAULT });
37944
38074
  return {
37945
38075
  store,
37946
38076
  ConfigReader,
37947
38077
  getState() { return JSON.stringify(store.state); },
37948
38078
  getEventCache() { return [].concat(eventCache); },
37949
- getAllGuides() { return [].concat(getActiveGuides()); },
37950
- getAutoGuides() { return AutoDisplay.sortAndFilter(getActiveGuides(), pendo$1.autoOrdering); },
37951
- getBadgeGuides() { return _.filter(getActiveGuides(), isBadge); },
38079
+ getAllGuides() { return [].concat(getActiveDefaultGuides()); },
38080
+ getAutoGuides() { return AutoDisplay.sortAndFilter(getActiveDefaultGuides(), pendo$1.autoOrdering); },
38081
+ getBadgeGuides() { return _.filter(getActiveDefaultGuides(), isBadge); },
37952
38082
  getLauncherGuides() { return []; },
37953
38083
  getEventHistory() { return []; },
37954
38084
  getAllFrames() { return store.getters['frames/allFrames'](); },
@@ -37957,7 +38087,6 @@ function debuggerExports() {
37957
38087
  setActiveGuides,
37958
38088
  getBody: dom.getBody,
37959
38089
  isMobileUserAgent: sniffer.isMobileUserAgent,
37960
- areGuidesDelayed,
37961
38090
  doesElementMatchContainsRules,
37962
38091
  getMetadata,
37963
38092
  isStagingServer,
@@ -38923,6 +39052,7 @@ class SessionManager {
38923
39052
  }
38924
39053
  var SessionManager$1 = new SessionManager();
38925
39054
 
39055
+ const SEGMENT_FLAGS_CACHE = 'segmentFlagsCache';
38926
39056
  class SegmentFlags {
38927
39057
  constructor() {
38928
39058
  this.name = 'SegmentFlags';
@@ -38940,26 +39070,57 @@ class SegmentFlags {
38940
39070
  if (!this.segmentFlagsEnabled)
38941
39071
  return;
38942
39072
  this.mostRecentSegmentsRequest = null;
39073
+ /**
39074
+ * Stores the cached segment flags for the current visitor.
39075
+ * Cleared on identity change and refreshed from server on page load.
39076
+ *
39077
+ * @name _pendo_segmentFlagsCache
39078
+ * @category Cookies/localStorage
39079
+ * @access public
39080
+ * @label SEGMENT_FLAGS_CACHE
39081
+ */
39082
+ PluginAPI.agentStorage.registry.addLocal(SEGMENT_FLAGS_CACHE, {
39083
+ isSecure: true,
39084
+ serializer: JSON.stringify,
39085
+ deserializer: SafeJsonDeserializer
39086
+ });
39087
+ if (shouldPersist()) {
39088
+ try {
39089
+ const cached = PluginAPI.agentStorage.read(SEGMENT_FLAGS_CACHE);
39090
+ if (cached) {
39091
+ this.pendo.segmentFlags = cached;
39092
+ }
39093
+ }
39094
+ catch (e) {
39095
+ // ignore read errors
39096
+ }
39097
+ }
38943
39098
  this.pendo.segmentsPayload = this.pendo._.bind(this.segmentsPayload, this);
38944
- this.handleMetadataChange = this.pendo._.debounce(this.pendo._.bind(this.requestSegmentFlags, this), 50);
38945
39099
  this.handleReadyBound = this.pendo._.bind(this.handleReady, this);
39100
+ this.handleIdentityChangeBound = this.pendo._.bind(this.handleIdentityChange, this);
38946
39101
  this.api.Events.ready.on(this.handleReadyBound);
38947
- this.api.Events.metadata.on(this.handleMetadataChange);
38948
- this.api.Events.identify.on(this.handleMetadataChange);
39102
+ this.api.Events.identify.on(this.handleIdentityChangeBound);
39103
+ this.api.Events.metadata.on(this.handleIdentityChangeBound);
38949
39104
  }
38950
39105
  teardown() {
38951
39106
  if (!this.segmentFlagsEnabled)
38952
39107
  return;
38953
39108
  this.pendo.segmentsPayload = this.pendo._.noop;
38954
- this.handleMetadataChange.cancel();
38955
39109
  this.api.Events.ready.off(this.handleReadyBound);
38956
- this.api.Events.metadata.off(this.handleMetadataChange);
38957
- this.api.Events.identify.off(this.handleMetadataChange);
39110
+ this.api.Events.identify.off(this.handleIdentityChangeBound);
39111
+ this.api.Events.metadata.off(this.handleIdentityChangeBound);
38958
39112
  }
38959
39113
  handleReady() {
38960
39114
  this.ready = true;
38961
39115
  this.requestSegmentFlags();
38962
39116
  }
39117
+ handleIdentityChange(event) {
39118
+ if (this.pendo._.get(event, 'data[0].wasCleared')) {
39119
+ this.api.agentStorage.clear(SEGMENT_FLAGS_CACHE);
39120
+ delete this.pendo.segmentFlags;
39121
+ }
39122
+ this.requestSegmentFlags();
39123
+ }
38963
39124
  requestSegmentFlags() {
38964
39125
  if (!this.ready)
38965
39126
  return;
@@ -39008,10 +39169,23 @@ class SegmentFlags {
39008
39169
  return;
39009
39170
  if (this.pendo._.isString(payload.id) && payload.id !== this.mostRecentSegmentsRequest)
39010
39171
  return;
39172
+ const changed = this.flagsChanged(this.pendo.segmentFlags, payload.segmentFlags);
39011
39173
  this.pendo.segmentFlags = payload.segmentFlags;
39174
+ if (shouldPersist()) {
39175
+ this.api.agentStorage.write(SEGMENT_FLAGS_CACHE, payload.segmentFlags);
39176
+ }
39177
+ if (changed) {
39178
+ this.api.Events.segmentFlagsUpdated.trigger(this.pendo.segmentFlags);
39179
+ }
39012
39180
  this.api.log.info('successfully loaded segment flags');
39013
39181
  this.mostRecentSegmentsRequest = null;
39014
39182
  }
39183
+ flagsChanged(oldFlags = [], newFlags = []) {
39184
+ if (oldFlags.length !== newFlags.length)
39185
+ return true;
39186
+ const intersection = this.pendo._.intersection(oldFlags, newFlags);
39187
+ return intersection.length !== oldFlags.length;
39188
+ }
39015
39189
  scriptLoad(url) {
39016
39190
  this.pendo.loadResource(url, this.pendo._.noop);
39017
39191
  }
@@ -40536,18 +40710,30 @@ function TextCapture() {
40536
40710
  function guideActivity(pendo, event) {
40537
40711
  if (!isEnabled())
40538
40712
  return;
40539
- var eventData = event.data[0];
40713
+ const { _ } = pendo;
40714
+ const eventData = event.data[0];
40540
40715
  if (eventData && eventData.type === 'guideActivity') {
40541
- var activeGuideObj = pendo.getActiveGuide();
40542
- if (!activeGuideObj)
40716
+ const shownSteps = _.reduce(pendo.getActiveGuides({ channel: '*' }), (shown, guide) => {
40717
+ if (guide.isShown()) {
40718
+ return shown.concat(_.filter(guide.steps, (step) => step.isShown()));
40719
+ }
40720
+ return shown;
40721
+ }, []);
40722
+ if (!shownSteps.length)
40543
40723
  return;
40544
- var findDomBlockInDomJson = pendo.BuildingBlocks.BuildingBlockGuides.findDomBlockInDomJson;
40545
- var element = findDomBlockInDomJson(activeGuideObj.step.domJson, function (domJson) {
40546
- return domJson.props && domJson.props.id && domJson.props.id === eventData.props.ui_element_id;
40724
+ const findDomBlockInDomJson = pendo.BuildingBlocks.BuildingBlockGuides.findDomBlockInDomJson;
40725
+ let elementJson;
40726
+ _.find(shownSteps, (step) => {
40727
+ if (!step.domJson)
40728
+ return false;
40729
+ elementJson = findDomBlockInDomJson(step.domJson, function (domJson) {
40730
+ return domJson.props && domJson.props.id && domJson.props.id === eventData.props.ui_element_id;
40731
+ });
40732
+ return elementJson;
40547
40733
  });
40548
- if (!element)
40734
+ if (!elementJson)
40549
40735
  return;
40550
- eventData.props.ui_element_text = element.content;
40736
+ eventData.props.ui_element_text = elementJson.content;
40551
40737
  }
40552
40738
  }
40553
40739
  function isEnabled() {
@@ -40810,6 +40996,30 @@ const MetadataSubstitution = {
40810
40996
  },
40811
40997
  designerListener(pendo) {
40812
40998
  const target = pendo.dom.getBody();
40999
+ if (pendo.designerv2) {
41000
+ pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
41001
+ var _a;
41002
+ if (!document.querySelector(guideMarkdownUtil.containerSelector))
41003
+ return;
41004
+ const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
41005
+ if (!step)
41006
+ return;
41007
+ const placeholderData = findSubstitutableElements(pendo);
41008
+ if (step.buildingBlocks) {
41009
+ findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
41010
+ }
41011
+ if (pendo._.size(placeholderData)) {
41012
+ pendo._.each(placeholderData, function (placeholder) {
41013
+ if (pendo._.isUndefined(placeholder))
41014
+ return;
41015
+ processPlaceholder(placeholder, pendo);
41016
+ });
41017
+ const containerId = `pendo-g-${step.id}`;
41018
+ const context = step.guideElement;
41019
+ updateGuideContainer(containerId, context, pendo);
41020
+ }
41021
+ };
41022
+ }
40813
41023
  const config = {
40814
41024
  attributeFilter: ['data-layout'],
40815
41025
  attributes: true,
@@ -40854,8 +41064,14 @@ function processPlaceholder(placeholder, pendo) {
40854
41064
  const { data, target } = placeholder;
40855
41065
  const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
40856
41066
  while ((match = matchPlaceholder(placeholder, subRegex))) {
40857
- let matched = subRegex.exec(match);
40858
- let mdValue = getSubstituteValue(matched, pendo);
41067
+ const usedArrayPath = Array.isArray(match) && match.length >= 2;
41068
+ const currentStr = target === 'textContent'
41069
+ ? data[target]
41070
+ : decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
41071
+ const matched = usedArrayPath ? match : subRegex.exec(currentStr);
41072
+ if (!matched)
41073
+ continue;
41074
+ const mdValue = getSubstituteValue(matched, pendo);
40859
41075
  substituteMetadataByTarget(data, target, mdValue, matched);
40860
41076
  }
40861
41077
  }
@@ -40864,29 +41080,52 @@ function matchPlaceholder(placeholder, regex) {
40864
41080
  return placeholder.data[placeholder.target].match(regex);
40865
41081
  }
40866
41082
  else {
40867
- return decodeURI(placeholder.data[placeholder.target]).match(regex);
41083
+ const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
41084
+ ? (placeholder.data.getAttribute(placeholder.target) || '')
41085
+ : placeholder.data[placeholder.target];
41086
+ return decodeURI(raw).match(regex);
41087
+ }
41088
+ }
41089
+ function getMetadataValueCaseInsensitive(metadata, type, property) {
41090
+ const kind = metadata && metadata[type];
41091
+ if (!kind || typeof kind !== 'object')
41092
+ return undefined;
41093
+ const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
41094
+ if (direct !== undefined) {
41095
+ return direct;
40868
41096
  }
41097
+ const propLower = property.toLowerCase();
41098
+ const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
41099
+ const value = key !== undefined ? kind[key] : undefined;
41100
+ return value;
40869
41101
  }
40870
41102
  function getSubstituteValue(match, pendo) {
40871
- if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2]))
41103
+ if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
40872
41104
  return;
41105
+ }
40873
41106
  let type = match[1];
40874
41107
  let property = match[2];
40875
41108
  let defaultValue = match[3];
40876
41109
  if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
40877
41110
  return;
40878
41111
  }
40879
- let mdValue = pendo._.get(pendo.getSerializedMetadata(), `${type}.${property}`) || defaultValue || '';
41112
+ const metadata = pendo.getSerializedMetadata();
41113
+ let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
41114
+ if (mdValue === undefined || mdValue === null)
41115
+ mdValue = defaultValue || '';
40880
41116
  return mdValue;
40881
41117
  }
40882
41118
  function substituteMetadataByTarget(data, target, mdValue, matched) {
41119
+ const isElement = data && typeof data.getAttribute === 'function';
41120
+ const current = (target === 'href' || target === 'value') && isElement
41121
+ ? (data.getAttribute(target) || '')
41122
+ : data[target];
40883
41123
  if (target === 'href' || target === 'value') {
40884
- data[target] = decodeURI(data[target])
40885
- .replace(matched[0], window.encodeURI(mdValue));
41124
+ const safeValue = window.encodeURIComponent(String(mdValue === undefined || mdValue === null ? '' : mdValue));
41125
+ data[target] = decodeURI(current).replace(matched[0], safeValue);
40886
41126
  }
40887
41127
  else {
40888
- data[target] = data[target]
40889
- .replace(matched[0], mdValue);
41128
+ data[target] = current.replace(matched[0], mdValue);
40890
41129
  }
40891
41130
  }
40892
41131
  function updateGuideContainer(containerId, context, pendo) {
@@ -53766,6 +54005,7 @@ const RECORDING_CONFIG_TREAT_IFRAME_AS_ROOT = 'recording.treatIframeAsRoot';
53766
54005
  const RECORDING_CONFIG_DISABLE_UNLOAD = 'recording.disableUnload';
53767
54006
  const RESOURCE_CACHING = 'resourceCaching';
53768
54007
  const ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000;
54008
+ const ONE_MINUTE_IN_MILLISECONDS = 60 * 1000;
53769
54009
  const THIRTY_MINUTES = 1000 * 60 * 30;
53770
54010
  const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
53771
54011
  const SESSION_RECORDING_ID = 'pendo_srId';
@@ -53888,6 +54128,7 @@ class SessionRecorder {
53888
54128
  this.transport.onWorkerMessage = bind(this.onWorkerMessage, this);
53889
54129
  this.sendQueue = new SendQueue(bind(this.transport.send, this.transport));
53890
54130
  this.sendQueue.onTimeout = bind(this.sendFailure, this, 'SEND_TIMEOUT');
54131
+ this.errorHandler = this.pendo._.throttle(bind(this.logStopReason, this, 'RRWEB_ERROR'), ONE_MINUTE_IN_MILLISECONDS, { trailing: false });
53891
54132
  this.isNewSession = false;
53892
54133
  this.isCheckingVisitorEligibility = false;
53893
54134
  this.pageLifecycleListeners = [];
@@ -54182,7 +54423,7 @@ class SessionRecorder {
54182
54423
  var config = this.recordingConfig(visitorConfig);
54183
54424
  this._stop = this.record(this.pendo._.extend({
54184
54425
  emit: bind(this.emit, this),
54185
- errorHandler: bind(this.errorHandler, this)
54426
+ errorHandler: this.errorHandler
54186
54427
  }, config));
54187
54428
  this._refreshIds();
54188
54429
  this.onRecordingStart();
@@ -54294,9 +54535,6 @@ class SessionRecorder {
54294
54535
  return null;
54295
54536
  }
54296
54537
  }
54297
- errorHandler(error) {
54298
- this.logStopReason('RRWEB_ERROR', error);
54299
- }
54300
54538
  /**
54301
54539
  * Handle new rrweb events coming in. This will also make sure that we are properly sending a "keyframe"
54302
54540
  * as the BE expects it. A "keyframe" should consist of only the events needed to start a recording. This includes
@@ -54604,7 +54842,7 @@ class SessionRecorder {
54604
54842
  recordingPayload: [],
54605
54843
  sequence: 0,
54606
54844
  recordingPayloadCount: 0,
54607
- props: Object.assign({ reason }, (error && { error }))
54845
+ props: Object.assign({ reason }, (error && { error: error instanceof Error ? error === null || error === void 0 ? void 0 : error.message : error }))
54608
54846
  }, tracer);
54609
54847
  var jzb = this.pendo.compress(payload);
54610
54848
  var url = this.buildRequestUrl(`${this.pendo.HOST}/data/rec/${this.pendo.apiKey}`, {
@@ -57027,7 +57265,7 @@ var ConfigReader = (function () {
57027
57265
  * @default false
57028
57266
  * @type {boolean}
57029
57267
  */
57030
- addOption('guides.delay', [SNIPPET_SRC], undefined, undefined, ['delayGuides']);
57268
+ addOption('guides.delay', [SNIPPET_SRC], false, undefined, ['delayGuides']);
57031
57269
  /**
57032
57270
  * Completely disables guides (this option has been moved from `disableGuides`).
57033
57271
  * Alias: `disableGuides`
@@ -57038,7 +57276,7 @@ var ConfigReader = (function () {
57038
57276
  * @default false
57039
57277
  * @type {boolean}
57040
57278
  */
57041
- addOption('guides.disabled', [SNIPPET_SRC], undefined, undefined, ['disableGuides']);
57279
+ addOption('guides.disabled', [SNIPPET_SRC], false, undefined, ['disableGuides']);
57042
57280
  /**
57043
57281
  * If 'true', guides with slow selectors will be removed from guide display processing.
57044
57282
  * This will improve application performance, but slow guides will not be shown to users.
@@ -58299,6 +58537,7 @@ function NetworkCapture() {
58299
58537
  let responseBodyCb;
58300
58538
  let pendoDevlogBaseUrl;
58301
58539
  let isCapturingNetworkLogs = false;
58540
+ let excludeRequestUrls = [];
58302
58541
  const CAPTURE_NETWORK_CONFIG = 'captureNetworkRequests';
58303
58542
  const NETWORK_SUB_TYPE = 'network';
58304
58543
  const NETWORK_LOGS_CONFIG = 'networkLogs';
@@ -58306,6 +58545,7 @@ function NetworkCapture() {
58306
58545
  const NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS = 'networkLogs.allowedResponseHeaders';
58307
58546
  const NETWORK_LOGS_CONFIG_CAPTURE_REQUEST_BODY = 'networkLogs.captureRequestBody';
58308
58547
  const NETWORK_LOGS_CONFIG_CAPTURE_RESPONSE_BODY = 'networkLogs.captureResponseBody';
58548
+ const NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS = 'networkLogs.excludeRequestUrls';
58309
58549
  const allowedRequestHeaders = {
58310
58550
  'content-type': true, 'content-length': true, 'accept': true, 'accept-language': true
58311
58551
  };
@@ -58336,6 +58576,8 @@ function NetworkCapture() {
58336
58576
  processBody,
58337
58577
  processRequestBody,
58338
58578
  processResponseBody,
58579
+ buildExcludeRequestUrls,
58580
+ isUrlExcluded,
58339
58581
  get isCapturingNetworkLogs() {
58340
58582
  return isCapturingNetworkLogs;
58341
58583
  },
@@ -58362,6 +58604,9 @@ function NetworkCapture() {
58362
58604
  },
58363
58605
  get responseBodyCb() {
58364
58606
  return responseBodyCb;
58607
+ },
58608
+ get excludeRequestUrls() {
58609
+ return excludeRequestUrls;
58365
58610
  }
58366
58611
  };
58367
58612
  function initialize(pendo, PluginAPI) {
@@ -58379,6 +58624,7 @@ function NetworkCapture() {
58379
58624
  processHeaderConfig(NETWORK_LOGS_CONFIG_ALLOWED_REQUEST_HEADERS, allowedRequestHeaders);
58380
58625
  processHeaderConfig(NETWORK_LOGS_CONFIG_ALLOWED_RESPONSE_HEADERS, allowedResponseHeaders);
58381
58626
  setupBodyCallbacks();
58627
+ buildExcludeRequestUrls();
58382
58628
  sendInterval = setInterval(() => {
58383
58629
  if (!sendQueue.failed()) {
58384
58630
  send();
@@ -58439,13 +58685,26 @@ function NetworkCapture() {
58439
58685
  * @type {function}
58440
58686
  */
58441
58687
  ConfigReader.addOption(NETWORK_LOGS_CONFIG_CAPTURE_RESPONSE_BODY, [ConfigReader.sources.SNIPPET_SRC], undefined);
58688
+ /**
58689
+ * A list of request URL patterns to exclude from network capture.
58690
+ * String patterns must match the full URL, including query parameters and fragments.
58691
+ * Use RegExp for flexible or partial matching.
58692
+ *
58693
+ * Example: `['https://example.com', new RegExp('https://test\\.com\\/.*'), /.*\\.domain\\.com/]`
58694
+ * @access public
58695
+ * @category Config/Network Logs
58696
+ * @name networkLogs.excludeRequestUrls
58697
+ * @default []
58698
+ * @type {Array<string|RegExp>}
58699
+ */
58700
+ ConfigReader.addOption(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS, [ConfigReader.sources.SNIPPET_SRC], []);
58442
58701
  }
58443
58702
  function processHeaderConfig(configHeaderName, targetHeaders) {
58444
58703
  const configHeaders = pluginAPI.ConfigReader.get(configHeaderName);
58445
58704
  if (!configHeaders || configHeaders.length === 0)
58446
58705
  return;
58447
58706
  globalPendo._.each(configHeaders, (header) => {
58448
- if (!header || typeof header !== 'string')
58707
+ if (!header || !globalPendo._.isString(header))
58449
58708
  return;
58450
58709
  targetHeaders[header.toLowerCase()] = true;
58451
58710
  });
@@ -58461,6 +58720,28 @@ function NetworkCapture() {
58461
58720
  responseBodyCb = config.captureResponseBody;
58462
58721
  }
58463
58722
  }
58723
+ function buildExcludeRequestUrls() {
58724
+ const requestUrls = pluginAPI.ConfigReader.get(NETWORK_LOGS_CONFIG_EXCLUDE_REQUEST_URLS);
58725
+ if (!requestUrls || requestUrls.length === 0)
58726
+ return;
58727
+ globalPendo._.each(requestUrls, (requestUrl) => {
58728
+ const processedRequestUrl = processUrlPattern(requestUrl);
58729
+ if (!processedRequestUrl)
58730
+ return;
58731
+ excludeRequestUrls.push(processedRequestUrl);
58732
+ });
58733
+ }
58734
+ function processUrlPattern(url) {
58735
+ if (!url)
58736
+ return;
58737
+ const isRegex = globalPendo._.isRegExp(url);
58738
+ if (!globalPendo._.isString(url) && !isRegex)
58739
+ return;
58740
+ if (isRegex)
58741
+ return url;
58742
+ const escapedUrl = pluginAPI.util.escapeRegExp(url);
58743
+ return new RegExp(`^${escapedUrl}$`);
58744
+ }
58464
58745
  function onPtmPaused() {
58465
58746
  isPtmPaused = true;
58466
58747
  }
@@ -58513,8 +58794,17 @@ function NetworkCapture() {
58513
58794
  pluginAPI.Events['recording:unpaused'].off(recordingStarted);
58514
58795
  pluginAPI.Events['recording:paused'].off(recordingStopped);
58515
58796
  }
58797
+ function isUrlExcluded(url) {
58798
+ if (!url || !globalPendo._.isString(url))
58799
+ return false;
58800
+ if (excludeRequestUrls.length === 0)
58801
+ return false;
58802
+ return globalPendo._.some(excludeRequestUrls, (excludeRequestUrl) => {
58803
+ return excludeRequestUrl.test(url);
58804
+ });
58805
+ }
58516
58806
  function handleRequest(request) {
58517
- if (!isCapturingNetworkLogs)
58807
+ if (!isCapturingNetworkLogs || !request || isUrlExcluded(request.url))
58518
58808
  return;
58519
58809
  requestMap[request.requestId] = request;
58520
58810
  }
@@ -58571,7 +58861,7 @@ function NetworkCapture() {
58571
58861
  }, []);
58572
58862
  }
58573
58863
  function processBody(body, contentType) {
58574
- if (!body || typeof body !== 'string')
58864
+ if (!body || !globalPendo._.isString(body))
58575
58865
  return '';
58576
58866
  const processedBody = maskSensitiveFields({ string: body, contentType, _: globalPendo._ });
58577
58867
  return truncate(processedBody, true);