@pendo/agent 2.296.1 → 2.297.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.
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.1_';
7317
+ var VERSION = '2.297.1_';
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
+ }
515
+ }
516
+ if (typeof pattern === 'string') {
517
+ pattern = new RegExp('^' + pattern + '$');
516
518
  }
517
- if (stagingServer instanceof RegExp && stagingServer.test(location.host)) {
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.1_';
3896
- let PACKAGE_VERSION = '2.296.1';
3907
+ let VERSION = '2.297.1_';
3908
+ let PACKAGE_VERSION = '2.297.1';
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;
@@ -11433,11 +11445,13 @@ function isTrustedOrigin(host) {
11433
11445
  // for CNAME, trust the top-level origin
11434
11446
  if (host === window.location.origin)
11435
11447
  return true;
11436
- // Trust the data host
11448
+ // Trust the configured hosts
11437
11449
  if (host === getDataHost())
11438
11450
  return true;
11439
11451
  if (host === getAssetHost())
11440
11452
  return true;
11453
+ if (host === getContentHost())
11454
+ return true;
11441
11455
  // Domains that Pendo owns, will be swapped in by build patches
11442
11456
  const patterns = [
11443
11457
  /^https:\/\/(adopt\.)?((us1)\.)?(app|via|adopt|cdn)(\.(au|eu|gov|hsbc|jpn))?\.pendo\.io$/,
@@ -11456,12 +11470,20 @@ function isTrustedOrigin(host) {
11456
11470
  if (host === fullHostname)
11457
11471
  return true;
11458
11472
  }
11459
- if (_.contains(ConfigReader.get('allowedOriginServers', []), host))
11473
+ if (urlMatchesPatterns(host, ConfigReader.get('allowedOriginServers', []), ConfigReader.get('allowedOriginServerHashes', [])))
11460
11474
  return true;
11461
11475
  return _.any(patterns, function (pattern) {
11462
11476
  return pattern.test(host);
11463
11477
  });
11464
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
+ }
11465
11487
 
11466
11488
  function parseUrl(url) {
11467
11489
  if (!_.isString(url))
@@ -11495,9 +11517,9 @@ function addIntegrityAttribute(element, url) {
11495
11517
  }
11496
11518
  }
11497
11519
  var trustedOriginForLoadResource = function (origin) {
11498
- var noAllowedOriginServers = ConfigReader.get('allowedOriginServers', []).length === 0;
11520
+ var noAllowedOriginServers = !hasAllowedOriginServers() && !hasHashedAllowedOriginServers();
11499
11521
  var isAdoptPartner = treatAsAdoptPartner();
11500
- if (noAllowedOriginServers || isAdoptPartner || !isBetaAgent(getPendoConfig())) {
11522
+ if (noAllowedOriginServers || isAdoptPartner) {
11501
11523
  return true;
11502
11524
  }
11503
11525
  return isTrustedOrigin(origin);
@@ -12819,7 +12841,7 @@ function createSendQueue(options, send, guaranteedSend) {
12819
12841
  }
12820
12842
  });
12821
12843
  queue.onTimeout = function () {
12822
- _PerformanceMonitor.track(`${options.beacon}-gif-failure`);
12844
+ _PerformanceMonitor.count(`${options.beacon}-gif-failure`);
12823
12845
  };
12824
12846
  queue.retryPending = true;
12825
12847
  return queue;
@@ -13119,8 +13141,10 @@ var extractAttribute = function (element, attrName, type) {
13119
13141
  var tag = element.nodeName.toLowerCase();
13120
13142
  if ((tag == 'img' && attrName == 'src') ||
13121
13143
  (tag == 'a' && attrName == 'href')) {
13122
- var src = element.getAttribute(attrName);
13123
- return sanitizeUrl(handleEmbeddedData(src));
13144
+ if (useLegacyGetHref()) {
13145
+ var src = element.getAttribute(attrName);
13146
+ return sanitizeUrl(handleEmbeddedData(src));
13147
+ }
13124
13148
  }
13125
13149
  var attr = getAttributeValue(element, attrName);
13126
13150
  if (type && typeof attr !== type)
@@ -16308,8 +16332,19 @@ var BuildingBlockTooltips = (function () {
16308
16332
  offset: TOOLTIP_CONSTANTS.DEFAULT_CARET_OFFSET,
16309
16333
  borderWidth: 0
16310
16334
  };
16311
- if (containerDomJson.props.style.border) {
16312
- 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(' ');
16313
16348
  caretDimensions.borderColor = guideBorderArray[2];
16314
16349
  caretDimensions.borderWidth = parseInt(guideBorderArray[0], 10) || 0;
16315
16350
  }
@@ -21975,6 +22010,7 @@ function startPreviewMode(window) {
21975
22010
  if (isInDesignerPreviewMode()) {
21976
22011
  const pendoConfig = getPendoConfig();
21977
22012
  pendoConfig.allowedOriginServers = [];
22013
+ pendoConfig.allowedOriginServerHashes = [];
21978
22014
  }
21979
22015
  Events.startPreview.trigger();
21980
22016
  Events.leaderChanged.on(function (e) {
@@ -24935,7 +24971,7 @@ var _addCredits = function (elem) {
24935
24971
  return;
24936
24972
  }
24937
24973
  var img = document.createElement('img');
24938
- img.setAttribute('src', getAssetHost() + '/img/tiny-logo.png');
24974
+ img.setAttribute('src', getContentHost() + '/img/tiny-logo.png');
24939
24975
  var credits = dom(document.createElement('div')).addClass('_pendo-credits_')
24940
24976
  .css({
24941
24977
  bottom: 0,
@@ -26390,6 +26426,9 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
26390
26426
  };
26391
26427
 
26392
26428
  const PENDO_HEADERS_KEY = '_pendoHeaders';
26429
+ function getTransformedUrl(url) {
26430
+ return store.getters['networkUrl/getTransformedUrl']()(url);
26431
+ }
26393
26432
  class NetworkRequestIntercept {
26394
26433
  entriesToObject(entries) {
26395
26434
  const obj = {};
@@ -26482,6 +26521,7 @@ class NetworkRequestIntercept {
26482
26521
  window.fetch = function (...args) {
26483
26522
  return __awaiter(this, void 0, void 0, function* () {
26484
26523
  const [url, config = {}] = args;
26524
+ const transformedUrl = getTransformedUrl(url);
26485
26525
  const method = config.method || 'GET';
26486
26526
  const requestId = networkInterceptor.generateRequestId();
26487
26527
  // Capture request data
@@ -26490,7 +26530,7 @@ class NetworkRequestIntercept {
26490
26530
  const body = networkInterceptor.safelySerializeBody(config.body);
26491
26531
  _.each(networkInterceptor.callbackFns, ({ request }) => {
26492
26532
  if (_.isFunction(request))
26493
- request({ requestId, method, url, body, headers });
26533
+ request({ requestId, method, url: transformedUrl, body, headers });
26494
26534
  });
26495
26535
  }
26496
26536
  catch (e) {
@@ -26517,7 +26557,7 @@ class NetworkRequestIntercept {
26517
26557
  statusText,
26518
26558
  body: responseBody,
26519
26559
  headers,
26520
- url,
26560
+ url: transformedUrl,
26521
26561
  method
26522
26562
  });
26523
26563
  }
@@ -26541,7 +26581,7 @@ class NetworkRequestIntercept {
26541
26581
  statusText: 'Network Error',
26542
26582
  headers: {},
26543
26583
  body: null,
26544
- url,
26584
+ url: transformedUrl,
26545
26585
  method,
26546
26586
  error: error.message
26547
26587
  });
@@ -26563,8 +26603,9 @@ class NetworkRequestIntercept {
26563
26603
  return networkInterceptor._originalSetRequestHeader.apply(this, arguments);
26564
26604
  };
26565
26605
  XMLHttpRequest.prototype.open = function (method, url) {
26606
+ const transformedUrl = getTransformedUrl(url);
26566
26607
  this._method = method;
26567
- this._url = url;
26608
+ this._url = transformedUrl;
26568
26609
  this._requestId = networkInterceptor.generateRequestId();
26569
26610
  return networkInterceptor._originalXHROpen.apply(this, arguments);
26570
26611
  };
@@ -29663,8 +29704,21 @@ var attrActionEnum = {
29663
29704
  href: ['Replace', 'ForceSecure'],
29664
29705
  protocol: ['ForceSecure']
29665
29706
  };
29666
- const TARGETS = ['location', 'attribute', 'both'];
29707
+ const TARGETS = ['location', 'attribute', 'both', 'network', 'all'];
29667
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
+ }
29668
29722
  function UrlTransform(attr, action, data, target) {
29669
29723
  if (_.isObject(attr)) {
29670
29724
  action = attr.action;
@@ -29680,14 +29734,11 @@ function UrlTransform(attr, action, data, target) {
29680
29734
  var validActions = attrActionEnum[attr].join(', ');
29681
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: ...}');
29682
29736
  }
29683
- // validate 'target'
29684
- if (TARGETS.indexOf(target) < 0) {
29685
- target = DEFAULT_TARGET;
29686
- }
29687
29737
  this.attr = attr;
29688
29738
  this.action = action;
29689
29739
  this.data = data;
29690
- this.target = target || DEFAULT_TARGET;
29740
+ // validate and normalize target
29741
+ this.target = normalizeTarget(target);
29691
29742
  }
29692
29743
  UrlTransform.prototype.applyTo = function (url) {
29693
29744
  var actionImpls = {
@@ -29885,12 +29936,16 @@ var LocationModule = (function (global) {
29885
29936
  addTransforms(context, transforms) {
29886
29937
  _.each(transforms, function (f) {
29887
29938
  const t = UrlTransform.fromJSON(f);
29888
- 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')) {
29889
29941
  context.commit('addTransform', t);
29890
29942
  }
29891
- if (t.target === 'attribute' || t.target === 'both') {
29943
+ if (_.contains(targets, 'attribute') || _.contains(targets, 'both') || _.contains(targets, 'all')) {
29892
29944
  store.dispatch('nodeAttr/addAttrTransform', t);
29893
29945
  }
29946
+ if (_.contains(targets, 'network') || _.contains(targets, 'all')) {
29947
+ store.dispatch('networkUrl/addNetworkTransform', t);
29948
+ }
29894
29949
  });
29895
29950
  },
29896
29951
  addInternalTransforms(context, transforms) {
@@ -29929,6 +29984,7 @@ var LocationModule = (function (global) {
29929
29984
  clearTransforms(state) {
29930
29985
  state.transforms = [];
29931
29986
  store.commit('nodeAttr/clearURLTransforms');
29987
+ store.commit('networkUrl/clearURLTransforms');
29932
29988
  },
29933
29989
  clearInternalTransforms(state) {
29934
29990
  state.internalTransforms = [];
@@ -33802,6 +33858,7 @@ const DebuggerModule = (() => {
33802
33858
  };
33803
33859
  })();
33804
33860
 
33861
+ const URL_ATTR_NAMES = ['src', 'href'];
33805
33862
  const NodeAttrModule = (function (global) {
33806
33863
  const state = {
33807
33864
  transforms: []
@@ -33835,11 +33892,14 @@ const NodeAttrModule = (function (global) {
33835
33892
  };
33836
33893
  const getters = {
33837
33894
  getAttribute(state) {
33838
- return function (element, attrName) {
33895
+ return function (element, attrName = '') {
33839
33896
  let attrValue = element.getAttribute ? element.getAttribute(attrName) : element[attrName];
33840
33897
  if (_.size(state.transforms) < 1) {
33841
33898
  return attrValue;
33842
33899
  }
33900
+ if (URL_ATTR_NAMES.indexOf(attrName.toLowerCase()) === -1) {
33901
+ return attrValue;
33902
+ }
33843
33903
  try {
33844
33904
  let url = resolveAttrValueAsURL(attrValue);
33845
33905
  url = _.reduce([
@@ -33864,6 +33924,54 @@ const NodeAttrModule = (function (global) {
33864
33924
  };
33865
33925
  })();
33866
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
+
33867
33975
  function registerModules(store) {
33868
33976
  store.registerModule('debugger', DebuggerModule);
33869
33977
  store.registerModule('errorLog', ErrorLogModule);
@@ -33875,6 +33983,7 @@ function registerModules(store) {
33875
33983
  store.registerModule('metadata', MetadataModule);
33876
33984
  store.registerModule('preview', PreviewModule);
33877
33985
  store.registerModule('nodeAttr', NodeAttrModule);
33986
+ store.registerModule('networkUrl', NetworkUrlModule);
33878
33987
  }
33879
33988
 
33880
33989
  const IFrameMonitor = (function () {
@@ -36604,7 +36713,7 @@ var Branding = (function () {
36604
36713
  link.href = 'https://www.pendo.io/pendo-free/nps?utm_source=pendo_app&utm_medium=branded-nps&utm_campaign=free-branded-nps';
36605
36714
  link.target = '_blank';
36606
36715
  var img = document.createElement('img');
36607
- img.setAttribute('src', getAssetHost() + '/img/nps-branding.png');
36716
+ img.setAttribute('src', getContentHost() + '/img/nps-branding.png');
36608
36717
  link.appendChild(img);
36609
36718
  link.style.display = 'inline-block';
36610
36719
  var div = document.createElement('div');
@@ -36852,6 +36961,7 @@ const EventProperties = (function () {
36852
36961
  let cepFailureCount;
36853
36962
  let collectionThreshold;
36854
36963
  const MAX_CONSECUTIVE_FAILURES = 3;
36964
+ const EVENT_PROPERTY_TIMEOUT = 'eventPropertyTimeout';
36855
36965
  const collectClickEventProperties = makeSafe(createClickEventProperties);
36856
36966
  const collectPageEventProperties = makeSafe(createPageEventProperties);
36857
36967
  return {
@@ -36871,20 +36981,37 @@ const EventProperties = (function () {
36871
36981
  pageEventPropertiesTimeout = false;
36872
36982
  pepFailureCount = 0;
36873
36983
  cepFailureCount = 0;
36874
- 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);
36875
36997
  globalPendo.getEventPropertyTarget = getEventPropertyTarget;
36876
36998
  globalPendo.previewEventProperty = collectEventProperty;
36877
36999
  pluginAPI.Events.onClickCaptured.off(handleClickCaptured);
36878
37000
  pluginAPI.Events.onClickCaptured.on(handleClickCaptured);
36879
37001
  pluginAPI.Events.ready.on(addPageEventProperties);
37002
+ pluginAPI.Events.deliverablesLoaded.on(resetCepFailureCount);
36880
37003
  }
36881
37004
  function teardown() {
36882
37005
  pluginAPI.Events.onClickCaptured.off(handleClickCaptured);
36883
37006
  pluginAPI.Events.ready.off(addPageEventProperties);
37007
+ pluginAPI.Events.deliverablesLoaded.off(resetCepFailureCount);
36884
37008
  removePageEventProperties();
36885
37009
  pepFailureCount = 0;
36886
37010
  cepFailureCount = 0;
36887
37011
  }
37012
+ function resetCepFailureCount() {
37013
+ cepFailureCount = 0;
37014
+ }
36888
37015
  function getRuleTesterImpl(matchParents, proxyFn) {
36889
37016
  if (matchParents) {
36890
37017
  return function (elem, rule) {
@@ -36953,7 +37080,8 @@ const EventProperties = (function () {
36953
37080
  // Check to see if the target matches any of the feature rules
36954
37081
  // or shortcircuit if too much time has elapsed
36955
37082
  var ep;
36956
- 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++) {
36957
37085
  ep = pageEventProperties[epIndex];
36958
37086
  if (!ep.name) {
36959
37087
  return;
@@ -36965,14 +37093,20 @@ const EventProperties = (function () {
36965
37093
  }
36966
37094
  var collectionOverheadInMs = getNow() - startTime;
36967
37095
  if (collectionOverheadInMs > eventPropertyCollectionThreshold) {
36968
- logEventPropertyTimeoutMessage(eventPropertyCollectionThreshold, ep);
36969
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
+ });
36970
37105
  }
36971
37106
  else {
36972
37107
  pepFailureCount = 0;
36973
37108
  }
36974
37109
  if (pepFailureCount >= MAX_CONSECUTIVE_FAILURES) {
36975
- logEventPropertyDisabledMessage(eventPropertyCollectionThreshold);
36976
37110
  pageEventPropertiesTimeout = true;
36977
37111
  }
36978
37112
  return result;
@@ -36985,7 +37119,9 @@ const EventProperties = (function () {
36985
37119
  // Check to see if the target matches any of the feature rules
36986
37120
  // or shortcircuit if too much time has elapsed
36987
37121
  var ep;
36988
- 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++) {
36989
37125
  ep = globalPendo.eventProperties[epIndex];
36990
37126
  var match = globalPendo._.any(ep.featureRules, function (rule) {
36991
37127
  try {
@@ -37012,7 +37148,6 @@ const EventProperties = (function () {
37012
37148
  // Naming matches event property name restrictions enforced by the backend.
37013
37149
  var collectionOverheadInMs = getNow() - startTime;
37014
37150
  if (collectionOverheadInMs > eventPropertyCollectionThreshold) {
37015
- cepFailureCount++;
37016
37151
  if (matchParents && elemProxyFn === globalPendo._.identity && globalPendo._.isFunction(globalPendo.getText)) {
37017
37152
  globalPendo.log('switching event property collection to fast text implementation');
37018
37153
  // Try again where textContent has been replaced with the faster (but limited) getText implementation
@@ -37024,10 +37159,17 @@ const EventProperties = (function () {
37024
37159
  return createFeatureEventPropertyMap(target, eventPropertyCollectionThreshold);
37025
37160
  }
37026
37161
  else {
37027
- 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
+ });
37028
37171
  }
37029
37172
  if (cepFailureCount >= MAX_CONSECUTIVE_FAILURES) {
37030
- logEventPropertyDisabledMessage(eventPropertyCollectionThreshold);
37031
37173
  globalPendo.eventProperties = [];
37032
37174
  }
37033
37175
  }
@@ -37036,18 +37178,11 @@ const EventProperties = (function () {
37036
37178
  }
37037
37179
  return result;
37038
37180
  }
37039
- function logEventPropertyDisabledMessage(eventPropertyCollectionThreshold) {
37040
- globalPendo.log('event property collection disabled; collection took greater than ' +
37041
- eventPropertyCollectionThreshold +
37042
- ' milliseconds.');
37043
- }
37044
- function logEventPropertyTimeoutMessage(eventPropertyCollectionThreshold, ep) {
37045
- var logMessage = 'ERROR event property collection exceeded time limit.';
37046
- if (ep.featureId) {
37047
- logMessage += '\n For feature with id: ' + ep.featureId;
37048
- }
37049
- else {
37050
- 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.';
37051
37186
  }
37052
37187
  pluginAPI.log.critical(logMessage);
37053
37188
  }
@@ -55136,6 +55271,7 @@ var ConfigReader = (function () {
55136
55271
  */
55137
55272
  addOption('additionalApiKeys', [PENDO_CONFIG_SRC, SNIPPET_SRC]);
55138
55273
  addOption('allowedOriginServers');
55274
+ addOption('allowedOriginServerHashes');
55139
55275
  addOption('allowMixedApiKeyFrames', [SNIPPET_SRC, PENDO_CONFIG_SRC], true);
55140
55276
  /**
55141
55277
  * A function that returns either an array of strings or an object to decorate the url for events.