@pendo/agent 2.296.0 → 2.297.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.
package/dist/dom.esm.js CHANGED
@@ -6164,6 +6164,7 @@ var ConfigReader = (function () {
6164
6164
  */
6165
6165
  addOption('additionalApiKeys', [PENDO_CONFIG_SRC, SNIPPET_SRC]);
6166
6166
  addOption('allowedOriginServers');
6167
+ addOption('allowedOriginServerHashes');
6167
6168
  addOption('allowMixedApiKeyFrames', [SNIPPET_SRC, PENDO_CONFIG_SRC], true);
6168
6169
  /**
6169
6170
  * A function that returns either an array of strings or an object to decorate the url for events.
@@ -7313,7 +7314,7 @@ function getScreenPosition(element) {
7313
7314
  };
7314
7315
  }
7315
7316
 
7316
- var VERSION = '2.296.0_';
7317
+ var VERSION = '2.297.0_';
7317
7318
 
7318
7319
  var decodeURIComponent = _.isFunction(window.decodeURIComponent) ? window.decodeURIComponent : _.identity;
7319
7320
 
@@ -488,51 +488,62 @@ function getAlternateAgentUrl(config, useStaging, debuggingEnabled) {
488
488
  }
489
489
  return agentUrl;
490
490
  }
491
- function isStagingServer(config, location) {
492
- if (!config) {
493
- config = getPendoConfig();
494
- }
495
- if (isStagingEnvironment(config)) {
496
- return true;
497
- }
498
- if (!location) {
499
- location = window.location;
500
- }
501
- // trying to not calculate Hash if not needed.
502
- if (hasHashedStagingServers(config)) {
503
- var hostHash = getHash(location.host);
504
- for (var j = 0, jj = config[STAGING_SERVER_HASHES].length; j < jj; ++j) {
505
- var h = config[STAGING_SERVER_HASHES][j];
506
- if (h === hostHash) {
491
+ function urlMatchesPatterns(url, patterns = [], hashes = []) {
492
+ if (!url)
493
+ return false;
494
+ if (hashes.length > 0) {
495
+ const urlHash = getHash(url);
496
+ for (let i = 0, x = hashes.length; i < x; ++i) {
497
+ if (hashes[i] === urlHash) {
507
498
  return true;
508
499
  }
509
500
  }
510
501
  }
511
- if (hasStagingServerConfig(config)) {
512
- for (var i = 0, ii = config.stagingServers.length; i < ii; ++i) {
513
- var stagingServer = config.stagingServers[i];
514
- if (typeof stagingServer === 'string') {
515
- stagingServer = new RegExp('^' + stagingServer + '$');
502
+ if (patterns.length > 0) {
503
+ for (let j = 0, y = patterns.length; j < y; ++j) {
504
+ let pattern = patterns[j];
505
+ if (typeof pattern === 'object' && pattern.value) {
506
+ if (pattern.regexp) {
507
+ if (pattern.value.startsWith('/') && pattern.value.endsWith('/')) {
508
+ pattern.value = pattern.value.substring(1, pattern.value.length - 1);
509
+ }
510
+ pattern = new RegExp(pattern.value);
511
+ }
512
+ else {
513
+ pattern = pattern.value;
514
+ }
516
515
  }
517
- if (stagingServer instanceof RegExp && stagingServer.test(location.host)) {
516
+ if (typeof pattern === 'string') {
517
+ pattern = new RegExp('^' + pattern + '$');
518
+ }
519
+ if (pattern instanceof RegExp && pattern.test(url)) {
518
520
  return true;
519
521
  }
520
522
  }
521
523
  }
522
524
  return false;
523
525
  }
526
+ function isStagingServer(config, location) {
527
+ if (!config) {
528
+ config = getPendoConfig();
529
+ }
530
+ if (!config) {
531
+ return false;
532
+ }
533
+ if (isStagingEnvironment(config)) {
534
+ return true;
535
+ }
536
+ if (!location) {
537
+ location = window.location;
538
+ }
539
+ return urlMatchesPatterns(location.host, config.stagingServers, config[STAGING_SERVER_HASHES]);
540
+ }
524
541
  function getHash(str) {
525
542
  return b64.uint8ToBase64(sha1
526
543
  .create()
527
544
  .update(str)
528
545
  .digest());
529
546
  }
530
- function hasHashedStagingServers(config) {
531
- return config && config.stagingAgentUrl && config[STAGING_SERVER_HASHES];
532
- }
533
- function hasStagingServerConfig(config) {
534
- return config && config.stagingAgentUrl && config.stagingServers;
535
- }
536
547
  var METHODS_TO_CAPTURE = [
537
548
  'initialize',
538
549
  'identify',
@@ -2790,6 +2801,7 @@ var ConfigReader = (function () {
2790
2801
  */
2791
2802
  addOption('additionalApiKeys', [PENDO_CONFIG_SRC, SNIPPET_SRC]);
2792
2803
  addOption('allowedOriginServers');
2804
+ addOption('allowedOriginServerHashes');
2793
2805
  addOption('allowMixedApiKeyFrames', [SNIPPET_SRC, PENDO_CONFIG_SRC], true);
2794
2806
  /**
2795
2807
  * A function that returns either an array of strings or an object to decorate the url for events.
@@ -3892,8 +3904,8 @@ let SERVER = '';
3892
3904
  let ASSET_HOST = '';
3893
3905
  let ASSET_PATH = '';
3894
3906
  let DESIGNER_SERVER = '';
3895
- let VERSION = '2.296.0_';
3896
- let PACKAGE_VERSION = '2.296.0';
3907
+ let VERSION = '2.297.0_';
3908
+ let PACKAGE_VERSION = '2.297.0';
3897
3909
  let LOADER = 'xhr';
3898
3910
  /* eslint-enable agent-eslint-rules/no-gulp-env-references */
3899
3911
  /**
@@ -3928,9 +3940,6 @@ function isProdAgent() {
3928
3940
  function isRCAgent() {
3929
3941
  return ENV.indexOf('rc') !== -1;
3930
3942
  }
3931
- function isBetaAgent(config) {
3932
- return !isProdAgent() || isStagingServer(config);
3933
- }
3934
3943
 
3935
3944
  var rtrim = /^\s+|\s+$/g;
3936
3945
  var trim = String.prototype.trim;
@@ -9533,12 +9542,15 @@ function exportDataHost(pendo) {
9533
9542
  pendo.HOST = HOST;
9534
9543
  }
9535
9544
  function getAssetHost() {
9545
+ return ConfigReader.get('assetHost') || getContentHost();
9546
+ }
9547
+ function getContentHost() {
9536
9548
  var protocol = 'https://';
9537
- var assetHost = ConfigReader.get('contentHost') || ConfigReader.get('assetHost') || ASSET_HOST;
9538
- if (assetHost && assetHost.indexOf('://') === -1) {
9539
- assetHost = protocol + assetHost;
9549
+ var contentHost = ConfigReader.get('contentHost') || ASSET_HOST;
9550
+ if (contentHost && contentHost.indexOf('://') === -1) {
9551
+ contentHost = protocol + contentHost;
9540
9552
  }
9541
- return assetHost;
9553
+ return contentHost;
9542
9554
  }
9543
9555
  function isLocalAgent(assetHost) {
9544
9556
  return assetHost.indexOf('localhost') >= 0 || assetHost.indexOf('local.pendo.io') >= 0;
@@ -9779,11 +9791,9 @@ function writeErrorPOST(msg) {
9779
9791
  * @returns void
9780
9792
  */
9781
9793
  function writeMetricsPOST(payload) {
9782
- if (_.size(payload).length < 1)
9783
- return;
9784
9794
  try {
9785
9795
  const url = `${HOST}/data/agentmetrics?apiKey=${pendo$1.apiKey}`;
9786
- log.debug(`Will send ${payload} to ${url} using ${fetchKeepalive.supported() ? 'fetch' : 'xhr'} once the endpoint exists`);
9796
+ log.debug(`Will send ${JSON.stringify(payload)} to ${url} using ${fetchKeepalive.supported() ? 'fetch' : 'xhr'} once the endpoint exists`);
9787
9797
  if (fetchKeepalive.supported()) {
9788
9798
  // fetch(url, {
9789
9799
  // method: 'POST',
@@ -11435,11 +11445,13 @@ function isTrustedOrigin(host) {
11435
11445
  // for CNAME, trust the top-level origin
11436
11446
  if (host === window.location.origin)
11437
11447
  return true;
11438
- // Trust the data host
11448
+ // Trust the configured hosts
11439
11449
  if (host === getDataHost())
11440
11450
  return true;
11441
11451
  if (host === getAssetHost())
11442
11452
  return true;
11453
+ if (host === getContentHost())
11454
+ return true;
11443
11455
  // Domains that Pendo owns, will be swapped in by build patches
11444
11456
  const patterns = [
11445
11457
  /^https:\/\/(adopt\.)?((us1)\.)?(app|via|adopt|cdn)(\.(au|eu|gov|hsbc|jpn))?\.pendo\.io$/,
@@ -11458,12 +11470,20 @@ function isTrustedOrigin(host) {
11458
11470
  if (host === fullHostname)
11459
11471
  return true;
11460
11472
  }
11461
- if (_.contains(ConfigReader.get('allowedOriginServers', []), host))
11473
+ if (urlMatchesPatterns(host, ConfigReader.get('allowedOriginServers', []), ConfigReader.get('allowedOriginServerHashes', [])))
11462
11474
  return true;
11463
11475
  return _.any(patterns, function (pattern) {
11464
11476
  return pattern.test(host);
11465
11477
  });
11466
11478
  }
11479
+ function hasAllowedOriginServers() {
11480
+ const allowedOriginServers = ConfigReader.get('allowedOriginServers', []);
11481
+ return allowedOriginServers && allowedOriginServers.length > 0;
11482
+ }
11483
+ function hasHashedAllowedOriginServers() {
11484
+ const allowedOriginServerHashes = ConfigReader.get('allowedOriginServerHashes', []);
11485
+ return allowedOriginServerHashes && allowedOriginServerHashes.length > 0;
11486
+ }
11467
11487
 
11468
11488
  function parseUrl(url) {
11469
11489
  if (!_.isString(url))
@@ -11497,9 +11517,9 @@ function addIntegrityAttribute(element, url) {
11497
11517
  }
11498
11518
  }
11499
11519
  var trustedOriginForLoadResource = function (origin) {
11500
- var noAllowedOriginServers = ConfigReader.get('allowedOriginServers', []).length === 0;
11520
+ var noAllowedOriginServers = !hasAllowedOriginServers() && !hasHashedAllowedOriginServers();
11501
11521
  var isAdoptPartner = treatAsAdoptPartner();
11502
- if (noAllowedOriginServers || isAdoptPartner || !isBetaAgent(getPendoConfig())) {
11522
+ if (noAllowedOriginServers || isAdoptPartner) {
11503
11523
  return true;
11504
11524
  }
11505
11525
  return isTrustedOrigin(origin);
@@ -12261,13 +12281,19 @@ class PerformanceMonitor {
12261
12281
  });
12262
12282
  }
12263
12283
  send() {
12264
- const payload = _.reduce(_.keys(Metrics), (acc, name) => {
12284
+ const metrics = _.reduce(_.keys(Metrics), (acc, name) => {
12265
12285
  const entries = performance.getEntriesByName(name);
12266
- const result = Metrics[name].instrument(entries);
12267
- acc[name] = result;
12268
- }, {});
12286
+ const value = Metrics[name].instrument(entries);
12287
+ acc.push({ name, value });
12288
+ return acc;
12289
+ }, []);
12290
+ const payload = _.filter(metrics, (metric) => {
12291
+ return metric.value > 0;
12292
+ });
12269
12293
  this._clearMarksAndMeasures();
12270
- writeMetricsPOST(payload);
12294
+ if (_.size(payload)) {
12295
+ writeMetricsPOST(payload);
12296
+ }
12271
12297
  }
12272
12298
  _checkPerformanceApi() {
12273
12299
  return ConfigReader.get('performanceMetricsEnabled') &&
@@ -12300,11 +12326,14 @@ class PerformanceMonitor {
12300
12326
  }
12301
12327
  }
12302
12328
  _clearMarksAndMeasures() {
12303
- _.each(this.marks.entries, (name) => {
12329
+ // TODO: fix custom lint rule to handle sets
12330
+ // eslint-disable-next-line agent-eslint-rules/no-array-foreach
12331
+ this.marks.forEach(name => {
12304
12332
  performance.clearMarks(name);
12305
12333
  });
12306
12334
  this.marks.clear();
12307
- _.each(this.measures.entries, (name) => {
12335
+ // eslint-disable-next-line agent-eslint-rules/no-array-foreach
12336
+ this.measures.forEach(name => {
12308
12337
  performance.clearMeasures(name);
12309
12338
  });
12310
12339
  this.measures.clear();
@@ -13112,8 +13141,10 @@ var extractAttribute = function (element, attrName, type) {
13112
13141
  var tag = element.nodeName.toLowerCase();
13113
13142
  if ((tag == 'img' && attrName == 'src') ||
13114
13143
  (tag == 'a' && attrName == 'href')) {
13115
- var src = element.getAttribute(attrName);
13116
- return sanitizeUrl(handleEmbeddedData(src));
13144
+ if (useLegacyGetHref()) {
13145
+ var src = element.getAttribute(attrName);
13146
+ return sanitizeUrl(handleEmbeddedData(src));
13147
+ }
13117
13148
  }
13118
13149
  var attr = getAttributeValue(element, attrName);
13119
13150
  if (type && typeof attr !== type)
@@ -16301,8 +16332,19 @@ var BuildingBlockTooltips = (function () {
16301
16332
  offset: TOOLTIP_CONSTANTS.DEFAULT_CARET_OFFSET,
16302
16333
  borderWidth: 0
16303
16334
  };
16304
- if (containerDomJson.props.style.border) {
16305
- var guideBorderArray = containerDomJson.props.style.border.split(' ');
16335
+ // Check for border in dark mode properties first, then fall back to regular properties
16336
+ var borderSource = null;
16337
+ var regularBorder = _.get(containerDomJson, 'props.style.border');
16338
+ var darkModeBorder = _.get(containerDomJson, 'darkModeProps.style.border');
16339
+ // Use dark mode properties if step.isDarkMode is true and dark mode properties exist
16340
+ if (step && step.isDarkMode && darkModeBorder) {
16341
+ borderSource = darkModeBorder;
16342
+ }
16343
+ else if (regularBorder) {
16344
+ borderSource = regularBorder;
16345
+ }
16346
+ if (borderSource) {
16347
+ var guideBorderArray = borderSource.split(' ');
16306
16348
  caretDimensions.borderColor = guideBorderArray[2];
16307
16349
  caretDimensions.borderWidth = parseInt(guideBorderArray[0], 10) || 0;
16308
16350
  }
@@ -21968,6 +22010,7 @@ function startPreviewMode(window) {
21968
22010
  if (isInDesignerPreviewMode()) {
21969
22011
  const pendoConfig = getPendoConfig();
21970
22012
  pendoConfig.allowedOriginServers = [];
22013
+ pendoConfig.allowedOriginServerHashes = [];
21971
22014
  }
21972
22015
  Events.startPreview.trigger();
21973
22016
  Events.leaderChanged.on(function (e) {
@@ -24928,7 +24971,7 @@ var _addCredits = function (elem) {
24928
24971
  return;
24929
24972
  }
24930
24973
  var img = document.createElement('img');
24931
- img.setAttribute('src', getAssetHost() + '/img/tiny-logo.png');
24974
+ img.setAttribute('src', getContentHost() + '/img/tiny-logo.png');
24932
24975
  var credits = dom(document.createElement('div')).addClass('_pendo-credits_')
24933
24976
  .css({
24934
24977
  bottom: 0,
@@ -26383,6 +26426,9 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
26383
26426
  };
26384
26427
 
26385
26428
  const PENDO_HEADERS_KEY = '_pendoHeaders';
26429
+ function getTransformedUrl(url) {
26430
+ return store.getters['networkUrl/getTransformedUrl']()(url);
26431
+ }
26386
26432
  class NetworkRequestIntercept {
26387
26433
  entriesToObject(entries) {
26388
26434
  const obj = {};
@@ -26475,6 +26521,7 @@ class NetworkRequestIntercept {
26475
26521
  window.fetch = function (...args) {
26476
26522
  return __awaiter(this, void 0, void 0, function* () {
26477
26523
  const [url, config = {}] = args;
26524
+ const transformedUrl = getTransformedUrl(url);
26478
26525
  const method = config.method || 'GET';
26479
26526
  const requestId = networkInterceptor.generateRequestId();
26480
26527
  // Capture request data
@@ -26483,7 +26530,7 @@ class NetworkRequestIntercept {
26483
26530
  const body = networkInterceptor.safelySerializeBody(config.body);
26484
26531
  _.each(networkInterceptor.callbackFns, ({ request }) => {
26485
26532
  if (_.isFunction(request))
26486
- request({ requestId, method, url, body, headers });
26533
+ request({ requestId, method, url: transformedUrl, body, headers });
26487
26534
  });
26488
26535
  }
26489
26536
  catch (e) {
@@ -26510,7 +26557,7 @@ class NetworkRequestIntercept {
26510
26557
  statusText,
26511
26558
  body: responseBody,
26512
26559
  headers,
26513
- url,
26560
+ url: transformedUrl,
26514
26561
  method
26515
26562
  });
26516
26563
  }
@@ -26534,7 +26581,7 @@ class NetworkRequestIntercept {
26534
26581
  statusText: 'Network Error',
26535
26582
  headers: {},
26536
26583
  body: null,
26537
- url,
26584
+ url: transformedUrl,
26538
26585
  method,
26539
26586
  error: error.message
26540
26587
  });
@@ -26556,8 +26603,9 @@ class NetworkRequestIntercept {
26556
26603
  return networkInterceptor._originalSetRequestHeader.apply(this, arguments);
26557
26604
  };
26558
26605
  XMLHttpRequest.prototype.open = function (method, url) {
26606
+ const transformedUrl = getTransformedUrl(url);
26559
26607
  this._method = method;
26560
- this._url = url;
26608
+ this._url = transformedUrl;
26561
26609
  this._requestId = networkInterceptor.generateRequestId();
26562
26610
  return networkInterceptor._originalXHROpen.apply(this, arguments);
26563
26611
  };
@@ -29656,8 +29704,21 @@ var attrActionEnum = {
29656
29704
  href: ['Replace', 'ForceSecure'],
29657
29705
  protocol: ['ForceSecure']
29658
29706
  };
29659
- const TARGETS = ['location', 'attribute', 'both'];
29707
+ const TARGETS = ['location', 'attribute', 'both', 'network', 'all'];
29660
29708
  const DEFAULT_TARGET = 'location';
29709
+ function normalizeTarget(target) {
29710
+ if (_.isArray(target)) {
29711
+ // Filter out invalid targets and fallback to DEFAULT_TARGET if empty
29712
+ const validTargets = _.filter(target, function (t) {
29713
+ return TARGETS.indexOf(t) >= 0;
29714
+ });
29715
+ return validTargets.length > 0 ? validTargets : [DEFAULT_TARGET];
29716
+ }
29717
+ if (TARGETS.indexOf(target) >= 0) {
29718
+ return target;
29719
+ }
29720
+ return DEFAULT_TARGET;
29721
+ }
29661
29722
  function UrlTransform(attr, action, data, target) {
29662
29723
  if (_.isObject(attr)) {
29663
29724
  action = attr.action;
@@ -29673,14 +29734,11 @@ function UrlTransform(attr, action, data, target) {
29673
29734
  var validActions = attrActionEnum[attr].join(', ');
29674
29735
  throw new Error('Invalid transform action: "' + action + '" for attribute "' + attr + '". Valid actions for "' + attr + '" are: ' + validActions + '. Example: {attr: "' + attr + '", action: "' + attrActionEnum[attr][0] + '", data: ...}');
29675
29736
  }
29676
- // validate 'target'
29677
- if (TARGETS.indexOf(target) < 0) {
29678
- target = DEFAULT_TARGET;
29679
- }
29680
29737
  this.attr = attr;
29681
29738
  this.action = action;
29682
29739
  this.data = data;
29683
- this.target = target || DEFAULT_TARGET;
29740
+ // validate and normalize target
29741
+ this.target = normalizeTarget(target);
29684
29742
  }
29685
29743
  UrlTransform.prototype.applyTo = function (url) {
29686
29744
  var actionImpls = {
@@ -29878,12 +29936,16 @@ var LocationModule = (function (global) {
29878
29936
  addTransforms(context, transforms) {
29879
29937
  _.each(transforms, function (f) {
29880
29938
  const t = UrlTransform.fromJSON(f);
29881
- if (t.target === 'location' || t.target === 'both') {
29939
+ const targets = _.isArray(t.target) ? t.target : [t.target];
29940
+ if (_.contains(targets, 'location') || _.contains(targets, 'both') || _.contains(targets, 'all')) {
29882
29941
  context.commit('addTransform', t);
29883
29942
  }
29884
- if (t.target === 'attribute' || t.target === 'both') {
29943
+ if (_.contains(targets, 'attribute') || _.contains(targets, 'both') || _.contains(targets, 'all')) {
29885
29944
  store.dispatch('nodeAttr/addAttrTransform', t);
29886
29945
  }
29946
+ if (_.contains(targets, 'network') || _.contains(targets, 'all')) {
29947
+ store.dispatch('networkUrl/addNetworkTransform', t);
29948
+ }
29887
29949
  });
29888
29950
  },
29889
29951
  addInternalTransforms(context, transforms) {
@@ -29922,6 +29984,7 @@ var LocationModule = (function (global) {
29922
29984
  clearTransforms(state) {
29923
29985
  state.transforms = [];
29924
29986
  store.commit('nodeAttr/clearURLTransforms');
29987
+ store.commit('networkUrl/clearURLTransforms');
29925
29988
  },
29926
29989
  clearInternalTransforms(state) {
29927
29990
  state.internalTransforms = [];
@@ -33795,6 +33858,7 @@ const DebuggerModule = (() => {
33795
33858
  };
33796
33859
  })();
33797
33860
 
33861
+ const URL_ATTR_NAMES = ['src', 'href'];
33798
33862
  const NodeAttrModule = (function (global) {
33799
33863
  const state = {
33800
33864
  transforms: []
@@ -33828,11 +33892,14 @@ const NodeAttrModule = (function (global) {
33828
33892
  };
33829
33893
  const getters = {
33830
33894
  getAttribute(state) {
33831
- return function (element, attrName) {
33895
+ return function (element, attrName = '') {
33832
33896
  let attrValue = element.getAttribute ? element.getAttribute(attrName) : element[attrName];
33833
33897
  if (_.size(state.transforms) < 1) {
33834
33898
  return attrValue;
33835
33899
  }
33900
+ if (URL_ATTR_NAMES.indexOf(attrName.toLowerCase()) === -1) {
33901
+ return attrValue;
33902
+ }
33836
33903
  try {
33837
33904
  let url = resolveAttrValueAsURL(attrValue);
33838
33905
  url = _.reduce([
@@ -33857,6 +33924,54 @@ const NodeAttrModule = (function (global) {
33857
33924
  };
33858
33925
  })();
33859
33926
 
33927
+ const NetworkUrlModule = (function (global) {
33928
+ const state = {
33929
+ transforms: []
33930
+ };
33931
+ const actions = {
33932
+ addNetworkTransform(context, urlTransform) {
33933
+ context.commit('addTransform', urlTransform);
33934
+ }
33935
+ };
33936
+ const mutations = {
33937
+ addTransform(state, transform) {
33938
+ state.transforms.push(transform);
33939
+ },
33940
+ clearURLTransforms(state) {
33941
+ state.transforms = [];
33942
+ }
33943
+ };
33944
+ const applyTransforms = (transforms, url) => {
33945
+ return _.reduce(transforms, function (tUrl, f) {
33946
+ return f.applyTo(tUrl);
33947
+ }, url);
33948
+ };
33949
+ const getters = {
33950
+ getTransformedUrl(state) {
33951
+ return function (url) {
33952
+ if (_.size(state.transforms) < 1) {
33953
+ return url;
33954
+ }
33955
+ try {
33956
+ let urlObj = url instanceof URL ? url : new URL(url, window.location.origin);
33957
+ urlObj = applyTransforms(state.transforms, urlObj);
33958
+ return urlObj.href;
33959
+ }
33960
+ catch (e) {
33961
+ log.critical(e);
33962
+ return url;
33963
+ }
33964
+ };
33965
+ }
33966
+ };
33967
+ return {
33968
+ state,
33969
+ actions,
33970
+ mutations,
33971
+ getters
33972
+ };
33973
+ })();
33974
+
33860
33975
  function registerModules(store) {
33861
33976
  store.registerModule('debugger', DebuggerModule);
33862
33977
  store.registerModule('errorLog', ErrorLogModule);
@@ -33868,6 +33983,7 @@ function registerModules(store) {
33868
33983
  store.registerModule('metadata', MetadataModule);
33869
33984
  store.registerModule('preview', PreviewModule);
33870
33985
  store.registerModule('nodeAttr', NodeAttrModule);
33986
+ store.registerModule('networkUrl', NetworkUrlModule);
33871
33987
  }
33872
33988
 
33873
33989
  const IFrameMonitor = (function () {
@@ -36597,7 +36713,7 @@ var Branding = (function () {
36597
36713
  link.href = 'https://www.pendo.io/pendo-free/nps?utm_source=pendo_app&utm_medium=branded-nps&utm_campaign=free-branded-nps';
36598
36714
  link.target = '_blank';
36599
36715
  var img = document.createElement('img');
36600
- img.setAttribute('src', getAssetHost() + '/img/nps-branding.png');
36716
+ img.setAttribute('src', getContentHost() + '/img/nps-branding.png');
36601
36717
  link.appendChild(img);
36602
36718
  link.style.display = 'inline-block';
36603
36719
  var div = document.createElement('div');
@@ -36845,6 +36961,7 @@ const EventProperties = (function () {
36845
36961
  let cepFailureCount;
36846
36962
  let collectionThreshold;
36847
36963
  const MAX_CONSECUTIVE_FAILURES = 3;
36964
+ const EVENT_PROPERTY_TIMEOUT = 'eventPropertyTimeout';
36848
36965
  const collectClickEventProperties = makeSafe(createClickEventProperties);
36849
36966
  const collectPageEventProperties = makeSafe(createPageEventProperties);
36850
36967
  return {
@@ -36864,20 +36981,37 @@ const EventProperties = (function () {
36864
36981
  pageEventPropertiesTimeout = false;
36865
36982
  pepFailureCount = 0;
36866
36983
  cepFailureCount = 0;
36867
- collectionThreshold = PluginAPI.ConfigReader.get('eventPropertyTimeout', 50);
36984
+ var configReader = PluginAPI.ConfigReader;
36985
+ /**
36986
+ * Maximum time in milliseconds that event property collection can take before it is considered a failure.
36987
+ * If collection fails more than 3 times consecutively, event property collection will be disabled completely.
36988
+ *
36989
+ * @access public
36990
+ * @category Config/Core
36991
+ * @name eventPropertyTimeout
36992
+ * @default 50
36993
+ * @type {number}
36994
+ */
36995
+ configReader.addOption(EVENT_PROPERTY_TIMEOUT, [configReader.sources.SNIPPET_SRC, configReader.sources.PENDO_CONFIG_SRC], 50);
36996
+ collectionThreshold = configReader.get(EVENT_PROPERTY_TIMEOUT);
36868
36997
  globalPendo.getEventPropertyTarget = getEventPropertyTarget;
36869
36998
  globalPendo.previewEventProperty = collectEventProperty;
36870
36999
  pluginAPI.Events.onClickCaptured.off(handleClickCaptured);
36871
37000
  pluginAPI.Events.onClickCaptured.on(handleClickCaptured);
36872
37001
  pluginAPI.Events.ready.on(addPageEventProperties);
37002
+ pluginAPI.Events.deliverablesLoaded.on(resetCepFailureCount);
36873
37003
  }
36874
37004
  function teardown() {
36875
37005
  pluginAPI.Events.onClickCaptured.off(handleClickCaptured);
36876
37006
  pluginAPI.Events.ready.off(addPageEventProperties);
37007
+ pluginAPI.Events.deliverablesLoaded.off(resetCepFailureCount);
36877
37008
  removePageEventProperties();
36878
37009
  pepFailureCount = 0;
36879
37010
  cepFailureCount = 0;
36880
37011
  }
37012
+ function resetCepFailureCount() {
37013
+ cepFailureCount = 0;
37014
+ }
36881
37015
  function getRuleTesterImpl(matchParents, proxyFn) {
36882
37016
  if (matchParents) {
36883
37017
  return function (elem, rule) {
@@ -36946,7 +37080,8 @@ const EventProperties = (function () {
36946
37080
  // Check to see if the target matches any of the feature rules
36947
37081
  // or shortcircuit if too much time has elapsed
36948
37082
  var ep;
36949
- for (var epIndex = 0; epIndex < pageEventProperties.length && getNow() - startTime < eventPropertyCollectionThreshold; epIndex++) {
37083
+ var epIndex;
37084
+ for (epIndex = 0; epIndex < pageEventProperties.length && getNow() - startTime < eventPropertyCollectionThreshold; epIndex++) {
36950
37085
  ep = pageEventProperties[epIndex];
36951
37086
  if (!ep.name) {
36952
37087
  return;
@@ -36958,14 +37093,20 @@ const EventProperties = (function () {
36958
37093
  }
36959
37094
  var collectionOverheadInMs = getNow() - startTime;
36960
37095
  if (collectionOverheadInMs > eventPropertyCollectionThreshold) {
36961
- logEventPropertyTimeoutMessage(eventPropertyCollectionThreshold, ep);
36962
37096
  pepFailureCount++;
37097
+ logEventPropertyTimeoutMessage({
37098
+ threshold: eventPropertyCollectionThreshold,
37099
+ name: ep.name,
37100
+ elapsedTime: collectionOverheadInMs,
37101
+ failureCount: pepFailureCount,
37102
+ index: epIndex,
37103
+ length: pageEventProperties.length
37104
+ });
36963
37105
  }
36964
37106
  else {
36965
37107
  pepFailureCount = 0;
36966
37108
  }
36967
37109
  if (pepFailureCount >= MAX_CONSECUTIVE_FAILURES) {
36968
- logEventPropertyDisabledMessage(eventPropertyCollectionThreshold);
36969
37110
  pageEventPropertiesTimeout = true;
36970
37111
  }
36971
37112
  return result;
@@ -36978,7 +37119,9 @@ const EventProperties = (function () {
36978
37119
  // Check to see if the target matches any of the feature rules
36979
37120
  // or shortcircuit if too much time has elapsed
36980
37121
  var ep;
36981
- for (var epIndex = 0; epIndex < globalPendo.eventProperties.length && getNow() - startTime < eventPropertyCollectionThreshold; epIndex++) {
37122
+ var epIndex;
37123
+ var len = globalPendo.eventProperties.length;
37124
+ for (epIndex = 0; epIndex < len && getNow() - startTime < eventPropertyCollectionThreshold; epIndex++) {
36982
37125
  ep = globalPendo.eventProperties[epIndex];
36983
37126
  var match = globalPendo._.any(ep.featureRules, function (rule) {
36984
37127
  try {
@@ -37005,7 +37148,6 @@ const EventProperties = (function () {
37005
37148
  // Naming matches event property name restrictions enforced by the backend.
37006
37149
  var collectionOverheadInMs = getNow() - startTime;
37007
37150
  if (collectionOverheadInMs > eventPropertyCollectionThreshold) {
37008
- cepFailureCount++;
37009
37151
  if (matchParents && elemProxyFn === globalPendo._.identity && globalPendo._.isFunction(globalPendo.getText)) {
37010
37152
  globalPendo.log('switching event property collection to fast text implementation');
37011
37153
  // Try again where textContent has been replaced with the faster (but limited) getText implementation
@@ -37017,10 +37159,17 @@ const EventProperties = (function () {
37017
37159
  return createFeatureEventPropertyMap(target, eventPropertyCollectionThreshold);
37018
37160
  }
37019
37161
  else {
37020
- logEventPropertyTimeoutMessage(eventPropertyCollectionThreshold, ep);
37162
+ cepFailureCount++;
37163
+ logEventPropertyTimeoutMessage({
37164
+ threshold: eventPropertyCollectionThreshold,
37165
+ featureId: ep.featureId,
37166
+ elapsedTime: collectionOverheadInMs,
37167
+ failureCount: cepFailureCount,
37168
+ index: epIndex,
37169
+ length: len
37170
+ });
37021
37171
  }
37022
37172
  if (cepFailureCount >= MAX_CONSECUTIVE_FAILURES) {
37023
- logEventPropertyDisabledMessage(eventPropertyCollectionThreshold);
37024
37173
  globalPendo.eventProperties = [];
37025
37174
  }
37026
37175
  }
@@ -37029,18 +37178,11 @@ const EventProperties = (function () {
37029
37178
  }
37030
37179
  return result;
37031
37180
  }
37032
- function logEventPropertyDisabledMessage(eventPropertyCollectionThreshold) {
37033
- globalPendo.log('event property collection disabled; collection took greater than ' +
37034
- eventPropertyCollectionThreshold +
37035
- ' milliseconds.');
37036
- }
37037
- function logEventPropertyTimeoutMessage(eventPropertyCollectionThreshold, ep) {
37038
- var logMessage = 'ERROR event property collection exceeded time limit.';
37039
- if (ep.featureId) {
37040
- logMessage += '\n For feature with id: ' + ep.featureId;
37041
- }
37042
- else {
37043
- logMessage += '\n For page event with name: ' + ep.name;
37181
+ function logEventPropertyTimeoutMessage({ threshold, featureId, name, elapsedTime, failureCount, index, length }) {
37182
+ var logMessage = `ERROR ${featureId ? 'click' : 'page'} event property collection timeout (${featureId || name}).`;
37183
+ logMessage += ` ${elapsedTime}ms/${threshold}ms, ${index}/${length} properties, ${failureCount}/${MAX_CONSECUTIVE_FAILURES} failures`;
37184
+ if (failureCount >= MAX_CONSECUTIVE_FAILURES) {
37185
+ logMessage += ', collection disabled.';
37044
37186
  }
37045
37187
  pluginAPI.log.critical(logMessage);
37046
37188
  }
@@ -55129,6 +55271,7 @@ var ConfigReader = (function () {
55129
55271
  */
55130
55272
  addOption('additionalApiKeys', [PENDO_CONFIG_SRC, SNIPPET_SRC]);
55131
55273
  addOption('allowedOriginServers');
55274
+ addOption('allowedOriginServerHashes');
55132
55275
  addOption('allowMixedApiKeyFrames', [SNIPPET_SRC, PENDO_CONFIG_SRC], true);
55133
55276
  /**
55134
55277
  * A function that returns either an array of strings or an object to decorate the url for events.