@pendo/agent 2.325.0 → 2.327.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/debugger-plugin.min.js +1 -1
- package/dist/dom.esm.js +58 -49
- package/dist/pendo.module.js +687 -254
- package/dist/pendo.module.min.js +8 -6
- package/dist/servers.json +7 -7
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -2707,11 +2707,11 @@ var underscoreExports = underscore.exports;
|
|
|
2707
2707
|
var _ = /*@__PURE__*/getDefaultExportFromCjs(underscoreExports);
|
|
2708
2708
|
|
|
2709
2709
|
/**
|
|
2710
|
-
* Utility function to check if passed value exists. Returns false for `null` and `undefined`.
|
|
2710
|
+
* Utility function to check if the passed value exists. Returns false for `null` and `undefined`.
|
|
2711
2711
|
*
|
|
2712
2712
|
* @access public
|
|
2713
2713
|
* @category Utility
|
|
2714
|
-
* @param {any} value
|
|
2714
|
+
* @param {any} arg value to type check
|
|
2715
2715
|
* @returns {Boolean}
|
|
2716
2716
|
* @example
|
|
2717
2717
|
* pendo.doesExist(null) => false
|
|
@@ -2964,7 +2964,7 @@ var ConfigReader = (function () {
|
|
|
2964
2964
|
*
|
|
2965
2965
|
* @access public
|
|
2966
2966
|
* @category Config/Core
|
|
2967
|
-
* @name
|
|
2967
|
+
* @name forcedLeader
|
|
2968
2968
|
* @default false
|
|
2969
2969
|
* @type {boolean}
|
|
2970
2970
|
*/
|
|
@@ -3151,7 +3151,7 @@ var ConfigReader = (function () {
|
|
|
3151
3151
|
* An array of exact strings that can still be included in event data if text capture is disabled
|
|
3152
3152
|
* (`excludeAllText`). This will not override any allow list specified by your application settings but will apply if none is provided.
|
|
3153
3153
|
* These are not selectors but are equality checks (the string 'Bug' will allow links that have 'Bug' as the
|
|
3154
|
-
* text to be captured but not ones like 'Bug Report')
|
|
3154
|
+
* text to be captured but not ones like 'Bug Report').
|
|
3155
3155
|
*
|
|
3156
3156
|
* @access public
|
|
3157
3157
|
* @category Config/Analytics
|
|
@@ -3249,7 +3249,7 @@ var ConfigReader = (function () {
|
|
|
3249
3249
|
/**
|
|
3250
3250
|
* By default, the web SDK will also attempt to intercept calls to `stopPropagation` and
|
|
3251
3251
|
* `stopImmediatePropagation` for click, focus, submit, and change events in order to ensure that Pendo can
|
|
3252
|
-
* still
|
|
3252
|
+
* still properly recognize these events. In the case of this causing duplicate events or other issues, this
|
|
3253
3253
|
* functionality can be disabled.
|
|
3254
3254
|
*
|
|
3255
3255
|
* @access public
|
|
@@ -3312,7 +3312,7 @@ var ConfigReader = (function () {
|
|
|
3312
3312
|
*/
|
|
3313
3313
|
addOption('cacheGuides', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3314
3314
|
/**
|
|
3315
|
-
* How often to clear the guides cache (in milliseconds)
|
|
3315
|
+
* How often to clear the guides cache (in milliseconds).
|
|
3316
3316
|
*
|
|
3317
3317
|
* @access public
|
|
3318
3318
|
* @category Config/Guides
|
|
@@ -3346,7 +3346,7 @@ var ConfigReader = (function () {
|
|
|
3346
3346
|
addOption('disableGlobalCSS', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3347
3347
|
/**
|
|
3348
3348
|
* Building block guides use an inline style tag for various pseudo styles (e.g. hover, carets, animations).
|
|
3349
|
-
* These can be turned off using this flag for
|
|
3349
|
+
* These can be turned off using this flag for applications with more restrictive CSP settings but will
|
|
3350
3350
|
* require custom effort to reach style parity.
|
|
3351
3351
|
*
|
|
3352
3352
|
* @access public
|
|
@@ -3372,7 +3372,7 @@ var ConfigReader = (function () {
|
|
|
3372
3372
|
* cookies, localStorage, click tracking, and metadata. Only displays guides
|
|
3373
3373
|
* that have been configured explicitly to show to this visitor.
|
|
3374
3374
|
*
|
|
3375
|
-
* @access
|
|
3375
|
+
* @access private
|
|
3376
3376
|
* @category Config/Guides
|
|
3377
3377
|
* @name doNotTrackGuides
|
|
3378
3378
|
* @default false
|
|
@@ -3380,7 +3380,7 @@ var ConfigReader = (function () {
|
|
|
3380
3380
|
*/
|
|
3381
3381
|
addOption('doNotTrackGuides', [SNIPPET_SRC, PENDO_CONFIG_SRC]);
|
|
3382
3382
|
/**
|
|
3383
|
-
* If `true`, the web SDK will listen for `alt+shift+8` on the keyboard and try to launch the designer
|
|
3383
|
+
* If `true`, the web SDK will listen for `alt+shift+8` on the keyboard and try to launch the designer. The
|
|
3384
3384
|
* keyboard shortcut requires the guide launch modal of Engage to be open in another tab showing the shortcut.
|
|
3385
3385
|
*
|
|
3386
3386
|
* @access public
|
|
@@ -3458,7 +3458,7 @@ var ConfigReader = (function () {
|
|
|
3458
3458
|
*/
|
|
3459
3459
|
addOption('guides.disabled', [SNIPPET_SRC], false, undefined, ['disableGuides']);
|
|
3460
3460
|
/**
|
|
3461
|
-
* If
|
|
3461
|
+
* If `true`, guides with slow selectors will be removed from guide display processing.
|
|
3462
3462
|
* This will improve application performance, but slow guides will not be shown to users.
|
|
3463
3463
|
*
|
|
3464
3464
|
* @access public
|
|
@@ -3514,7 +3514,7 @@ var ConfigReader = (function () {
|
|
|
3514
3514
|
*/
|
|
3515
3515
|
addOption('inlineStyleNonce', [SNIPPET_SRC]);
|
|
3516
3516
|
/**
|
|
3517
|
-
* Formerly `leaderKey
|
|
3517
|
+
* Formerly `leaderKey`. Specify a preferred publicAppId to lead the multi-application iframe installation to make decisions about automatic
|
|
3518
3518
|
* guide display. In installations with more than 2 publicAppIds, the leaderApplication can be specified as a priority
|
|
3519
3519
|
* list (e.g. `leaderApplication: ['key1', 'key2', ...]`). Either all frames must agree on the leaderApplication setting,
|
|
3520
3520
|
* or only one frame should specify the leaderApplication. If neither of these conditions are met, the default leader
|
|
@@ -3544,7 +3544,7 @@ var ConfigReader = (function () {
|
|
|
3544
3544
|
addOption('storage.allowKeys', [SNIPPET_SRC], '*');
|
|
3545
3545
|
// Feedback
|
|
3546
3546
|
/**
|
|
3547
|
-
* If Feedback is
|
|
3547
|
+
* If Feedback is set up for your subscription, this option can be used to selectively disable Feedback.
|
|
3548
3548
|
*
|
|
3549
3549
|
* @access public
|
|
3550
3550
|
* @category Config/Core
|
|
@@ -3557,8 +3557,8 @@ var ConfigReader = (function () {
|
|
|
3557
3557
|
addOption('feedbackSettings', [PENDO_CONFIG_SRC], {});
|
|
3558
3558
|
addOption('pendoFeedback', [PENDO_CONFIG_SRC], false);
|
|
3559
3559
|
/**
|
|
3560
|
-
* If set, the web SDK will use this as the suffix when writing last step advanced key into the
|
|
3561
|
-
* This supports cross
|
|
3560
|
+
* If set, the web SDK will use this as the suffix when writing the last step advanced key into the visitor's cookie.
|
|
3561
|
+
* This supports cross-app guides by having a shared accessible location for different apps on the same effective level domain.
|
|
3562
3562
|
*
|
|
3563
3563
|
* @access public
|
|
3564
3564
|
* @category Config/Core
|
|
@@ -3979,12 +3979,12 @@ let SERVER = '';
|
|
|
3979
3979
|
let ASSET_HOST = '';
|
|
3980
3980
|
let ASSET_PATH = '';
|
|
3981
3981
|
let DESIGNER_SERVER = '';
|
|
3982
|
-
let VERSION = '2.
|
|
3983
|
-
let PACKAGE_VERSION = '2.
|
|
3982
|
+
let VERSION = '2.327.0_';
|
|
3983
|
+
let PACKAGE_VERSION = '2.327.0';
|
|
3984
3984
|
let LOADER = 'xhr';
|
|
3985
3985
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
3986
3986
|
/**
|
|
3987
|
-
* Returns current version of the Pendo Web SDK as a string. Also directly accessible at `pendo.VERSION`.
|
|
3987
|
+
* Returns the current version of the Pendo Web SDK as a string. Also directly accessible at `pendo.VERSION`.
|
|
3988
3988
|
*
|
|
3989
3989
|
* @access public
|
|
3990
3990
|
* @category Core
|
|
@@ -5694,6 +5694,7 @@ var Events = (function () {
|
|
|
5694
5694
|
new EventType('eventCaptured', [DEBUG]),
|
|
5695
5695
|
new EventType('error', [DEBUG, LIFECYCLE]),
|
|
5696
5696
|
new EventType('onClickCaptured', [DEBUG]),
|
|
5697
|
+
new EventType('onEventCaptured', [DEBUG]),
|
|
5697
5698
|
new EventType('urlChanged', [LIFECYCLE]),
|
|
5698
5699
|
new EventType('leaderChanged', [LIFECYCLE, FRAMES]),
|
|
5699
5700
|
new EventType('transmit:locked', [LIFECYCLE]),
|
|
@@ -5924,7 +5925,7 @@ const ACCOUNT_ID_KEY = 'accountId';
|
|
|
5924
5925
|
*
|
|
5925
5926
|
* @access public
|
|
5926
5927
|
* @category Identity
|
|
5927
|
-
* @param {string} prefix string to prepend to the unique id
|
|
5928
|
+
* @param {string} [prefix] string to prepend to the unique id
|
|
5928
5929
|
* @returns {string}
|
|
5929
5930
|
* @example
|
|
5930
5931
|
* pendo.generate_unique_id('user-') => 'user-RaPiWJ5M53Y'
|
|
@@ -6041,7 +6042,7 @@ function findVisitorId() {
|
|
|
6041
6042
|
}
|
|
6042
6043
|
/**
|
|
6043
6044
|
* Returns the id for the visitor currently being applied to any events being sent to Pendo.
|
|
6044
|
-
* Will always be set either by host application or as an anonymous generated ID.
|
|
6045
|
+
* Will always be set either by the host application or as an anonymous generated ID.
|
|
6045
6046
|
*
|
|
6046
6047
|
* @access public
|
|
6047
6048
|
* @alias getVisitorId
|
|
@@ -6071,8 +6072,8 @@ function get_visitor_id_public() {
|
|
|
6071
6072
|
return get_visitor_id() || generate_anonymous_visitor_id();
|
|
6072
6073
|
}
|
|
6073
6074
|
/**
|
|
6074
|
-
* Sets visitor id for the web SDK. Requires a valid visitor id string. This will not change
|
|
6075
|
-
* or clear existing visitor metadata
|
|
6075
|
+
* Sets the visitor id for the web SDK. Requires a valid visitor id string. This will not change
|
|
6076
|
+
* or clear existing visitor metadata.
|
|
6076
6077
|
*
|
|
6077
6078
|
* @access public
|
|
6078
6079
|
* @category Identity
|
|
@@ -6114,8 +6115,8 @@ var get_account_id = function () {
|
|
|
6114
6115
|
return pendo$1.accountId;
|
|
6115
6116
|
};
|
|
6116
6117
|
/**
|
|
6117
|
-
* Sets account id for the web SDK without changing existing metadata. However,
|
|
6118
|
-
*
|
|
6118
|
+
* Sets the account id for the web SDK without changing existing metadata. However,
|
|
6119
|
+
* an invalid account id or an explicit `null` value will clear the current account id
|
|
6119
6120
|
* and account metadata.
|
|
6120
6121
|
*
|
|
6121
6122
|
* @access public
|
|
@@ -6166,7 +6167,7 @@ function clearAccount() {
|
|
|
6166
6167
|
}
|
|
6167
6168
|
}
|
|
6168
6169
|
/**
|
|
6169
|
-
* Removes current visitor id and account id. Triggers an identify event and reloads
|
|
6170
|
+
* Removes the current visitor id and account id. Triggers an identify event and reloads
|
|
6170
6171
|
* with a new anonymous visitor.
|
|
6171
6172
|
*
|
|
6172
6173
|
* @access public
|
|
@@ -8901,16 +8902,17 @@ var SizzleProxy = wrapSizzle(Sizzle);
|
|
|
8901
8902
|
* pendo.dom('h1')[0].remove()
|
|
8902
8903
|
* @example
|
|
8903
8904
|
* pendo.dom('.left').css({ 'text-align': 'center' })
|
|
8904
|
-
*/
|
|
8905
|
-
|
|
8906
|
-
*
|
|
8907
|
-
*
|
|
8908
|
-
* @
|
|
8909
|
-
* @
|
|
8910
|
-
* @
|
|
8911
|
-
* @
|
|
8912
|
-
*
|
|
8913
|
-
|
|
8905
|
+
*/
|
|
8906
|
+
/**
|
|
8907
|
+
* Creates new DOM elements from HTML text.
|
|
8908
|
+
*
|
|
8909
|
+
* @param {string} htmlString HTML syntax used to produce new DOM elements
|
|
8910
|
+
* @returns {DomQuery} array with the newly created elements
|
|
8911
|
+
* @access public
|
|
8912
|
+
* @category DOM
|
|
8913
|
+
* @example
|
|
8914
|
+
* pendo.dom('<div><span>this should create an unattached DOM node</span></div>');
|
|
8915
|
+
*/
|
|
8914
8916
|
function dom(selection, context) {
|
|
8915
8917
|
var self = this;
|
|
8916
8918
|
var nodes;
|
|
@@ -9672,7 +9674,7 @@ var objectToQueryString = function (obj) {
|
|
|
9672
9674
|
}, '');
|
|
9673
9675
|
};
|
|
9674
9676
|
/**
|
|
9675
|
-
* URL getter that
|
|
9677
|
+
* URL getter that returns the URL used by the web SDK to describe all data events
|
|
9676
9678
|
* collected for this app and for Guide requests. This URL can differ from the browser's URL based on
|
|
9677
9679
|
* customizations made by the host application. The URL customizations can be learned about [here](https://agent.pendo.io/advanced/location).
|
|
9678
9680
|
*
|
|
@@ -10107,7 +10109,7 @@ var locked = false;
|
|
|
10107
10109
|
* @category Events
|
|
10108
10110
|
* @example
|
|
10109
10111
|
* $ pendo.stopSendingEvents()
|
|
10110
|
-
* > Pendo Web SDK locked.
|
|
10112
|
+
* > Pendo Web SDK locked. No more events will be written.
|
|
10111
10113
|
*/
|
|
10112
10114
|
var lockEvents = function () {
|
|
10113
10115
|
var fireEvent = isUnlocked();
|
|
@@ -10124,7 +10126,7 @@ var lockEvents = function () {
|
|
|
10124
10126
|
* @category Events
|
|
10125
10127
|
* @example
|
|
10126
10128
|
* $ pendo.startSendingEvents()
|
|
10127
|
-
* > Pendo Web SDK unlocked.
|
|
10129
|
+
* > Pendo Web SDK unlocked. Events will be written.
|
|
10128
10130
|
*/
|
|
10129
10131
|
var unlockEvents = function () {
|
|
10130
10132
|
var fireEvent = !isUnlocked();
|
|
@@ -10154,8 +10156,8 @@ var isUnlocked = function () {
|
|
|
10154
10156
|
* Check if the Element has this classname.
|
|
10155
10157
|
*
|
|
10156
10158
|
* @alias hasClass
|
|
10157
|
-
* @param {element}
|
|
10158
|
-
* @param {String}
|
|
10159
|
+
* @param {element} ele The Element to test for the classname
|
|
10160
|
+
* @param {String} cls The classname to look for on the element
|
|
10159
10161
|
* @returns {Boolean}
|
|
10160
10162
|
* @access public
|
|
10161
10163
|
* @category DOM
|
|
@@ -10195,7 +10197,7 @@ var _addClass = function (ele, cls) {
|
|
|
10195
10197
|
}
|
|
10196
10198
|
};
|
|
10197
10199
|
/**
|
|
10198
|
-
* Remove a classname from an
|
|
10200
|
+
* Remove a classname from an Element's classlist.
|
|
10199
10201
|
*
|
|
10200
10202
|
* @alias removeClass
|
|
10201
10203
|
* @param {element} ele The Element from which the class will be removed
|
|
@@ -10218,7 +10220,7 @@ var _removeClass = function (ele, cls) {
|
|
|
10218
10220
|
}
|
|
10219
10221
|
};
|
|
10220
10222
|
/**
|
|
10221
|
-
* Sets the classname
|
|
10223
|
+
* Sets the classname for an Element.
|
|
10222
10224
|
*
|
|
10223
10225
|
* @alias setClass
|
|
10224
10226
|
* @param {element} ele The Element that will get the new classlist.
|
|
@@ -10976,8 +10978,15 @@ function scrollElementIntoParentRect(element, scrollParent) {
|
|
|
10976
10978
|
clientRect.left += diff;
|
|
10977
10979
|
clientRect.right += diff;
|
|
10978
10980
|
}
|
|
10979
|
-
|
|
10980
|
-
|
|
10981
|
+
const isScrollByAFunction = _.isFunction(scrollParent.scrollBy);
|
|
10982
|
+
const isScrollByNative = isScrollByAFunction && isNativeCode(scrollParent.scrollBy);
|
|
10983
|
+
if (isScrollByAFunction) {
|
|
10984
|
+
if (isScrollByNative) {
|
|
10985
|
+
scrollParent.scrollBy(xScrollAmount, yScrollAmount);
|
|
10986
|
+
}
|
|
10987
|
+
else {
|
|
10988
|
+
scrollParent.scrollTo(scrollParent.scrollX + xScrollAmount, scrollParent.scrollY + yScrollAmount);
|
|
10989
|
+
}
|
|
10981
10990
|
}
|
|
10982
10991
|
else {
|
|
10983
10992
|
scrollParent.scrollTop += yScrollAmount;
|
|
@@ -11023,8 +11032,8 @@ DomQuery.$ = {
|
|
|
11023
11032
|
return newDom;
|
|
11024
11033
|
},
|
|
11025
11034
|
/**
|
|
11026
|
-
* Iterate over each element in the DomQuery list and call the
|
|
11027
|
-
*
|
|
11035
|
+
* Iterate over each element in the DomQuery list and call the provided callback function passing in the
|
|
11036
|
+
* element as the argument.
|
|
11028
11037
|
*
|
|
11029
11038
|
* @function each
|
|
11030
11039
|
* @param {function} callback The callback to be called for each element in the list
|
|
@@ -11046,7 +11055,7 @@ DomQuery.$ = {
|
|
|
11046
11055
|
* Iterate over each element in the DomQuery list and create and append the Elements represented by the HTML string provided.
|
|
11047
11056
|
*
|
|
11048
11057
|
* @function html
|
|
11049
|
-
* @param {String}
|
|
11058
|
+
* @param {String} content String representing html to be created as dom Elements for each of the Elements in the list.
|
|
11050
11059
|
* @returns {DomQuery}
|
|
11051
11060
|
* @category DOMQuery
|
|
11052
11061
|
* @access public
|
|
@@ -11067,7 +11076,7 @@ DomQuery.$ = {
|
|
|
11067
11076
|
* Iterate over each element in the DomQuery list and add the text provided as innerText on the element.
|
|
11068
11077
|
*
|
|
11069
11078
|
* @function text
|
|
11070
|
-
* @param {String} content String to be added as innerText
|
|
11079
|
+
* @param {String} content String to be added as innerText.
|
|
11071
11080
|
* @returns {DomQuery}
|
|
11072
11081
|
* @access public
|
|
11073
11082
|
* @category DOMQuery
|
|
@@ -11132,7 +11141,7 @@ DomQuery.$ = {
|
|
|
11132
11141
|
});
|
|
11133
11142
|
},
|
|
11134
11143
|
/**
|
|
11135
|
-
* Iterate over each element and
|
|
11144
|
+
* Iterate over each element and check for each class name. Returns true if all elements have each classname.
|
|
11136
11145
|
*
|
|
11137
11146
|
* @function hasClass
|
|
11138
11147
|
* @param {String} classNames Space separated string of classnames.
|
|
@@ -11155,7 +11164,7 @@ DomQuery.$ = {
|
|
|
11155
11164
|
return allElemsHaveClass;
|
|
11156
11165
|
},
|
|
11157
11166
|
/**
|
|
11158
|
-
* Iterate over each element and toggle each class name on or off depending on
|
|
11167
|
+
* Iterate over each element and toggle each class name on or off depending on
|
|
11159
11168
|
* the current state of the element.
|
|
11160
11169
|
*
|
|
11161
11170
|
* @function toggleClass
|
|
@@ -11183,7 +11192,7 @@ DomQuery.$ = {
|
|
|
11183
11192
|
* Iterate over each element and apply the styles object.
|
|
11184
11193
|
*
|
|
11185
11194
|
* @function css
|
|
11186
|
-
* @param {Object} styles Object containing style
|
|
11195
|
+
* @param {Object} styles Object containing style attribute names and values.
|
|
11187
11196
|
* @returns {DomQuery}
|
|
11188
11197
|
* @access public
|
|
11189
11198
|
* @category DOMQuery
|
|
@@ -11237,7 +11246,7 @@ DomQuery.$ = {
|
|
|
11237
11246
|
return self;
|
|
11238
11247
|
},
|
|
11239
11248
|
/**
|
|
11240
|
-
* Add all elements in the list as
|
|
11249
|
+
* Add all elements in the list as topmost child nodes of the first element found for the given selector.
|
|
11241
11250
|
*
|
|
11242
11251
|
* @function prependTo
|
|
11243
11252
|
* @param {String} selector CSS selector to identify the target parent element
|
|
@@ -11252,10 +11261,10 @@ DomQuery.$ = {
|
|
|
11252
11261
|
return this;
|
|
11253
11262
|
},
|
|
11254
11263
|
/**
|
|
11255
|
-
* Add all children from the selector as
|
|
11264
|
+
* Add all children from the selector as topmost children of the first element in this list.
|
|
11256
11265
|
*
|
|
11257
11266
|
* @function prepend
|
|
11258
|
-
* @param {String} selector CSS selector to identify
|
|
11267
|
+
* @param {String} selector CSS selector to identify topmost child element(s)
|
|
11259
11268
|
* @returns {DomQuery}
|
|
11260
11269
|
* @access public
|
|
11261
11270
|
* @category DOMQuery
|
|
@@ -11279,7 +11288,7 @@ DomQuery.$ = {
|
|
|
11279
11288
|
return self;
|
|
11280
11289
|
},
|
|
11281
11290
|
/**
|
|
11282
|
-
* Return the parent node of the first element in this list
|
|
11291
|
+
* Return the parent node of the first element in this list.
|
|
11283
11292
|
*
|
|
11284
11293
|
* @function getParent
|
|
11285
11294
|
* @returns {element}
|
|
@@ -11296,7 +11305,7 @@ DomQuery.$ = {
|
|
|
11296
11305
|
},
|
|
11297
11306
|
/**
|
|
11298
11307
|
* For the first element in this list, insert the first element from the selector before it
|
|
11299
|
-
* in parent element's child nodes list.
|
|
11308
|
+
* in the parent element's child nodes list.
|
|
11300
11309
|
*
|
|
11301
11310
|
* @function insertBefore
|
|
11302
11311
|
* @param {String} selector CSS selector for the element to be inserted before this element
|
|
@@ -11335,7 +11344,7 @@ DomQuery.$ = {
|
|
|
11335
11344
|
return this;
|
|
11336
11345
|
},
|
|
11337
11346
|
/**
|
|
11338
|
-
* Iterate over each element and set the attribute name to the specified value
|
|
11347
|
+
* Iterate over each element and set the attribute name to the specified value.
|
|
11339
11348
|
*
|
|
11340
11349
|
* @function attr
|
|
11341
11350
|
* @param {String} attrName Name of attribute to set
|
|
@@ -11396,10 +11405,10 @@ DomQuery.$ = {
|
|
|
11396
11405
|
return dom(this[index]);
|
|
11397
11406
|
},
|
|
11398
11407
|
/**
|
|
11399
|
-
* Set the height or unset the height for the first element in the list
|
|
11408
|
+
* Set the height or unset the height for the first element in the list.
|
|
11400
11409
|
*
|
|
11401
11410
|
* @function height
|
|
11402
|
-
* @param {Number} height The new height to set. Undefined will remove the height allow it to auto determined.
|
|
11411
|
+
* @param {Number} height The new height to set. Undefined will remove the height and allow it to be auto determined.
|
|
11403
11412
|
* @returns {DomQuery}
|
|
11404
11413
|
* @access public
|
|
11405
11414
|
* @category DOMQuery
|
|
@@ -11420,10 +11429,10 @@ DomQuery.$ = {
|
|
|
11420
11429
|
}
|
|
11421
11430
|
},
|
|
11422
11431
|
/**
|
|
11423
|
-
* Set the width or unset the width for the first element in the list
|
|
11432
|
+
* Set the width or unset the width for the first element in the list.
|
|
11424
11433
|
*
|
|
11425
11434
|
* @function width
|
|
11426
|
-
* @param {Number} width The new width to set. Undefined will remove the width allow it to auto determined.
|
|
11435
|
+
* @param {Number} width The new width to set. Undefined will remove the width and allow it to be auto determined.
|
|
11427
11436
|
* @returns {DomQuery}
|
|
11428
11437
|
* @access public
|
|
11429
11438
|
* @category DOMQuery
|
|
@@ -11444,7 +11453,7 @@ DomQuery.$ = {
|
|
|
11444
11453
|
}
|
|
11445
11454
|
},
|
|
11446
11455
|
/**
|
|
11447
|
-
* For each element in the list, call the element's focus method if it exists
|
|
11456
|
+
* For each element in the list, call the element's focus method if it exists.
|
|
11448
11457
|
*
|
|
11449
11458
|
* @function focus
|
|
11450
11459
|
* @returns {DomQuery}
|
|
@@ -12195,12 +12204,14 @@ function callLater(callback, n) {
|
|
|
12195
12204
|
*
|
|
12196
12205
|
* @access public
|
|
12197
12206
|
* @category Events
|
|
12198
|
-
* @param {
|
|
12207
|
+
* @param {Object} [options] - Options passed through to each queue's flush method
|
|
12208
|
+
* @param {boolean} [options.unload] - signals the page is unloading; drains the send queue using sendBeacon or sync XHR for reliable last-chance delivery
|
|
12209
|
+
* @param {boolean} [options.hidden] - signals the page is being hidden; drains the send queue immediately rather than waiting for the next timer tick
|
|
12199
12210
|
* @returns {void}
|
|
12200
12211
|
* @example
|
|
12201
12212
|
* pendo.flushNow()
|
|
12202
12213
|
*/
|
|
12203
|
-
function flushNow(
|
|
12214
|
+
function flushNow(options) {
|
|
12204
12215
|
try {
|
|
12205
12216
|
_.each(queues, function (queue) {
|
|
12206
12217
|
if (queue.flush) {
|
|
@@ -12213,14 +12224,14 @@ function flushNow(force, options) {
|
|
|
12213
12224
|
}
|
|
12214
12225
|
}
|
|
12215
12226
|
/*
|
|
12216
|
-
* Queue
|
|
12217
|
-
*
|
|
12227
|
+
* Queue {flushNow} for {n} ticks of the event loop, deferring CPU-intensive
|
|
12228
|
+
* compression until the main thread is free.
|
|
12218
12229
|
*/
|
|
12219
12230
|
function flushLater(n) {
|
|
12220
|
-
return callLater(
|
|
12231
|
+
return callLater(flushNow, n);
|
|
12221
12232
|
}
|
|
12222
12233
|
/**
|
|
12223
|
-
* Force a full flush
|
|
12234
|
+
* Force a full flush on {n} ticks
|
|
12224
12235
|
*
|
|
12225
12236
|
* @access private
|
|
12226
12237
|
* @param {number} n ticks to call {flushNow} on
|
|
@@ -12484,7 +12495,7 @@ class LocalStorageEventBuffer {
|
|
|
12484
12495
|
}
|
|
12485
12496
|
read(storage) {
|
|
12486
12497
|
/**
|
|
12487
|
-
* If enabled, Pendo will write pending events to
|
|
12498
|
+
* If enabled, Pendo will write pending events to localStorage before unloading the page
|
|
12488
12499
|
* rather than attempting to send them. The events will be sent the next time the page is loaded.
|
|
12489
12500
|
*
|
|
12490
12501
|
* @name _pendo_unsentEvents
|
|
@@ -13400,6 +13411,7 @@ var makeSafe = function (method, noLogging) {
|
|
|
13400
13411
|
* @function
|
|
13401
13412
|
* @category URL
|
|
13402
13413
|
* @param {string} [url] if not provided, defaults to the current URL from the browser
|
|
13414
|
+
* @returns {boolean | undefined} true if the URL changed and a load event was sent, otherwise undefined
|
|
13403
13415
|
* @example
|
|
13404
13416
|
* pendo.pageLoad()
|
|
13405
13417
|
*/
|
|
@@ -13439,7 +13451,7 @@ pageLoad.reset = function () {
|
|
|
13439
13451
|
|
|
13440
13452
|
/**
|
|
13441
13453
|
* Returns the normalized URL sent from the backend. This won't always
|
|
13442
|
-
* match the desired output from the customer's
|
|
13454
|
+
* match the desired output from the customer's URL customizations if using the location API.
|
|
13443
13455
|
*
|
|
13444
13456
|
* @access public
|
|
13445
13457
|
* @category URL
|
|
@@ -13566,13 +13578,13 @@ function createChannelMatcher(options = {}) {
|
|
|
13566
13578
|
}
|
|
13567
13579
|
/**
|
|
13568
13580
|
* Returns an array of all guides available on the current page to the current user.
|
|
13569
|
-
* If multiple frames on a
|
|
13581
|
+
* If there are multiple frames on a page, `pendo.getActiveGuides()` will return the list of eligible
|
|
13570
13582
|
* guides across all frames. If no frames, this will be the same as `pendo.guides`.
|
|
13571
13583
|
*
|
|
13572
13584
|
* @access public
|
|
13573
13585
|
* @category Guides
|
|
13574
|
-
* @param {object} options - Options for filtering guides
|
|
13575
|
-
* @param {string} options.channel - Channel to filter guides by
|
|
13586
|
+
* @param {object} [options] - Options for filtering guides
|
|
13587
|
+
* @param {string} [options.channel] - Channel to filter guides by
|
|
13576
13588
|
* @returns {Guide[]}
|
|
13577
13589
|
* @example
|
|
13578
13590
|
* pendo.getActiveGuides() => [{ Pendo Guide Object }, ...]
|
|
@@ -13634,7 +13646,7 @@ function findGuideBy(field, value) {
|
|
|
13634
13646
|
*
|
|
13635
13647
|
* @access public
|
|
13636
13648
|
* @category Guides
|
|
13637
|
-
* @param {string}
|
|
13649
|
+
* @param {string} guideId id of the guide as a string
|
|
13638
13650
|
* @returns {Guide | null} JSON guide object or null if no guide found
|
|
13639
13651
|
* @example
|
|
13640
13652
|
* pendo.findGuideById('guide_id')
|
|
@@ -13857,6 +13869,7 @@ const internalEvents = {
|
|
|
13857
13869
|
guidesFailed: 1,
|
|
13858
13870
|
guidesLoaded: 1,
|
|
13859
13871
|
onClickCaptured: 1,
|
|
13872
|
+
onEventCaptured: 1,
|
|
13860
13873
|
segmentFlagsUpdated: 1,
|
|
13861
13874
|
segmentFlagsReady: 1,
|
|
13862
13875
|
segmentFlagsError: 1
|
|
@@ -13870,6 +13883,7 @@ const browserEvents = {
|
|
|
13870
13883
|
const supportedPublicEvents = [
|
|
13871
13884
|
'ready',
|
|
13872
13885
|
'onClickCaptured',
|
|
13886
|
+
'onEventCaptured',
|
|
13873
13887
|
'deliverablesLoaded',
|
|
13874
13888
|
'guidesFailed',
|
|
13875
13889
|
'guidesLoaded',
|
|
@@ -18229,7 +18243,7 @@ var updateVisitorOptions = function (options = {}) {
|
|
|
18229
18243
|
};
|
|
18230
18244
|
};
|
|
18231
18245
|
/**
|
|
18232
|
-
* Updates metadata object for the Pendo Web SDK. Can include visitor and/or account updates, along
|
|
18246
|
+
* Updates the metadata object for the Pendo Web SDK. Can include visitor and/or account updates, along
|
|
18233
18247
|
* with customer-defined metadata values. Changes to identity information will potentially fire
|
|
18234
18248
|
* identity and metadata events, in turn evaluating guide eligibility for the new user and displaying
|
|
18235
18249
|
* any matching guides automatically.
|
|
@@ -18247,11 +18261,11 @@ var updateOptions = makeSafe(function (options) {
|
|
|
18247
18261
|
});
|
|
18248
18262
|
/**
|
|
18249
18263
|
* This function accepts either a string for just the visitor id or it accepts an Object that will contain at least
|
|
18250
|
-
* a visitor object with at least an id field.
|
|
18251
|
-
* visitor object. Also,
|
|
18252
|
-
* also contain other account
|
|
18264
|
+
* a visitor object with at least an id field. It may also contain other visitor-related Key/Value pairs in the
|
|
18265
|
+
* visitor object. Also, the options object may contain an account object that will contain at least an id field. It may
|
|
18266
|
+
* also contain other account-related Key/Value pairs. This will potentially send an identify event and a metadata event.
|
|
18253
18267
|
*
|
|
18254
|
-
* Identifying a visitor will send an event to Pendo and begin loading eligible guides
|
|
18268
|
+
* Identifying a visitor will send an event to Pendo and begin loading eligible guides for the identified user. To remove
|
|
18255
18269
|
* visitor identity use `pendo.clearSession()`.
|
|
18256
18270
|
*
|
|
18257
18271
|
* @access public
|
|
@@ -20667,7 +20681,7 @@ var clearLoopTimer = function () {
|
|
|
20667
20681
|
store.dispatch('guideUpdate/stopScheduledUpdate');
|
|
20668
20682
|
};
|
|
20669
20683
|
/**
|
|
20670
|
-
*
|
|
20684
|
+
* Clears any showing guides and prevents any loaded guides from rendering.
|
|
20671
20685
|
* Loaded guides remain in memory, so calling startGuides will work just fine
|
|
20672
20686
|
* after a stopGuides call.
|
|
20673
20687
|
*
|
|
@@ -20690,7 +20704,7 @@ var stopGuides = function () {
|
|
|
20690
20704
|
};
|
|
20691
20705
|
/**
|
|
20692
20706
|
* Starts the process that loops over all currently loaded guides and
|
|
20693
|
-
* determines what to show. Checks
|
|
20707
|
+
* determines what to show. Checks multi-step guide continuation,
|
|
20694
20708
|
* auto-display guides, launcher guides, and badges.
|
|
20695
20709
|
*
|
|
20696
20710
|
* @access public
|
|
@@ -21678,11 +21692,7 @@ var handle_event = function (evt) {
|
|
|
21678
21692
|
}
|
|
21679
21693
|
if (data.ignore)
|
|
21680
21694
|
return;
|
|
21681
|
-
|
|
21682
|
-
if (type === 'click') {
|
|
21683
|
-
eventProperties = getClickEventProperties(target);
|
|
21684
|
-
}
|
|
21685
|
-
collectEvent(type, { target: data }, undefined, undefined, eventProperties, evt);
|
|
21695
|
+
collectEvent(type, { target: data }, undefined, undefined, undefined, evt);
|
|
21686
21696
|
Events.trigger('appUsage', data, evt);
|
|
21687
21697
|
}
|
|
21688
21698
|
catch (e) {
|
|
@@ -21692,33 +21702,6 @@ var handle_event = function (evt) {
|
|
|
21692
21702
|
performanceMonitor.stopTimer(EVENT_CAPTURED_TIMER);
|
|
21693
21703
|
}
|
|
21694
21704
|
};
|
|
21695
|
-
function getClickEventProperties(target) {
|
|
21696
|
-
const eventPropertyHandler = getEventPropertyHandler(target);
|
|
21697
|
-
Events.onClickCaptured.trigger(eventPropertyHandler);
|
|
21698
|
-
const eventProperties = eventPropertyHandler.getEventProperties();
|
|
21699
|
-
// create event expects undefined
|
|
21700
|
-
if (_.isEmpty(eventProperties)) {
|
|
21701
|
-
return;
|
|
21702
|
-
}
|
|
21703
|
-
return eventProperties;
|
|
21704
|
-
}
|
|
21705
|
-
function getEventPropertyHandler(target) {
|
|
21706
|
-
const eventProperties = {};
|
|
21707
|
-
return {
|
|
21708
|
-
getEventProperties() {
|
|
21709
|
-
return eventProperties;
|
|
21710
|
-
},
|
|
21711
|
-
addEventProperty(key, value) {
|
|
21712
|
-
if (_.isString(key) && !_.isUndefined(value)) {
|
|
21713
|
-
eventProperties[key] = value;
|
|
21714
|
-
}
|
|
21715
|
-
else {
|
|
21716
|
-
log.error('Failed to add click event property');
|
|
21717
|
-
}
|
|
21718
|
-
},
|
|
21719
|
-
target
|
|
21720
|
-
};
|
|
21721
|
-
}
|
|
21722
21705
|
/*
|
|
21723
21706
|
* Adds listeners to the DOM for user events
|
|
21724
21707
|
* like click and focus.
|
|
@@ -21989,12 +21972,12 @@ function interceptPreventDefault(EventConstructor, eventList) {
|
|
|
21989
21972
|
*
|
|
21990
21973
|
* @access public
|
|
21991
21974
|
* @category Events
|
|
21992
|
-
* @param {HTMLElement} element DOM element to attach listener
|
|
21975
|
+
* @param {HTMLElement} element DOM element to attach listener to
|
|
21993
21976
|
* @param {string} evt type of DOM event
|
|
21994
21977
|
* @param {Function} fn callback function
|
|
21995
21978
|
* @param {Boolean} useCapture use capture phase instead of bubble
|
|
21996
21979
|
* @example
|
|
21997
|
-
* pendo.attachEvent(pendo.dom("h1")[0], 'click', helloWorld = () => { console.log(Hello World") });
|
|
21980
|
+
* pendo.attachEvent(pendo.dom("h1")[0], 'click', helloWorld = () => { console.log("Hello World") });
|
|
21998
21981
|
*/
|
|
21999
21982
|
function attachEvent(element, evt, fn, useCapture) {
|
|
22000
21983
|
if (!(element && evt && fn)) {
|
|
@@ -22010,12 +21993,12 @@ function attachEvent(element, evt, fn, useCapture) {
|
|
|
22010
21993
|
});
|
|
22011
21994
|
}
|
|
22012
21995
|
/**
|
|
22013
|
-
* Pendo Web SDK's version of detaching event listeners.
|
|
22014
|
-
*
|
|
21996
|
+
* Pendo Web SDK's version of detaching event listeners. The callback must be a named function; anonymous
|
|
21997
|
+
* functions cannot be removed.
|
|
22015
21998
|
*
|
|
22016
21999
|
* @access public
|
|
22017
22000
|
* @category Events
|
|
22018
|
-
* @param {HTMLElement} element DOM element to
|
|
22001
|
+
* @param {HTMLElement} element DOM element to detach listener from
|
|
22019
22002
|
* @param {string} evt type of DOM event
|
|
22020
22003
|
* @param {Function} fn callback function
|
|
22021
22004
|
* @param {Boolean} useCapture use capture phase instead of bubble
|
|
@@ -23324,7 +23307,7 @@ var controlGuideLogMessage = 'Guide was not shown because this visitor is in a c
|
|
|
23324
23307
|
/**
|
|
23325
23308
|
* @constant defaultCssUrl {String}
|
|
23326
23309
|
*
|
|
23327
|
-
* Readonly
|
|
23310
|
+
* Readonly property that provides the default CSS URL based on the customer's Apps configuration with Pendo.
|
|
23328
23311
|
*
|
|
23329
23312
|
* @access public
|
|
23330
23313
|
* @category Guides
|
|
@@ -23419,7 +23402,7 @@ var getStepIdFromElement = function (element) {
|
|
|
23419
23402
|
* In most cases, `pendo.stopGuides()` is preferred since it will stop the loop and guides will not redisplay until `pendo.startGuides()` is called.
|
|
23420
23403
|
*
|
|
23421
23404
|
* Manually hide any active Guides. An argument of an Object containing the property stayHidden set to true needs to be
|
|
23422
|
-
* provided in order for the guides
|
|
23405
|
+
* provided in order for the hidden guides to stay hidden.
|
|
23423
23406
|
*
|
|
23424
23407
|
* @param {Object} - Optional JS Object containing boolean property `stayHidden`
|
|
23425
23408
|
* @access public
|
|
@@ -23502,7 +23485,7 @@ function shouldAffectThrottling(guide, seenReason) {
|
|
|
23502
23485
|
* Hides the current guide and invokes the `guideDismissed` event. Dismissed guides will not
|
|
23503
23486
|
* be re-displayed by default unless they have a recurrence setting or can be reactivated
|
|
23504
23487
|
* with an element. They can always be redisplayed via onGuideAdvanced or onGuidePrevious.
|
|
23505
|
-
|
|
23488
|
+
*
|
|
23506
23489
|
* @access public
|
|
23507
23490
|
* @category Guides
|
|
23508
23491
|
* @example
|
|
@@ -23566,7 +23549,7 @@ var onGuideDismissed = function (evt, step) {
|
|
|
23566
23549
|
};
|
|
23567
23550
|
/**
|
|
23568
23551
|
* Snoozes the current guide. If another guide is eligible to be shown automatically, it will show after snooze.
|
|
23569
|
-
*
|
|
23552
|
+
* The guide will redisplay after one day by default, or a custom `snoozeDuration` can be set in milliseconds as the third argument.
|
|
23570
23553
|
*
|
|
23571
23554
|
* @access public
|
|
23572
23555
|
* @category Guides
|
|
@@ -23681,7 +23664,7 @@ var goToStep = function (evt) {
|
|
|
23681
23664
|
};
|
|
23682
23665
|
/**
|
|
23683
23666
|
* Proceeds to the next step in a multi-step guide and sends a `guideAdvanced` event.
|
|
23684
|
-
* Can
|
|
23667
|
+
* Can advance multiple steps or beyond a specific step by passing optional parameters.
|
|
23685
23668
|
* Lastly, sends a `guideSeen` event for the resulting displayed step.
|
|
23686
23669
|
*
|
|
23687
23670
|
* @access public
|
|
@@ -24243,7 +24226,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24243
24226
|
};
|
|
24244
24227
|
/**
|
|
24245
24228
|
* Returns the normalized URL sent from the backend with the guides payload. This won't always
|
|
24246
|
-
* match the desired output from the customer's
|
|
24229
|
+
* match the desired output from the customer's URL customizations if using the location API.
|
|
24247
24230
|
*
|
|
24248
24231
|
* @access public
|
|
24249
24232
|
* @alias getCurrentUrl
|
|
@@ -24255,6 +24238,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24255
24238
|
* pendo.normalizedUrl
|
|
24256
24239
|
* @example
|
|
24257
24240
|
* pendo.getCurrentUrl()
|
|
24241
|
+
*/
|
|
24258
24242
|
/**
|
|
24259
24243
|
* Activates the Guide for the given name, if loaded. If it is not in the payload,
|
|
24260
24244
|
* this function will return false.
|
|
@@ -24262,7 +24246,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24262
24246
|
* @access public
|
|
24263
24247
|
* @category Guides
|
|
24264
24248
|
* @param {string} name name of the guide to display
|
|
24265
|
-
* @param {string} reason optional reason for the display
|
|
24249
|
+
* @param {string} [reason] optional reason for the display
|
|
24266
24250
|
* @example
|
|
24267
24251
|
* pendo.showGuideByName('guide_name')
|
|
24268
24252
|
*/
|
|
@@ -24284,7 +24268,7 @@ var showGuideByName = function (name, reason) {
|
|
|
24284
24268
|
* @access public
|
|
24285
24269
|
* @category Guides
|
|
24286
24270
|
* @param {string} id id of the guide to display
|
|
24287
|
-
* @param {string} reason optional reason for the display
|
|
24271
|
+
* @param {string} [reason] optional reason for the display
|
|
24288
24272
|
* @example
|
|
24289
24273
|
* pendo.showGuideById('guide_id')
|
|
24290
24274
|
*/
|
|
@@ -24311,7 +24295,7 @@ var resetPendoUI = function () {
|
|
|
24311
24295
|
*
|
|
24312
24296
|
* @access public
|
|
24313
24297
|
* @name doNotProcess
|
|
24314
|
-
* @type {
|
|
24298
|
+
* @type {boolean}
|
|
24315
24299
|
* @category Events
|
|
24316
24300
|
* @example
|
|
24317
24301
|
* pendo.doNotProcess => true
|
|
@@ -24536,8 +24520,8 @@ function shouldLoadGuides(visitorId, callback) {
|
|
|
24536
24520
|
return true;
|
|
24537
24521
|
}
|
|
24538
24522
|
/**
|
|
24539
|
-
* Manually load guides for current visitor and URL. This is typically handled automatically by the web SDK
|
|
24540
|
-
* whenever the host Application changes its URL. In rare circumstances, a host Application may
|
|
24523
|
+
* Manually load guides for the current visitor and URL. This is typically handled automatically by the web SDK
|
|
24524
|
+
* whenever the host Application changes its URL. In rare circumstances, a host Application may choose to
|
|
24541
24525
|
* force the load of Guides programmatically. One reason may be in order to get any guides designed for a visitor
|
|
24542
24526
|
* immediately after using a specific part of the Application that doesn't cause a URL change.
|
|
24543
24527
|
*
|
|
@@ -24839,7 +24823,7 @@ function securityPolicyViolationFn(evt) {
|
|
|
24839
24823
|
}
|
|
24840
24824
|
let guideCache;
|
|
24841
24825
|
/**
|
|
24842
|
-
* Resets and starts guide loop
|
|
24826
|
+
* Resets and starts the guide loop.
|
|
24843
24827
|
*
|
|
24844
24828
|
* @access public
|
|
24845
24829
|
* @category Guides
|
|
@@ -24945,7 +24929,7 @@ var initGuides = function (observer) {
|
|
|
24945
24929
|
*/
|
|
24946
24930
|
agentStorage.registry.addLocal(THROTTLING_STATE.SNOOZED);
|
|
24947
24931
|
/**
|
|
24948
|
-
* Used to determine if guides have been blocked
|
|
24932
|
+
* Used to determine if guides have been blocked by the user, an ad blocker, or a failed guide request.
|
|
24949
24933
|
* This will prevent additional guide requests and display attempts, to optimize page performance and
|
|
24950
24934
|
* user experience in cases where guides cannot be loaded.
|
|
24951
24935
|
*
|
|
@@ -24971,7 +24955,7 @@ var initGuides = function (observer) {
|
|
|
24971
24955
|
};
|
|
24972
24956
|
};
|
|
24973
24957
|
/**
|
|
24974
|
-
* Returns true or false
|
|
24958
|
+
* Returns true or false depending on whether the client has disabled guides in the snippet or via a command.
|
|
24975
24959
|
*
|
|
24976
24960
|
* @access public
|
|
24977
24961
|
* @category Guides
|
|
@@ -24983,7 +24967,7 @@ var areGuidesDisabled = function () {
|
|
|
24983
24967
|
return ConfigReader.get('guides.disabled', false) || !pendoCore;
|
|
24984
24968
|
};
|
|
24985
24969
|
/**
|
|
24986
|
-
* Returns true or false
|
|
24970
|
+
* Returns true or false depending on whether the client has delayed guides in the snippet or via a command.
|
|
24987
24971
|
*
|
|
24988
24972
|
* @access public
|
|
24989
24973
|
* @category Guides
|
|
@@ -26439,7 +26423,7 @@ function insertOriginContentHash(originalHash, url, extensionStr, sha256Hash) {
|
|
|
26439
26423
|
}
|
|
26440
26424
|
|
|
26441
26425
|
/**
|
|
26442
|
-
* Formerly `apiKey`.
|
|
26426
|
+
* Formerly `apiKey`. The public app ID associated with the current Pendo installation as a string.
|
|
26443
26427
|
*
|
|
26444
26428
|
* @access public
|
|
26445
26429
|
* @name publicAppId
|
|
@@ -26449,7 +26433,7 @@ function insertOriginContentHash(originalHash, url, extensionStr, sha256Hash) {
|
|
|
26449
26433
|
* pendo.publicAppId => 'PUBLIC_APP_ID'
|
|
26450
26434
|
*/
|
|
26451
26435
|
/**
|
|
26452
|
-
* Formerly `additionalApiKeys`.
|
|
26436
|
+
* Formerly `additionalApiKeys`. An array of additional app IDs that are set in the config. If no primary app ID is set,
|
|
26453
26437
|
* the first in this array will be assigned to `pendo.publicAppId`.
|
|
26454
26438
|
*
|
|
26455
26439
|
* @access public
|
|
@@ -27218,7 +27202,7 @@ var P2AutoLaunch = (function () {
|
|
|
27218
27202
|
function launchDesignerOrPreview(options) {
|
|
27219
27203
|
/**
|
|
27220
27204
|
* Application state while viewing a guide in preview mode. Used while preview mode is active
|
|
27221
|
-
* to track step, status, etc
|
|
27205
|
+
* to track step, status, etc., and cleared when preview mode is exited.
|
|
27222
27206
|
*
|
|
27223
27207
|
* @name pendo-preview
|
|
27224
27208
|
* @category Cookies/localStorage
|
|
@@ -27228,7 +27212,7 @@ function launchDesignerOrPreview(options) {
|
|
|
27228
27212
|
agentStorage.registry.addLocal(pendoPreview$1);
|
|
27229
27213
|
/**
|
|
27230
27214
|
* Application state while previewing a guide from the designer. Used while designer preview is active
|
|
27231
|
-
* to track step, status, etc
|
|
27215
|
+
* to track step, status, etc., and cleared when designer preview is exited.
|
|
27232
27216
|
*
|
|
27233
27217
|
* @name current-guide-preview
|
|
27234
27218
|
* @category Cookies/localStorage
|
|
@@ -28443,8 +28427,6 @@ const PluginAPI = {
|
|
|
28443
28427
|
frames: {
|
|
28444
28428
|
getChannel: () => channel
|
|
28445
28429
|
},
|
|
28446
|
-
getAssetHost,
|
|
28447
|
-
getAssetUrl,
|
|
28448
28430
|
getEventable: () => Eventable.call({}),
|
|
28449
28431
|
getScreenPosition,
|
|
28450
28432
|
GlobalRuntime: {
|
|
@@ -28466,6 +28448,9 @@ const PluginAPI = {
|
|
|
28466
28448
|
getElementForGuideStep
|
|
28467
28449
|
},
|
|
28468
28450
|
hosts: {
|
|
28451
|
+
getAssetHost,
|
|
28452
|
+
getAssetUrl,
|
|
28453
|
+
getDataHost,
|
|
28469
28454
|
SERVER
|
|
28470
28455
|
},
|
|
28471
28456
|
NodeSerializer,
|
|
@@ -28782,7 +28767,7 @@ var ResourceCenterActivity = (function () {
|
|
|
28782
28767
|
})();
|
|
28783
28768
|
|
|
28784
28769
|
/**
|
|
28785
|
-
* Returns boolean representing whether the Pendo Web SDK is fully loaded and has an API key.
|
|
28770
|
+
* Returns a boolean representing whether the Pendo Web SDK is fully loaded and has an API key.
|
|
28786
28771
|
*
|
|
28787
28772
|
* @access public
|
|
28788
28773
|
* @category Core
|
|
@@ -28997,7 +28982,7 @@ const initializeImmediately = 'initializeImmediately';
|
|
|
28997
28982
|
* @function
|
|
28998
28983
|
* @category Core
|
|
28999
28984
|
* @name initialize
|
|
29000
|
-
* @param {object} options identity metadata and configuration to initialize web SDK
|
|
28985
|
+
* @param {object} options identity metadata and configuration to initialize the web SDK
|
|
29001
28986
|
* @see {@link https://support.pendo.io/hc/en-us/articles/360046272771-Developer-s-guide-to-installing-Pendo#what-installation-involves-0-2 | Pendo Installation}
|
|
29002
28987
|
* @example
|
|
29003
28988
|
* pendo.initialize({
|
|
@@ -29100,7 +29085,7 @@ function initialize(options) {
|
|
|
29100
29085
|
teardownFns.push(() => observer.teardown());
|
|
29101
29086
|
if (pendoCore) {
|
|
29102
29087
|
/**
|
|
29103
|
-
* Current visitor id for
|
|
29088
|
+
* Current visitor id for the Pendo installation, either anonymous or identified. Used to determine
|
|
29104
29089
|
* a visitor's guide experience, settings, and associated data.
|
|
29105
29090
|
*
|
|
29106
29091
|
* @name _pendo_visitorId
|
|
@@ -29110,7 +29095,7 @@ function initialize(options) {
|
|
|
29110
29095
|
*/
|
|
29111
29096
|
agentStorage.registry.addLocal(VISITOR_ID_KEY);
|
|
29112
29097
|
/**
|
|
29113
|
-
* Often an anonymous visitor id that is replaced by a logged
|
|
29098
|
+
* Often an anonymous visitor id that is replaced by a logged-in user.
|
|
29114
29099
|
*
|
|
29115
29100
|
* @name _pendo_oldVisitorId
|
|
29116
29101
|
* @category Cookies/localStorage
|
|
@@ -29119,7 +29104,7 @@ function initialize(options) {
|
|
|
29119
29104
|
*/
|
|
29120
29105
|
agentStorage.registry.addLocal(OLD_VISITOR_ID_KEY);
|
|
29121
29106
|
/**
|
|
29122
|
-
* The current account id for
|
|
29107
|
+
* The current account id for the Pendo installation provided in the `pendo.initialize()` call.
|
|
29123
29108
|
*
|
|
29124
29109
|
* @name _pendo_accountId
|
|
29125
29110
|
* @category Cookies/localStorage
|
|
@@ -29155,12 +29140,12 @@ function initialize(options) {
|
|
|
29155
29140
|
teardownFns.push(performanceMonitor.initialize());
|
|
29156
29141
|
}
|
|
29157
29142
|
const flushOnAppHidden = () => {
|
|
29158
|
-
flushNow(
|
|
29143
|
+
flushNow({ hidden: true });
|
|
29159
29144
|
};
|
|
29160
29145
|
Events.appHidden.on(flushOnAppHidden);
|
|
29161
29146
|
teardownFns.push(() => Events.appHidden.off(flushOnAppHidden));
|
|
29162
29147
|
const flushOnAppUnloaded = () => {
|
|
29163
|
-
flushNow(
|
|
29148
|
+
flushNow({ unload: true });
|
|
29164
29149
|
if (localStorageUnloadEnabled) {
|
|
29165
29150
|
localStorageEventBuffer.write(agentStorage);
|
|
29166
29151
|
}
|
|
@@ -29776,13 +29761,20 @@ var BuildingBlockGuides = (function () {
|
|
|
29776
29761
|
detachEvent(targetElement, 'focus', targetElementFocusCallback);
|
|
29777
29762
|
});
|
|
29778
29763
|
}
|
|
29764
|
+
function getTargetElementForStep(step) {
|
|
29765
|
+
if (step.element && step.element !== getBody()) {
|
|
29766
|
+
return step.element;
|
|
29767
|
+
}
|
|
29768
|
+
return null;
|
|
29769
|
+
}
|
|
29779
29770
|
function trapFocusStep(step, guideContainer) {
|
|
29780
|
-
var
|
|
29781
|
-
|
|
29771
|
+
var guideContainerElement = guideContainer.find('#pendo-guide-container');
|
|
29772
|
+
var targetElement = _.get(step, 'attributes.blockOutUI.enabled') && getTargetElementForStep(step);
|
|
29773
|
+
trapFocus(guideContainerElement, targetElement);
|
|
29782
29774
|
}
|
|
29783
29775
|
function getSelectedPollElementForFocus(focusableChildren, bumperElement) {
|
|
29784
29776
|
let elementToFocus;
|
|
29785
|
-
if (bumperElement.getAttribute('type') === 'radio') {
|
|
29777
|
+
if (bumperElement.getAttribute('type') === 'radio' && bumperElement.getAttribute('data-pendo-poll-id')) {
|
|
29786
29778
|
const pollId = bumperElement.getAttribute('data-pendo-poll-id');
|
|
29787
29779
|
elementToFocus = _.find(focusableChildren, function (child) {
|
|
29788
29780
|
const childPollId = child.getAttribute('data-pendo-poll-id');
|
|
@@ -29791,8 +29783,42 @@ var BuildingBlockGuides = (function () {
|
|
|
29791
29783
|
}
|
|
29792
29784
|
return elementToFocus || bumperElement;
|
|
29793
29785
|
}
|
|
29794
|
-
function
|
|
29795
|
-
|
|
29786
|
+
function collectTargetFocusables(targetElement) {
|
|
29787
|
+
if (!targetElement)
|
|
29788
|
+
return [];
|
|
29789
|
+
var focusables = _.toArray(targetElement.querySelectorAll(FOCUSABLE_SELECTORS));
|
|
29790
|
+
if (targetElement.matches(FOCUSABLE_SELECTORS)) {
|
|
29791
|
+
focusables.unshift(targetElement);
|
|
29792
|
+
}
|
|
29793
|
+
return focusables;
|
|
29794
|
+
}
|
|
29795
|
+
function createTargetBumper(className) {
|
|
29796
|
+
var bumper = document.createElement('div');
|
|
29797
|
+
bumper.setAttribute('tabIndex', 0);
|
|
29798
|
+
bumper.setAttribute('class', className);
|
|
29799
|
+
bumper.setAttribute('aria-hidden', 'true');
|
|
29800
|
+
bumper.style.cssText = 'position:absolute !important;width:0 !important;height:0 !important;overflow:hidden !important;outline:none !important;border:none !important;padding:0 !important;margin:0 !important;';
|
|
29801
|
+
return bumper;
|
|
29802
|
+
}
|
|
29803
|
+
function insertTargetBumpers(targetElement) {
|
|
29804
|
+
if (!targetElement || !targetElement.parentNode)
|
|
29805
|
+
return null;
|
|
29806
|
+
var before = createTargetBumper('pendo-before-target-focus-bumper');
|
|
29807
|
+
var after = createTargetBumper('pendo-after-target-focus-bumper');
|
|
29808
|
+
targetElement.parentNode.insertBefore(before, targetElement);
|
|
29809
|
+
targetElement.parentNode.insertBefore(after, targetElement.nextSibling);
|
|
29810
|
+
return { before, after };
|
|
29811
|
+
}
|
|
29812
|
+
function removeTargetBumpers(targetBumpers) {
|
|
29813
|
+
if (!targetBumpers)
|
|
29814
|
+
return;
|
|
29815
|
+
_.each([targetBumpers.before, targetBumpers.after], function (bumper) {
|
|
29816
|
+
if (bumper && bumper.parentNode)
|
|
29817
|
+
bumper.parentNode.removeChild(bumper);
|
|
29818
|
+
});
|
|
29819
|
+
}
|
|
29820
|
+
function trapFocus(guideContainerElement, targetElement) {
|
|
29821
|
+
var containerNode = guideContainerElement[0];
|
|
29796
29822
|
if (!containerNode) {
|
|
29797
29823
|
return;
|
|
29798
29824
|
}
|
|
@@ -29812,43 +29838,75 @@ var BuildingBlockGuides = (function () {
|
|
|
29812
29838
|
// some quirks
|
|
29813
29839
|
'iframe'
|
|
29814
29840
|
].join(', ');
|
|
29815
|
-
var focusableChildren = _.toArray(
|
|
29841
|
+
var focusableChildren = _.toArray(guideContainerElement.find(selectors));
|
|
29816
29842
|
if (!focusableChildren.length) {
|
|
29817
29843
|
return;
|
|
29818
29844
|
}
|
|
29819
29845
|
var firstFocusableEl = focusableChildren[0];
|
|
29820
29846
|
var lastFocusableEl = focusableChildren[focusableChildren.length - 1];
|
|
29821
29847
|
// insert bumpers after the above selectors run for content
|
|
29822
|
-
var bumpers = insertTrapFocusBumpers(
|
|
29848
|
+
var bumpers = insertTrapFocusBumpers(guideContainerElement);
|
|
29823
29849
|
var startFocusBumper = bumpers[0];
|
|
29824
29850
|
var endFocusBumper = bumpers[1];
|
|
29851
|
+
var targetFocusables = collectTargetFocusables(targetElement);
|
|
29852
|
+
var firstTargetFocusable = targetFocusables[0];
|
|
29853
|
+
var lastTargetFocusable = targetFocusables[targetFocusables.length - 1];
|
|
29854
|
+
// Insert bumpers as siblings of the target so we can catch focus crossings even when focus moves through a
|
|
29855
|
+
// cross-origin iframe inside the target (our keydown listener can't see events inside the iframe, but it can
|
|
29856
|
+
// see focus landing on a bumper in the parent document afterwards).
|
|
29857
|
+
var targetBumpers = targetFocusables.length ? insertTargetBumpers(targetElement) : null;
|
|
29858
|
+
var beforeTargetBumper = targetBumpers && targetBumpers.before;
|
|
29859
|
+
var afterTargetBumper = targetBumpers && targetBumpers.after;
|
|
29860
|
+
var targetRoot = targetElement && dom.getRootNode(targetElement);
|
|
29861
|
+
var wrapForward = firstTargetFocusable || firstFocusableEl;
|
|
29862
|
+
var wrapBackward = lastTargetFocusable || lastFocusableEl;
|
|
29825
29863
|
var trapFocusCallback = function (e) {
|
|
29826
|
-
|
|
29827
|
-
var isShiftPressed = e.shiftKey;
|
|
29828
|
-
if (!isTabPressed) {
|
|
29864
|
+
if (!isTabEvent(e)) {
|
|
29829
29865
|
return;
|
|
29830
29866
|
}
|
|
29867
|
+
const isShiftPressed = e.shiftKey;
|
|
29868
|
+
const isKeydown = e.type === 'keydown';
|
|
29831
29869
|
// Check if focus is on the body (clicked on the backdrop), the guide container (starts there when guide opens), or on the focus bumpers
|
|
29832
29870
|
const activeElement = dom.getRootNode(containerNode).activeElement;
|
|
29833
29871
|
const containerActive = activeElement === containerNode;
|
|
29834
29872
|
const bodyActive = document.activeElement === document.body; // if the guide is in a shadow root but you click on the backdrop, the active element is the body of the main document
|
|
29835
|
-
|
|
29873
|
+
const startBumperActive = activeElement === startFocusBumper;
|
|
29874
|
+
const endBumperActive = activeElement === endFocusBumper;
|
|
29875
|
+
const targetActiveElement = targetRoot && targetRoot.activeElement;
|
|
29876
|
+
const beforeTargetBumperActive = !!beforeTargetBumper && targetActiveElement === beforeTargetBumper;
|
|
29877
|
+
const afterTargetBumperActive = !!afterTargetBumper && targetActiveElement === afterTargetBumper;
|
|
29878
|
+
const onLastTargetFocusable = isKeydown && !!lastTargetFocusable && targetActiveElement === lastTargetFocusable;
|
|
29879
|
+
const onFirstTargetFocusable = isKeydown && !!firstTargetFocusable && targetActiveElement === firstTargetFocusable;
|
|
29880
|
+
let elementToFocus;
|
|
29836
29881
|
if (isShiftPressed) {
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
elementToFocus
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
|
|
29882
|
+
if (onFirstTargetFocusable)
|
|
29883
|
+
elementToFocus = lastFocusableEl;
|
|
29884
|
+
else if (beforeTargetBumperActive)
|
|
29885
|
+
elementToFocus = lastFocusableEl;
|
|
29886
|
+
else if (afterTargetBumperActive)
|
|
29887
|
+
elementToFocus = lastTargetFocusable;
|
|
29888
|
+
else if (startBumperActive || containerActive || bodyActive)
|
|
29889
|
+
elementToFocus = wrapBackward;
|
|
29844
29890
|
}
|
|
29845
29891
|
else {
|
|
29846
|
-
|
|
29847
|
-
|
|
29848
|
-
|
|
29849
|
-
elementToFocus
|
|
29850
|
-
|
|
29851
|
-
|
|
29892
|
+
if (onLastTargetFocusable)
|
|
29893
|
+
elementToFocus = firstFocusableEl;
|
|
29894
|
+
else if (afterTargetBumperActive)
|
|
29895
|
+
elementToFocus = firstFocusableEl;
|
|
29896
|
+
else if (beforeTargetBumperActive)
|
|
29897
|
+
elementToFocus = firstTargetFocusable;
|
|
29898
|
+
else if (endBumperActive)
|
|
29899
|
+
elementToFocus = wrapForward;
|
|
29900
|
+
else if (containerActive || bodyActive)
|
|
29901
|
+
elementToFocus = firstFocusableEl;
|
|
29902
|
+
}
|
|
29903
|
+
if (elementToFocus) {
|
|
29904
|
+
const resolved = getSelectedPollElementForFocus(focusableChildren, elementToFocus);
|
|
29905
|
+
resolved.focus();
|
|
29906
|
+
if (dom.getRootNode(resolved).activeElement !== resolved) {
|
|
29907
|
+
(isShiftPressed ? lastFocusableEl : firstFocusableEl).focus();
|
|
29908
|
+
}
|
|
29909
|
+
e.preventDefault();
|
|
29852
29910
|
}
|
|
29853
29911
|
};
|
|
29854
29912
|
// attaching to both events helps some edge cases such as breakout by long-pressing the tab
|
|
@@ -29857,6 +29915,7 @@ var BuildingBlockGuides = (function () {
|
|
|
29857
29915
|
Events.one('unmounted', () => {
|
|
29858
29916
|
detachEvent(document, 'keyup', trapFocusCallback);
|
|
29859
29917
|
detachEvent(document, 'keydown', trapFocusCallback);
|
|
29918
|
+
removeTargetBumpers(targetBumpers);
|
|
29860
29919
|
});
|
|
29861
29920
|
}
|
|
29862
29921
|
// bumpers are divs with a tabindex to allow them to be focused, but which should immediately
|
|
@@ -30076,7 +30135,7 @@ var shouldWeLog = function (contexts) {
|
|
|
30076
30135
|
return (!!logOverride || !!isDebuggingEnabled());
|
|
30077
30136
|
};
|
|
30078
30137
|
/**
|
|
30079
|
-
* Logs
|
|
30138
|
+
* Logs output to the console as the [Pendo Web SDK].
|
|
30080
30139
|
*
|
|
30081
30140
|
* @access public
|
|
30082
30141
|
* @category Debugging
|
|
@@ -30194,12 +30253,12 @@ function collectEventHelper({ type, name, props, eventProperties }) {
|
|
|
30194
30253
|
collectEvent(type, correctedProps, url, name, correctedEventProperties);
|
|
30195
30254
|
}
|
|
30196
30255
|
/**
|
|
30197
|
-
* Method to manually track events. Requires a non-empty name string to collect event.
|
|
30256
|
+
* Method to manually track events. Requires a non-empty name string to collect the event.
|
|
30198
30257
|
*
|
|
30199
30258
|
* @access public
|
|
30200
30259
|
* @category Events
|
|
30201
30260
|
* @param {string} name name of the collected event
|
|
30202
|
-
* @param {Object} [props] optional properties object to collect with
|
|
30261
|
+
* @param {Object} [props] optional properties object to collect with the event
|
|
30203
30262
|
* @param {Object} [eventProperties] optional key-value map stored on the event as top-level event properties
|
|
30204
30263
|
* @example
|
|
30205
30264
|
* pendo.track('scroll')
|
|
@@ -30216,7 +30275,7 @@ const privacyFilterCache = new Map();
|
|
|
30216
30275
|
*
|
|
30217
30276
|
* @access public
|
|
30218
30277
|
* @category Events
|
|
30219
|
-
* @param {string} type type of the collected agentic event
|
|
30278
|
+
* @param {string} type type of the collected agentic event (e.g. 'prompt', 'agent_response', 'user_reaction')
|
|
30220
30279
|
* @param {Object} props event-specific properties object
|
|
30221
30280
|
* @param {Object} [eventProperties] optional key-value map stored on the event as top-level event properties (same as pendo.track)
|
|
30222
30281
|
* @example
|
|
@@ -30292,7 +30351,7 @@ function getCachedRegex(filterPattern) {
|
|
|
30292
30351
|
}
|
|
30293
30352
|
|
|
30294
30353
|
/**
|
|
30295
|
-
* Checks visitor and account metadata in the current Pendo installation. Either logs to console
|
|
30354
|
+
* Checks visitor and account metadata in the current Pendo installation. Either logs to the console
|
|
30296
30355
|
* or returns an array with the results of validation.
|
|
30297
30356
|
*
|
|
30298
30357
|
* @access public
|
|
@@ -30554,7 +30613,7 @@ var validateBuiltInGlobals = function (skipLogging) {
|
|
|
30554
30613
|
}
|
|
30555
30614
|
};
|
|
30556
30615
|
/**
|
|
30557
|
-
* Checks current URL of the browser for customized or sanitized
|
|
30616
|
+
* Checks the current URL of the browser for strings customized or sanitized by the application.
|
|
30558
30617
|
*
|
|
30559
30618
|
* @access public
|
|
30560
30619
|
* @category Validation
|
|
@@ -30643,6 +30702,7 @@ const validatePluginsAndExtensions = (skipLogging) => {
|
|
|
30643
30702
|
*
|
|
30644
30703
|
* @access public
|
|
30645
30704
|
* @category Validation
|
|
30705
|
+
* @param {boolean} [skipLogging] does not log output to console if true, returning the environment object instead
|
|
30646
30706
|
* @example
|
|
30647
30707
|
* pendo.validateEnvironment()
|
|
30648
30708
|
*/
|
|
@@ -31131,7 +31191,7 @@ const DEFAULT_GUIDE_SEEN_TIMEOUT_LENGTH = 10000;
|
|
|
31131
31191
|
* @constant guideSeenTimeoutLength {number}
|
|
31132
31192
|
*
|
|
31133
31193
|
* Readonly number that indicates how long a guide will try to show before sending an error.
|
|
31134
|
-
* Defaults to 10 seconds.
|
|
31194
|
+
* Defaults to 10 seconds (10000 ms).
|
|
31135
31195
|
*
|
|
31136
31196
|
* @access public
|
|
31137
31197
|
* @category Guides
|
|
@@ -31249,9 +31309,7 @@ function exportPublicApi(pendo) {
|
|
|
31249
31309
|
pendo.VERSION = VERSION;
|
|
31250
31310
|
pendo.LOADER = LOADER;
|
|
31251
31311
|
// cache.js
|
|
31252
|
-
pendo.flushNow = exportPendoCoreOnly(
|
|
31253
|
-
return flushNow(true, options);
|
|
31254
|
-
});
|
|
31312
|
+
pendo.flushNow = exportPendoCoreOnly(flushNow);
|
|
31255
31313
|
pendo.teardown = makeSafe(teardown);
|
|
31256
31314
|
// guides.js
|
|
31257
31315
|
pendo.initGuides = exportPendoCoreOnly(initGuides);
|
|
@@ -31394,7 +31452,7 @@ function exportPublicApi(pendo) {
|
|
|
31394
31452
|
pendo.receiveDomStructureJson = exportPendoCoreOnly(ContentLoader.receiveDomStructureJson);
|
|
31395
31453
|
pendo.addExtension = addExtension;
|
|
31396
31454
|
/**
|
|
31397
|
-
* Retrieve a configuration value from the web
|
|
31455
|
+
* Retrieve a configuration value from the web SDK's config. Available configuration keys can be
|
|
31398
31456
|
* found in the [configuration section](/config).
|
|
31399
31457
|
*
|
|
31400
31458
|
* @access public
|
|
@@ -31644,7 +31702,7 @@ function Guide() {
|
|
|
31644
31702
|
return true;
|
|
31645
31703
|
};
|
|
31646
31704
|
/**
|
|
31647
|
-
* Returns a Boolean value to indicate if the Guide can
|
|
31705
|
+
* Returns a Boolean value to indicate if the Guide can show at this time.
|
|
31648
31706
|
*
|
|
31649
31707
|
* @access public
|
|
31650
31708
|
* @category Guides
|
|
@@ -31677,13 +31735,13 @@ function Guide() {
|
|
|
31677
31735
|
return promise;
|
|
31678
31736
|
};
|
|
31679
31737
|
/**
|
|
31680
|
-
|
|
31681
|
-
|
|
31682
|
-
|
|
31683
|
-
|
|
31684
|
-
|
|
31685
|
-
|
|
31686
|
-
|
|
31738
|
+
* Attempt to show the Guide. The Guide will still honor any constraints like
|
|
31739
|
+
* requiring a DOM element to be present if it was configured for that.
|
|
31740
|
+
*
|
|
31741
|
+
* @access public
|
|
31742
|
+
* @category Guides
|
|
31743
|
+
* @returns {void}
|
|
31744
|
+
*/
|
|
31687
31745
|
this.show = function (reason) {
|
|
31688
31746
|
var guide = this;
|
|
31689
31747
|
return joinShowPromises(_.map(guide.steps, function (step) {
|
|
@@ -31697,7 +31755,7 @@ function Guide() {
|
|
|
31697
31755
|
*
|
|
31698
31756
|
* @access public
|
|
31699
31757
|
* @category Guides
|
|
31700
|
-
* @returns {
|
|
31758
|
+
* @returns {void}
|
|
31701
31759
|
* @example
|
|
31702
31760
|
* guide.hide({stayHidden: true});
|
|
31703
31761
|
*/
|
|
@@ -32794,7 +32852,7 @@ function GuideStep(guide) {
|
|
|
32794
32852
|
removeStyleElementsForIdFromHead(this.id);
|
|
32795
32853
|
};
|
|
32796
32854
|
/**
|
|
32797
|
-
*
|
|
32855
|
+
* Attempts to show the step.
|
|
32798
32856
|
*
|
|
32799
32857
|
* @access public
|
|
32800
32858
|
* @category Guides
|
|
@@ -32975,7 +33033,7 @@ function GuideStep(guide) {
|
|
|
32975
33033
|
/**
|
|
32976
33034
|
* Hides the Step if shown. Use an argument of an Object containing a
|
|
32977
33035
|
* key of `stayHidden` set to `true` to make sure to keep the Step hidden
|
|
32978
|
-
* if the Guide it belongs to is designated as
|
|
33036
|
+
* if the Guide it belongs to is designated as automatically shown.
|
|
32979
33037
|
*
|
|
32980
33038
|
* @access public
|
|
32981
33039
|
* @category Guides
|
|
@@ -33026,7 +33084,7 @@ function GuideStep(guide) {
|
|
|
33026
33084
|
*
|
|
33027
33085
|
* @access public
|
|
33028
33086
|
* @category Guides
|
|
33029
|
-
* @returns {
|
|
33087
|
+
* @returns {void}
|
|
33030
33088
|
*/
|
|
33031
33089
|
this.dismiss = function () {
|
|
33032
33090
|
if (this.seenState === 'dismissed' && !this.isRendered())
|
|
@@ -33052,9 +33110,9 @@ function GuideStep(guide) {
|
|
|
33052
33110
|
* Allows for an eventListener to be created that will automatically get cleaned up when this
|
|
33053
33111
|
* Step is torn down.
|
|
33054
33112
|
*
|
|
33055
|
-
* @param element {Element} - The DOM element to attach the listener.
|
|
33113
|
+
* @param element {Element} - The DOM element to attach the listener to.
|
|
33056
33114
|
* @param type {String} - The type of event: 'click', 'mousedown', 'keypress', etc...
|
|
33057
|
-
* @param fn {function} - A function that will be called when an event
|
|
33115
|
+
* @param fn {function} - A function that will be called when an event of the specified type occurs.
|
|
33058
33116
|
*
|
|
33059
33117
|
* @access public
|
|
33060
33118
|
* @category Guides
|
|
@@ -33212,7 +33270,7 @@ class CloneDetection {
|
|
|
33212
33270
|
return;
|
|
33213
33271
|
/**
|
|
33214
33272
|
* Randomly generated ID used to detect when sessionStorage has been cloned
|
|
33215
|
-
* from another browser
|
|
33273
|
+
* from another browser tab.
|
|
33216
33274
|
*
|
|
33217
33275
|
* @name pendo_cd
|
|
33218
33276
|
* @category Cookies/sessionStorage
|
|
@@ -33329,7 +33387,7 @@ var FramesModule = (function () {
|
|
|
33329
33387
|
if (state.initialized)
|
|
33330
33388
|
return;
|
|
33331
33389
|
/**
|
|
33332
|
-
* Randomly generated string that identifies a browser
|
|
33390
|
+
* Randomly generated string that identifies a browser tab.
|
|
33333
33391
|
*
|
|
33334
33392
|
* @name pendo_tabId
|
|
33335
33393
|
* @category Cookies/sessionStorage
|
|
@@ -33338,7 +33396,7 @@ var FramesModule = (function () {
|
|
|
33338
33396
|
*/
|
|
33339
33397
|
agentStorage.registry.addSession(TAB_ID);
|
|
33340
33398
|
/**
|
|
33341
|
-
* When a browser
|
|
33399
|
+
* When a browser tab is cloned, the `pendo_tabId` is copied to the new tab.
|
|
33342
33400
|
* The Pendo Web SDK detects this, creates a new `pendo_tabId`, and stores the old
|
|
33343
33401
|
* `pendo_tabId` in `pendo_parentTabId`.
|
|
33344
33402
|
*
|
|
@@ -35417,7 +35475,7 @@ function addDebuggingFunctions() {
|
|
|
35417
35475
|
pendo$1.debugging = debugging;
|
|
35418
35476
|
}
|
|
35419
35477
|
/**
|
|
35420
|
-
* Loads Pendo Debugger and extends the global pendo object with additional functionality
|
|
35478
|
+
* Loads the Pendo Debugger and extends the global `pendo` object with additional functionality
|
|
35421
35479
|
* for debugging purposes.
|
|
35422
35480
|
*
|
|
35423
35481
|
* @access public
|
|
@@ -35444,7 +35502,7 @@ function enableDebugging(andChain) {
|
|
|
35444
35502
|
return 'debugging enabled';
|
|
35445
35503
|
}
|
|
35446
35504
|
/**
|
|
35447
|
-
* Removes Pendo Debugger extension.
|
|
35505
|
+
* Removes the Pendo Debugger extension.
|
|
35448
35506
|
*
|
|
35449
35507
|
* @access public
|
|
35450
35508
|
* @category Debugging
|
|
@@ -35523,7 +35581,7 @@ const DebuggerLauncher = (function () {
|
|
|
35523
35581
|
}
|
|
35524
35582
|
globalPendo = pendo;
|
|
35525
35583
|
/**
|
|
35526
|
-
* Returns a string indicating debugging status. Pass an optional value of true to get result as a boolean.
|
|
35584
|
+
* Returns a string indicating debugging status. Pass an optional value of true to get the result as a boolean.
|
|
35527
35585
|
*
|
|
35528
35586
|
* @access public
|
|
35529
35587
|
* @category Debugging
|
|
@@ -36101,7 +36159,7 @@ const EmbeddedGuides = (function () {
|
|
|
36101
36159
|
}
|
|
36102
36160
|
})();
|
|
36103
36161
|
/**
|
|
36104
|
-
* Returns a list of embedded guides eligible
|
|
36162
|
+
* Returns a list of embedded guides eligible for the active visitor on the active page.
|
|
36105
36163
|
*
|
|
36106
36164
|
* @access public
|
|
36107
36165
|
* @category Guides
|
|
@@ -36113,7 +36171,7 @@ function getEmbeddedGuides() {
|
|
|
36113
36171
|
return EmbeddedGuides.activeEmbeddedGuides;
|
|
36114
36172
|
}
|
|
36115
36173
|
/**
|
|
36116
|
-
* Returns a list of embedded guides that are rendered on the page
|
|
36174
|
+
* Returns a list of embedded guides that are rendered on the page.
|
|
36117
36175
|
*
|
|
36118
36176
|
* @access public
|
|
36119
36177
|
* @category Guides
|
|
@@ -39051,7 +39109,7 @@ var doesLauncherHaveGuides = function () {
|
|
|
39051
39109
|
return dom('._pendo-launcher-item_').length > 0;
|
|
39052
39110
|
};
|
|
39053
39111
|
/**
|
|
39054
|
-
* Closes Pendo Guide Center (launcher) if open on page.
|
|
39112
|
+
* Closes the Pendo Guide Center (launcher) if open on the page.
|
|
39055
39113
|
*
|
|
39056
39114
|
* @access public
|
|
39057
39115
|
* @category Classic Guides
|
|
@@ -39069,7 +39127,7 @@ var collapseLauncherList = function () {
|
|
|
39069
39127
|
}
|
|
39070
39128
|
};
|
|
39071
39129
|
/**
|
|
39072
|
-
* Opens Pendo Guide Center (launcher) if present on page.
|
|
39130
|
+
* Opens the Pendo Guide Center (launcher) if present on the page.
|
|
39073
39131
|
*
|
|
39074
39132
|
* @access public
|
|
39075
39133
|
* @category Classic Guides
|
|
@@ -39182,7 +39240,7 @@ var initLauncherPlugin = function (pendo, PluginAPI) {
|
|
|
39182
39240
|
PluginAPI.GuideLoop.addUpdatePhase(launcherProc);
|
|
39183
39241
|
registerLoadGuideJobs(loadLauncherContentHandler);
|
|
39184
39242
|
/**
|
|
39185
|
-
* Written when the classic guide center is closed. Legacy guide center only
|
|
39243
|
+
* Written when the classic guide center is closed. Legacy guide center only; not used for the resource center.
|
|
39186
39244
|
*
|
|
39187
39245
|
* @name _pendo_launcher-closed
|
|
39188
39246
|
* @category Cookies/localStorage
|
|
@@ -39387,7 +39445,7 @@ var PromoteMetadata = (function () {
|
|
|
39387
39445
|
promotedAgentMetadata = PluginAPI.ConfigReader.get(PROMOTED_AGENT_METADATA);
|
|
39388
39446
|
schemaGroup = {};
|
|
39389
39447
|
/**
|
|
39390
|
-
* Stores the historical metadata fields for the current visitor
|
|
39448
|
+
* Stores the historical metadata fields for the current visitor when enabled in an application.
|
|
39391
39449
|
* This is turned on by an admin in Pendo's Data Mappings and used to track metadata changes over time.
|
|
39392
39450
|
*
|
|
39393
39451
|
* @name _pendo___sg__
|
|
@@ -39992,6 +40050,299 @@ class DOMPrompt {
|
|
|
39992
40050
|
}
|
|
39993
40051
|
}
|
|
39994
40052
|
|
|
40053
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
40054
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
40055
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
40056
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
40057
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
40058
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
40059
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
40060
|
+
const THUMB_DOWN = 'thumbDown';
|
|
40061
|
+
const THUMB_UP = 'thumbUp';
|
|
40062
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
40063
|
+
const TURN_ATTR = 'turnAttr';
|
|
40064
|
+
const USER_MESSAGE = 'userMessage';
|
|
40065
|
+
const REQUIRED_SELECTORS = [
|
|
40066
|
+
ASSISTANT_MESSAGE,
|
|
40067
|
+
CONVERSATION_ID_URL_PATTERN,
|
|
40068
|
+
MESSAGE_ID_ATTR,
|
|
40069
|
+
STREAMING_ACTIVE,
|
|
40070
|
+
TURN_CONTAINER,
|
|
40071
|
+
TURN_ATTR,
|
|
40072
|
+
USER_MESSAGE
|
|
40073
|
+
];
|
|
40074
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
40075
|
+
class DOMConversation {
|
|
40076
|
+
// Returns the list of required selector types that are missing or empty
|
|
40077
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
40078
|
+
// valid for instantiation.
|
|
40079
|
+
static validateConfig(cssSelectors) {
|
|
40080
|
+
if (!Array.isArray(cssSelectors)) {
|
|
40081
|
+
return REQUIRED_SELECTORS.slice();
|
|
40082
|
+
}
|
|
40083
|
+
const present = new Set();
|
|
40084
|
+
for (const cfg of cssSelectors) {
|
|
40085
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
40086
|
+
continue;
|
|
40087
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
40088
|
+
try {
|
|
40089
|
+
RegExp(cfg.cssSelector);
|
|
40090
|
+
}
|
|
40091
|
+
catch (e) {
|
|
40092
|
+
continue;
|
|
40093
|
+
}
|
|
40094
|
+
}
|
|
40095
|
+
present.add(cfg.type);
|
|
40096
|
+
}
|
|
40097
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
40098
|
+
}
|
|
40099
|
+
static supportedPreset(preset) {
|
|
40100
|
+
return preset === 'chatgpt-full';
|
|
40101
|
+
}
|
|
40102
|
+
constructor(pendo, PluginAPI, id, privacyFilters, cssSelectors) {
|
|
40103
|
+
this.selectors = {};
|
|
40104
|
+
this.listeners = [];
|
|
40105
|
+
this.isActive = true;
|
|
40106
|
+
this.observers = [];
|
|
40107
|
+
this.wasStreaming = false;
|
|
40108
|
+
this.streamingEndTimer = null;
|
|
40109
|
+
this.requestNode = null;
|
|
40110
|
+
this.conversationIdRegex = null;
|
|
40111
|
+
this.lastReturnedMessageId = null;
|
|
40112
|
+
this.dom = pendo.dom;
|
|
40113
|
+
this._ = pendo._;
|
|
40114
|
+
this.api = PluginAPI;
|
|
40115
|
+
this.Sizzle = pendo.Sizzle;
|
|
40116
|
+
this.id = id;
|
|
40117
|
+
this.setFilters(privacyFilters);
|
|
40118
|
+
if (!this._.isArray(cssSelectors)) {
|
|
40119
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
40120
|
+
cssSelectors = [];
|
|
40121
|
+
}
|
|
40122
|
+
this._.each(cssSelectors, (cfg) => {
|
|
40123
|
+
if (cfg && cfg.type) {
|
|
40124
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
40125
|
+
}
|
|
40126
|
+
});
|
|
40127
|
+
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
40128
|
+
this.root = document.body;
|
|
40129
|
+
this.setupReactionListener();
|
|
40130
|
+
this.setupStreamingObserver();
|
|
40131
|
+
}
|
|
40132
|
+
setupReactionListener() {
|
|
40133
|
+
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
40134
|
+
return;
|
|
40135
|
+
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
40136
|
+
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
40137
|
+
}
|
|
40138
|
+
handleReactionClick(evt) {
|
|
40139
|
+
const target = evt.target;
|
|
40140
|
+
if (!target || target.nodeType !== 1)
|
|
40141
|
+
return;
|
|
40142
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
40143
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
40144
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
40145
|
+
if (!thumb.length)
|
|
40146
|
+
return;
|
|
40147
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
40148
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
40149
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
40150
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
40151
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
40152
|
+
const assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
40153
|
+
.find(this.findSelector(ASSISTANT_MESSAGE));
|
|
40154
|
+
this.emit('user_reaction', {
|
|
40155
|
+
agentId: this.id,
|
|
40156
|
+
messageId: this.getMessageId(assistantNode),
|
|
40157
|
+
content,
|
|
40158
|
+
privacyFilterApplied: false
|
|
40159
|
+
});
|
|
40160
|
+
}
|
|
40161
|
+
// observe the streaming indicator
|
|
40162
|
+
setupStreamingObserver() {
|
|
40163
|
+
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
40164
|
+
this.stopStreamingEndTimer();
|
|
40165
|
+
const MutationObserver = getZoneSafeMethod('MutationObserver');
|
|
40166
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
40167
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
40168
|
+
observer.observe(this.root, {
|
|
40169
|
+
childList: true,
|
|
40170
|
+
subtree: true,
|
|
40171
|
+
attributes: true,
|
|
40172
|
+
attributeFilter: attrName ? [attrName] : undefined
|
|
40173
|
+
});
|
|
40174
|
+
this.observers.push(observer);
|
|
40175
|
+
}
|
|
40176
|
+
// look for changes in the state of the streaming indicator.
|
|
40177
|
+
// streaming started -> a prompt has been submitted
|
|
40178
|
+
// streaming ended -> got a response
|
|
40179
|
+
// we don't send the prompt immediately when it's submitted because it might not have a
|
|
40180
|
+
// conversation id yet.
|
|
40181
|
+
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
40182
|
+
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
40183
|
+
// end-handling is deferred by a short settle window
|
|
40184
|
+
handleMutation() {
|
|
40185
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
40186
|
+
if (isStreaming === this.wasStreaming)
|
|
40187
|
+
return;
|
|
40188
|
+
if (isStreaming) { // started streaming
|
|
40189
|
+
if (!this.streamingEndTimer) {
|
|
40190
|
+
this.onSubmissionStart();
|
|
40191
|
+
}
|
|
40192
|
+
else {
|
|
40193
|
+
// stream restarted during the settle window (multi-phase response).
|
|
40194
|
+
// treat as a continuation of the prior request, not a new submission.
|
|
40195
|
+
// we'll handle it next time streaming stops
|
|
40196
|
+
this.stopStreamingEndTimer();
|
|
40197
|
+
}
|
|
40198
|
+
}
|
|
40199
|
+
else { // finished streaming
|
|
40200
|
+
this.startStreamingEndTimer();
|
|
40201
|
+
}
|
|
40202
|
+
this.wasStreaming = isStreaming;
|
|
40203
|
+
}
|
|
40204
|
+
onSubmissionStart() {
|
|
40205
|
+
this.requestNode = this.findLastRequestNode();
|
|
40206
|
+
if (this.requestNode) {
|
|
40207
|
+
this.handleUserMessage(this.requestNode);
|
|
40208
|
+
}
|
|
40209
|
+
}
|
|
40210
|
+
onSubmissionEnd() {
|
|
40211
|
+
this.streamingEndTimer = null;
|
|
40212
|
+
let requestNode = this.requestNode;
|
|
40213
|
+
this.requestNode = null;
|
|
40214
|
+
if (!requestNode) {
|
|
40215
|
+
// onSubmissionStart didn't send, send it now
|
|
40216
|
+
requestNode = this.findLastRequestNode();
|
|
40217
|
+
if (!requestNode)
|
|
40218
|
+
return;
|
|
40219
|
+
this.handleUserMessage(requestNode);
|
|
40220
|
+
}
|
|
40221
|
+
const requestTurn = this.findTurnNumber(requestNode);
|
|
40222
|
+
if (requestTurn === null)
|
|
40223
|
+
return;
|
|
40224
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
40225
|
+
const toEmit = [];
|
|
40226
|
+
for (let i = assistantNodes.length - 1; i >= 0; i--) {
|
|
40227
|
+
const n = this.findTurnNumber(this.dom(assistantNodes[i]));
|
|
40228
|
+
if (n === null)
|
|
40229
|
+
continue;
|
|
40230
|
+
if (n <= requestTurn)
|
|
40231
|
+
break;
|
|
40232
|
+
toEmit.push(assistantNodes[i]);
|
|
40233
|
+
}
|
|
40234
|
+
// emit in chronological order (reverse of collection order)
|
|
40235
|
+
for (let i = toEmit.length - 1; i >= 0; i--) {
|
|
40236
|
+
this.handleAssistantMessage(this.dom(toEmit[i]));
|
|
40237
|
+
}
|
|
40238
|
+
}
|
|
40239
|
+
extractContent(node) {
|
|
40240
|
+
const rawContent = node.text().trim();
|
|
40241
|
+
const content = this.applyPrivacyFilter(rawContent);
|
|
40242
|
+
return { content, privacyFilterApplied: content !== rawContent };
|
|
40243
|
+
}
|
|
40244
|
+
getMessageId(node) {
|
|
40245
|
+
return node.attr(this.findSelector(MESSAGE_ID_ATTR));
|
|
40246
|
+
}
|
|
40247
|
+
handleUserMessage(node) {
|
|
40248
|
+
this.emit('prompt', Object.assign({ agentId: this.id, messageId: this.getMessageId(node) }, this.extractContent(node)));
|
|
40249
|
+
}
|
|
40250
|
+
handleAssistantMessage(node) {
|
|
40251
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
40252
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
40253
|
+
this.emit('agent_response', Object.assign({ agentId: this.id, messageId: this.getMessageId(node), agentModelsUsed: modelUsed ? [modelUsed] : [] }, this.extractContent(node)));
|
|
40254
|
+
}
|
|
40255
|
+
findLastRequestNode() {
|
|
40256
|
+
if (!this.getConversationId())
|
|
40257
|
+
return null;
|
|
40258
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
40259
|
+
if (!node)
|
|
40260
|
+
return null;
|
|
40261
|
+
const $node = this.dom(node);
|
|
40262
|
+
const messageId = this.getMessageId($node);
|
|
40263
|
+
if (!messageId)
|
|
40264
|
+
return null;
|
|
40265
|
+
if (messageId === this.lastReturnedMessageId)
|
|
40266
|
+
return null;
|
|
40267
|
+
this.lastReturnedMessageId = messageId;
|
|
40268
|
+
return $node;
|
|
40269
|
+
}
|
|
40270
|
+
findTurnNumber(node) {
|
|
40271
|
+
const turnSelector = this.findSelector(TURN_CONTAINER);
|
|
40272
|
+
const turnAttr = this.findSelector(TURN_ATTR);
|
|
40273
|
+
const turn = node.closest(turnSelector).attr(turnAttr);
|
|
40274
|
+
if (!turn)
|
|
40275
|
+
return null;
|
|
40276
|
+
const seqMatch = String(turn).match(/\d+/);
|
|
40277
|
+
return seqMatch ? parseInt(seqMatch[0], 10) : null;
|
|
40278
|
+
}
|
|
40279
|
+
findSelector(type) {
|
|
40280
|
+
return this.selectors[type];
|
|
40281
|
+
}
|
|
40282
|
+
select(type) {
|
|
40283
|
+
return this.dom(this.findSelector(type), this.root);
|
|
40284
|
+
}
|
|
40285
|
+
getConversationId() {
|
|
40286
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
40287
|
+
if (!m)
|
|
40288
|
+
return null;
|
|
40289
|
+
return m[1] !== undefined ? m[1] : m[0];
|
|
40290
|
+
}
|
|
40291
|
+
setFilters(candidateFilter) {
|
|
40292
|
+
if (!candidateFilter) {
|
|
40293
|
+
this.privacyFilters = null;
|
|
40294
|
+
return null;
|
|
40295
|
+
}
|
|
40296
|
+
try {
|
|
40297
|
+
this.privacyFilters = new RegExp(candidateFilter, 'gmi');
|
|
40298
|
+
}
|
|
40299
|
+
catch (e) {
|
|
40300
|
+
this.privacyFilters = null;
|
|
40301
|
+
this.api.log.error(e);
|
|
40302
|
+
}
|
|
40303
|
+
return this.privacyFilters;
|
|
40304
|
+
}
|
|
40305
|
+
applyPrivacyFilter(candidateValue, filters = null) {
|
|
40306
|
+
const filtersToUse = filters || this.privacyFilters;
|
|
40307
|
+
if (!filtersToUse || !this._.isRegExp(filtersToUse))
|
|
40308
|
+
return candidateValue;
|
|
40309
|
+
return candidateValue.replace(filtersToUse, 'redacted');
|
|
40310
|
+
}
|
|
40311
|
+
onSubmit(callback) {
|
|
40312
|
+
this.listeners.push(callback);
|
|
40313
|
+
}
|
|
40314
|
+
emit(eventType, eventPayload) {
|
|
40315
|
+
eventPayload.conversationId = this.getConversationId();
|
|
40316
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
40317
|
+
}
|
|
40318
|
+
startStreamingEndTimer() {
|
|
40319
|
+
this.stopStreamingEndTimer();
|
|
40320
|
+
this.streamingEndTimer = setTimeout$1(this.onSubmissionEnd.bind(this), STREAMING_END_SETTLE_MS);
|
|
40321
|
+
}
|
|
40322
|
+
stopStreamingEndTimer() {
|
|
40323
|
+
if (!this.streamingEndTimer)
|
|
40324
|
+
return;
|
|
40325
|
+
clearTimeout(this.streamingEndTimer);
|
|
40326
|
+
this.streamingEndTimer = null;
|
|
40327
|
+
}
|
|
40328
|
+
suspend() {
|
|
40329
|
+
this.isActive = false;
|
|
40330
|
+
}
|
|
40331
|
+
resume() {
|
|
40332
|
+
this.isActive = true;
|
|
40333
|
+
}
|
|
40334
|
+
teardown() {
|
|
40335
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
40336
|
+
this.observers = [];
|
|
40337
|
+
if (this.reactionClickHandler && this.root) {
|
|
40338
|
+
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
40339
|
+
this.reactionClickHandler = null;
|
|
40340
|
+
}
|
|
40341
|
+
this.stopStreamingEndTimer();
|
|
40342
|
+
this.listeners = [];
|
|
40343
|
+
}
|
|
40344
|
+
}
|
|
40345
|
+
|
|
39995
40346
|
/*
|
|
39996
40347
|
* Prompt Analytics Plugin
|
|
39997
40348
|
*
|
|
@@ -40156,18 +40507,31 @@ class PromptPlugin {
|
|
|
40156
40507
|
}
|
|
40157
40508
|
}
|
|
40158
40509
|
observePrompt(config) {
|
|
40159
|
-
const { id, cssSelectors, privacyFilters } = config;
|
|
40510
|
+
const { id, cssSelectors, privacyFilters, preset } = config;
|
|
40160
40511
|
// Check if agent already exists
|
|
40161
40512
|
const existingPrompt = this._.find(this.prompts, prompt => prompt.id === id);
|
|
40162
40513
|
if (existingPrompt) {
|
|
40163
40514
|
return;
|
|
40164
40515
|
}
|
|
40516
|
+
if (DOMConversation.supportedPreset(preset)) {
|
|
40517
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
40518
|
+
if (missing.length) {
|
|
40519
|
+
this.api.log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
40520
|
+
return;
|
|
40521
|
+
}
|
|
40522
|
+
const conversation = new DOMConversation(this.pendo, this.api, id, privacyFilters, cssSelectors);
|
|
40523
|
+
conversation.onSubmit((eventType, payload) => {
|
|
40524
|
+
this.sendConversationEvent(eventType, payload);
|
|
40525
|
+
});
|
|
40526
|
+
this.prompts.push(conversation);
|
|
40527
|
+
return;
|
|
40528
|
+
}
|
|
40165
40529
|
let inputCssSelectors, submitCssSelectors;
|
|
40166
40530
|
inputCssSelectors = this.parseCssSelector('input', cssSelectors);
|
|
40167
40531
|
submitCssSelectors = this.parseCssSelector('submit', cssSelectors);
|
|
40168
40532
|
const prompt = new DOMPrompt(this.pendo, this.api, id, privacyFilters, inputCssSelectors, submitCssSelectors);
|
|
40169
40533
|
prompt.onSubmit((promptPayload) => {
|
|
40170
|
-
this.
|
|
40534
|
+
this.sendPromptEvent(promptPayload);
|
|
40171
40535
|
});
|
|
40172
40536
|
this.prompts.push(prompt);
|
|
40173
40537
|
}
|
|
@@ -40176,7 +40540,7 @@ class PromptPlugin {
|
|
|
40176
40540
|
const selectors = this._.map(filtered, cfg => cfg.cssSelector);
|
|
40177
40541
|
return selectors;
|
|
40178
40542
|
}
|
|
40179
|
-
|
|
40543
|
+
sendPromptEvent(promptEvent) {
|
|
40180
40544
|
// Block event if the prompt is suspended
|
|
40181
40545
|
const prompt = this._.find(this.prompts, p => p.id === promptEvent.agentId);
|
|
40182
40546
|
if (prompt && !prompt.isActive) {
|
|
@@ -40188,6 +40552,15 @@ class PromptPlugin {
|
|
|
40188
40552
|
}, promptEvent);
|
|
40189
40553
|
this.api.analytics.collectEvent('prompt', event, undefined, 'agentic');
|
|
40190
40554
|
}
|
|
40555
|
+
sendConversationEvent(eventType, eventPayload) {
|
|
40556
|
+
// Block event if the prompt is suspended
|
|
40557
|
+
const conv = this._.find(this.prompts, p => p.id === eventPayload.agentId);
|
|
40558
|
+
if (conv && !conv.isActive) {
|
|
40559
|
+
return;
|
|
40560
|
+
}
|
|
40561
|
+
eventPayload = this._.extend({ agentType: 'conversation' }, eventPayload);
|
|
40562
|
+
this.api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
40563
|
+
}
|
|
40191
40564
|
teardown() {
|
|
40192
40565
|
this._.each(this.prompts, (prompt) => prompt.teardown());
|
|
40193
40566
|
if (this.agentsCache) {
|
|
@@ -40255,7 +40628,7 @@ class SessionManager {
|
|
|
40255
40628
|
this.suffix = this.api.ConfigReader.get('identityStorageSuffix');
|
|
40256
40629
|
/**
|
|
40257
40630
|
* Randomly generated string that identifies a session. This is similar to `pendo_tabId`,
|
|
40258
|
-
* but identifies the entire browser
|
|
40631
|
+
* but identifies the entire browser session rather than individual tabs.
|
|
40259
40632
|
*
|
|
40260
40633
|
* @name sessionId
|
|
40261
40634
|
* @category Cookies/localStorage
|
|
@@ -40681,6 +41054,69 @@ class WebAnalytics {
|
|
|
40681
41054
|
}
|
|
40682
41055
|
var WebAnalytics$1 = new WebAnalytics();
|
|
40683
41056
|
|
|
41057
|
+
function mergeEventProperties(capturedEvent, properties) {
|
|
41058
|
+
if (_.isEmpty(properties)) {
|
|
41059
|
+
return;
|
|
41060
|
+
}
|
|
41061
|
+
capturedEvent.eventProperties = _.extend({}, capturedEvent.eventProperties, properties);
|
|
41062
|
+
}
|
|
41063
|
+
function collectClickCapturedProperties(target) {
|
|
41064
|
+
const clickPropertyHandler = getEventPropertyHandler({ target });
|
|
41065
|
+
Events.onClickCaptured.trigger(clickPropertyHandler);
|
|
41066
|
+
return clickPropertyHandler.getEventProperties();
|
|
41067
|
+
}
|
|
41068
|
+
function collectEventCapturedProperties(target, capturedEvent) {
|
|
41069
|
+
const eventPropertyHandler = getEventPropertyHandler({ event: capturedEvent, target });
|
|
41070
|
+
Events.onEventCaptured.trigger(eventPropertyHandler);
|
|
41071
|
+
return eventPropertyHandler.getEventProperties();
|
|
41072
|
+
}
|
|
41073
|
+
function getEventPropertyHandler(obj) {
|
|
41074
|
+
const eventProperties = {};
|
|
41075
|
+
return _.extend({
|
|
41076
|
+
getEventProperties() {
|
|
41077
|
+
return eventProperties;
|
|
41078
|
+
},
|
|
41079
|
+
addEventProperty(key, value) {
|
|
41080
|
+
if (_.isString(key) && !_.isUndefined(value)) {
|
|
41081
|
+
eventProperties[key] = value;
|
|
41082
|
+
}
|
|
41083
|
+
else {
|
|
41084
|
+
log.error('Failed to add click event property');
|
|
41085
|
+
}
|
|
41086
|
+
}
|
|
41087
|
+
}, obj);
|
|
41088
|
+
}
|
|
41089
|
+
class EventCaptured {
|
|
41090
|
+
constructor() {
|
|
41091
|
+
this.name = 'EventCaptured';
|
|
41092
|
+
}
|
|
41093
|
+
initialize(pendo, PluginAPI) {
|
|
41094
|
+
this.api = PluginAPI;
|
|
41095
|
+
this.pendo = pendo;
|
|
41096
|
+
this.subscriptions = [
|
|
41097
|
+
this.api.attachEvent(this.api.Events, 'eventCaptured', _.bind(this.eventCaptured, this))
|
|
41098
|
+
];
|
|
41099
|
+
}
|
|
41100
|
+
teardown() {
|
|
41101
|
+
_.each(this.subscriptions, function (unsubscribe) {
|
|
41102
|
+
unsubscribe();
|
|
41103
|
+
});
|
|
41104
|
+
this.subscriptions.length = 0;
|
|
41105
|
+
}
|
|
41106
|
+
eventCaptured(event) {
|
|
41107
|
+
if (!event || !event.data || !event.data.length)
|
|
41108
|
+
return;
|
|
41109
|
+
const capturedEvent = event.data[0];
|
|
41110
|
+
const context = event.data[1];
|
|
41111
|
+
const target = context && context.target;
|
|
41112
|
+
if (capturedEvent.type === 'click') {
|
|
41113
|
+
mergeEventProperties(capturedEvent, collectClickCapturedProperties(target));
|
|
41114
|
+
}
|
|
41115
|
+
mergeEventProperties(capturedEvent, collectEventCapturedProperties(target, capturedEvent));
|
|
41116
|
+
}
|
|
41117
|
+
}
|
|
41118
|
+
var eventCapturedPlugin = new EventCaptured();
|
|
41119
|
+
|
|
40684
41120
|
function registerBuiltInPlugins() {
|
|
40685
41121
|
registerPlugin(ActionAutomation);
|
|
40686
41122
|
registerPlugin(Branding);
|
|
@@ -40701,6 +41137,7 @@ function registerBuiltInPlugins() {
|
|
|
40701
41137
|
registerPlugin(SessionManager$1);
|
|
40702
41138
|
registerPlugin(StepTimeoutMonitor);
|
|
40703
41139
|
registerPlugin(WebAnalytics$1);
|
|
41140
|
+
registerPlugin(eventCapturedPlugin);
|
|
40704
41141
|
}
|
|
40705
41142
|
|
|
40706
41143
|
/*
|
|
@@ -49423,7 +49860,7 @@ class SessionRecorder {
|
|
|
49423
49860
|
// https://github.com/pendo-io/pendo-browser-extension/blob/master/src/common/agent-loader.js
|
|
49424
49861
|
cf.addOption(RECORDING_CONFIG_ON_RECORDING_STOP, [cf.sources.SNIPPET_SRC, cf.sources.PENDO_CONFIG_SRC], undefined);
|
|
49425
49862
|
/**
|
|
49426
|
-
* Used when self
|
|
49863
|
+
* Used when self-hosting the replay web worker. Specifies the URL that points to the self-hosted web worker.
|
|
49427
49864
|
*
|
|
49428
49865
|
* @access public
|
|
49429
49866
|
* @category Config/Replay
|
|
@@ -49531,7 +49968,7 @@ class SessionRecorder {
|
|
|
49531
49968
|
this.subscriptions.push(this.api.attachEvent(this.api.Events, 'ready', bind(this.ready, this)));
|
|
49532
49969
|
}
|
|
49533
49970
|
/**
|
|
49534
|
-
* Randomly generated string that identifies a session. This is
|
|
49971
|
+
* Randomly generated string that identifies a session. This is similar to `pendo_sessionId`, but
|
|
49535
49972
|
* meant specifically for session recording.
|
|
49536
49973
|
*
|
|
49537
49974
|
* @name pendo_srId
|
|
@@ -49696,6 +50133,7 @@ class SessionRecorder {
|
|
|
49696
50133
|
* Used to start collecting replay data.
|
|
49697
50134
|
*
|
|
49698
50135
|
* @function start
|
|
50136
|
+
* @alias recording.start
|
|
49699
50137
|
* @category Replay
|
|
49700
50138
|
* @access public
|
|
49701
50139
|
* @example
|
|
@@ -51210,7 +51648,7 @@ function includes(str, substring) {
|
|
|
51210
51648
|
function getResourceType(blockedURI, directive) {
|
|
51211
51649
|
if (!directive || typeof directive !== 'string')
|
|
51212
51650
|
return 'resource';
|
|
51213
|
-
|
|
51651
|
+
const d = directive.toLowerCase();
|
|
51214
51652
|
if (blockedURI === 'inline') {
|
|
51215
51653
|
if (includes(d, 'script-src-attr')) {
|
|
51216
51654
|
return 'inline event handler';
|
|
@@ -51269,12 +51707,11 @@ function getResourceType(blockedURI, directive) {
|
|
|
51269
51707
|
function getDirective(policy, directiveName) {
|
|
51270
51708
|
if (!policy || !directiveName)
|
|
51271
51709
|
return '';
|
|
51272
|
-
|
|
51273
|
-
for (
|
|
51274
|
-
|
|
51275
|
-
|
|
51276
|
-
|
|
51277
|
-
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
51710
|
+
const needle = directiveName.toLowerCase();
|
|
51711
|
+
for (const directive of policy.split(';')) {
|
|
51712
|
+
const trimmed = directive.trim();
|
|
51713
|
+
const lower = trimmed.toLowerCase();
|
|
51714
|
+
if (lower === needle || lower.startsWith(`${needle} `)) {
|
|
51278
51715
|
return trimmed;
|
|
51279
51716
|
}
|
|
51280
51717
|
}
|
|
@@ -51296,7 +51733,7 @@ function getDirective(policy, directiveName) {
|
|
|
51296
51733
|
function getArticle(phrase) {
|
|
51297
51734
|
if (!phrase || typeof phrase !== 'string')
|
|
51298
51735
|
return 'A';
|
|
51299
|
-
|
|
51736
|
+
const c = phrase.trim().charAt(0).toLowerCase();
|
|
51300
51737
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
51301
51738
|
}
|
|
51302
51739
|
/**
|
|
@@ -51339,47 +51776,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
51339
51776
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
51340
51777
|
}
|
|
51341
51778
|
try {
|
|
51342
|
-
|
|
51779
|
+
const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
51343
51780
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
51344
51781
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
51345
|
-
return
|
|
51782
|
+
return `Content Security Policy${reportOnlyText}: The display of ${blockedURI} in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
51346
51783
|
}
|
|
51347
|
-
|
|
51348
|
-
|
|
51349
|
-
|
|
51350
|
-
|
|
51351
|
-
|
|
51352
|
-
|
|
51353
|
-
return
|
|
51784
|
+
const resourceType = getResourceType(blockedURI, directive);
|
|
51785
|
+
const article = getArticle(resourceType);
|
|
51786
|
+
const source = formatBlockedUri(blockedURI);
|
|
51787
|
+
const directiveValue = getDirective(originalPolicy, directive);
|
|
51788
|
+
const policyDisplay = directiveValue || directive;
|
|
51789
|
+
const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
|
|
51790
|
+
return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
51354
51791
|
}
|
|
51355
51792
|
catch (error) {
|
|
51356
|
-
return
|
|
51793
|
+
return `Content Security Policy: Error formatting violation message: ${error.message}`;
|
|
51357
51794
|
}
|
|
51358
51795
|
}
|
|
51359
51796
|
|
|
51360
|
-
|
|
51361
|
-
|
|
51797
|
+
const MAX_LENGTH = 1000;
|
|
51798
|
+
const PII_PATTERN = {
|
|
51362
51799
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
51363
51800
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
51364
51801
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
51365
51802
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
51366
51803
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
51367
51804
|
};
|
|
51368
|
-
|
|
51369
|
-
|
|
51370
|
-
|
|
51371
|
-
|
|
51372
|
-
|
|
51805
|
+
const PII_REPLACEMENT = '*'.repeat(10);
|
|
51806
|
+
const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
51807
|
+
const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
51808
|
+
const joinedKeys = JSON_PII_KEYS.join('|');
|
|
51809
|
+
const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
|
|
51373
51810
|
// only scrub strings, numbers, and booleans
|
|
51374
|
-
|
|
51811
|
+
const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
51375
51812
|
/**
|
|
51376
51813
|
* Truncates a string to the max length
|
|
51377
51814
|
* @access private
|
|
51378
51815
|
* @param {String} string
|
|
51379
51816
|
* @returns {String}
|
|
51380
51817
|
*/
|
|
51381
|
-
function truncate(string, includeEllipsis) {
|
|
51382
|
-
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
51818
|
+
function truncate(string, includeEllipsis = false) {
|
|
51383
51819
|
if (string.length <= MAX_LENGTH)
|
|
51384
51820
|
return string;
|
|
51385
51821
|
if (includeEllipsis) {
|
|
@@ -51396,7 +51832,7 @@ function truncate(string, includeEllipsis) {
|
|
|
51396
51832
|
* @returns {String}
|
|
51397
51833
|
*/
|
|
51398
51834
|
function generateLogKey(methodName, message, stackTrace) {
|
|
51399
|
-
return
|
|
51835
|
+
return `${methodName}|${message}|${stackTrace}`;
|
|
51400
51836
|
}
|
|
51401
51837
|
/**
|
|
51402
51838
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -51413,13 +51849,12 @@ function mightContainPII(string) {
|
|
|
51413
51849
|
* @param {String} string
|
|
51414
51850
|
* @returns {String}
|
|
51415
51851
|
*/
|
|
51416
|
-
function scrubPII(
|
|
51417
|
-
var string = _a.string, _ = _a._;
|
|
51852
|
+
function scrubPII({ string, _ }) {
|
|
51418
51853
|
if (!string || typeof string !== 'string')
|
|
51419
51854
|
return string;
|
|
51420
51855
|
if (!mightContainPII(string))
|
|
51421
51856
|
return string;
|
|
51422
|
-
return _.reduce(_.values(PII_PATTERN),
|
|
51857
|
+
return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
|
|
51423
51858
|
}
|
|
51424
51859
|
/**
|
|
51425
51860
|
* Scrub PII from a stringified JSON object
|
|
@@ -51428,14 +51863,12 @@ function scrubPII(_a) {
|
|
|
51428
51863
|
* @returns {String}
|
|
51429
51864
|
*/
|
|
51430
51865
|
function scrubJsonPII(string) {
|
|
51431
|
-
|
|
51866
|
+
const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
|
|
51432
51867
|
if (fullScrubRegex.test(string)) {
|
|
51433
51868
|
return UNABLE_TO_DISPLAY_BODY;
|
|
51434
51869
|
}
|
|
51435
|
-
|
|
51436
|
-
return string.replace(keyValueScrubRegex,
|
|
51437
|
-
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
51438
|
-
});
|
|
51870
|
+
const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
|
|
51871
|
+
return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
|
|
51439
51872
|
}
|
|
51440
51873
|
/**
|
|
51441
51874
|
* Checks if a string is a JSON object
|
|
@@ -51447,7 +51880,7 @@ function scrubJsonPII(string) {
|
|
|
51447
51880
|
function mightContainJson(string, contentType) {
|
|
51448
51881
|
if (!string || typeof string !== 'string')
|
|
51449
51882
|
return false;
|
|
51450
|
-
|
|
51883
|
+
const firstChar = string.charAt(0);
|
|
51451
51884
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
51452
51885
|
return true;
|
|
51453
51886
|
}
|
|
@@ -51460,20 +51893,19 @@ function mightContainJson(string, contentType) {
|
|
|
51460
51893
|
* @param {String} contentType
|
|
51461
51894
|
* @returns {String}
|
|
51462
51895
|
*/
|
|
51463
|
-
function maskSensitiveFields(
|
|
51464
|
-
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
51896
|
+
function maskSensitiveFields({ string, contentType, _ }) {
|
|
51465
51897
|
if (!string || typeof string !== 'string')
|
|
51466
51898
|
return string;
|
|
51467
51899
|
if (mightContainJson(string, contentType)) {
|
|
51468
51900
|
string = scrubJsonPII(string);
|
|
51469
51901
|
}
|
|
51470
51902
|
if (mightContainPII(string)) {
|
|
51471
|
-
string = scrubPII({ string
|
|
51903
|
+
string = scrubPII({ string, _ });
|
|
51472
51904
|
}
|
|
51473
51905
|
return string;
|
|
51474
51906
|
}
|
|
51475
51907
|
|
|
51476
|
-
|
|
51908
|
+
const DEV_LOG_TYPE = 'devlog';
|
|
51477
51909
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
51478
51910
|
return {
|
|
51479
51911
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -52052,6 +52484,7 @@ function NetworkCapture() {
|
|
|
52052
52484
|
* Use RegExp for flexible or partial matching.
|
|
52053
52485
|
*
|
|
52054
52486
|
* Example: `['https://example.com', new RegExp('https://test\\.com\\/.*'), /.*\\.domain\\.com/]`
|
|
52487
|
+
*
|
|
52055
52488
|
* @access public
|
|
52056
52489
|
* @category Config/Network Logs
|
|
52057
52490
|
* @name networkLogs.excludeRequestUrls
|