diff --git a/.eslintignore b/.eslintignore index 2f263929..08cbf405 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,4 @@ -lib/countly.min.js +lib plugin/boomerang/boomerang.min.js examples/ node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index e2bc6dce..6da2fbb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ -## X.X.X +## 23.12.0 - You can now provide custom storage methods to the SDK +- You can now use the SDK in web workers +- From this version on the SDK is bundled from the Countly JavaScript SDK ## 23.6.3 - You can now add segmentation while presenting a widget with 'present_feedback_widget' diff --git a/README.md b/README.md index f6ccca85..0d963d5d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ # Countly Web SDK +This SDK is bundled from the modular [Countly JavaScript SDK](https://github.com/Countly/countly-sdk-js). + This repository contains the Countly Web SDK, which can be integrated into websites and web applications. The Countly Web SDK is intended to be used with [Countly Lite](https://countly.com/lite), [Countly Flex](https://countly.com/flex) [Countly Enterprise](https://countly.com/enterprise). ## What is Countly? diff --git a/cypress/fixtures/click_test.html b/cypress/fixtures/click_test.html index bca3ef33..1e5e3b04 100644 --- a/cypress/fixtures/click_test.html +++ b/cypress/fixtures/click_test.html @@ -19,7 +19,7 @@ var domEl = queryExtractor(window.location.search).dom; Countly.init({ app_key: "YOUR_APP_KEY", - url: "https://your.domain.count.ly", + url: "https://your.domain.countly", debug: true, test_mode: true }) diff --git a/cypress/fixtures/multi_instance.html b/cypress/fixtures/multi_instance.html index fa9ddacb..b3deb9bd 100644 --- a/cypress/fixtures/multi_instance.html +++ b/cypress/fixtures/multi_instance.html @@ -22,7 +22,7 @@ //initializing first instance, which will be global Countly Countly.init({ app_key: "YOUR_APP_KEY1", - url: "https://your.domain.count.ly", + url: "https://your.domain.countly", test_mode: true }) Countly.remove_consent(); @@ -57,7 +57,7 @@ //initialize second instance for another app synchronously var Countly2 = Countly.init({ app_key: "YOUR_APP_KEY2", //must have different APP key - url: "https://your.domain.count.ly", + url: "https://your.domain.countly", test_mode: true }); @@ -94,7 +94,7 @@ //initialize third instance for another app asynchronously Countly.q.push(["init", { app_key: "YOUR_APP_KEY3", //must have different APP key - url: "https://your.domain.count.ly", + url: "https://your.domain.countly", test_mode: true }]) @@ -128,7 +128,7 @@ //initialize fourth instance for another app asynchronously Countly.q.push(["init", { app_key: "YOUR_APP_KEY4", //must have different APP key - url: "https://your.domain.count.ly", + url: "https://your.domain.countly", test_mode: true }]) diff --git a/cypress/fixtures/referrer.html b/cypress/fixtures/referrer.html index 5b94d0a5..527414f1 100644 --- a/cypress/fixtures/referrer.html +++ b/cypress/fixtures/referrer.html @@ -4,7 +4,7 @@ */ -(function(root, factory) { - if (typeof define === "function" && define.amd) { - define([], function() { - return factory(root.Countly); +(function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Countly = global.Countly || {})); +})(this, (function(exports) { + 'use strict'; + + function _typeof(o) { + "@babel/helpers - typeof"; + + return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) { + return typeof o; + } : function(o) { + return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; + }, _typeof(o); + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + Object.defineProperty(Constructor, "prototype", { + writable: false }); + return Constructor; } - else if (typeof module === "object" && module.exports) { - module.exports = factory(root.Countly); + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); } - else { - root.Countly = factory(root.Countly); + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); } -}(typeof window !== "undefined" ? window : this, function(Countly) { - var isBrowser = typeof window !== "undefined"; - /** @lends Countly */ - Countly = Countly || {}; + var isBrowser = typeof window !== "undefined"; + var Countly = globalThis.Countly || {}; /** * Array with list of available features that you can require consent for @@ -188,18 +226,15 @@ */ Countly.onload = Countly.onload || []; - var SDK_VERSION = "23.6.3"; + var SDK_VERSION = "23.12.0"; var SDK_NAME = "javascript_native_web"; // Using this on document.referrer would return an array with 15 elements in it. The 12th element (array[11]) would be the path we are looking for. Others would be things like password and such (use https://regex101.com/ to check more) var urlParseRE = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/; var apmLibrariesNotLoaded = true; // used to prevent loading apm scripts multiple times. - /** - * @this Countly - * @param {Object} ob - Configuration object - */ - var CountlyClass = function(ob) { + var CountlyClass = /*#__PURE__*/_createClass(function CountlyClass(ob) { + _classCallCheck(this, CountlyClass); var self = this; var global = !Countly.i; var sessionStarted = false; @@ -385,7 +420,7 @@ } } - if ((this.passed_data && this.passed_data.app_key && this.passed_data.app_key === this.app_key) || (this.passed_data && !this.passed_data.app_key && global)) { + if (this.passed_data && this.passed_data.app_key && this.passed_data.app_key === this.app_key || this.passed_data && !this.passed_data.app_key && global) { if (this.passed_data.token && this.passed_data.purpose) { if (this.passed_data.token !== getValueFromStorage("cly_old_token")) { setToken(this.passed_data.token); @@ -574,7 +609,7 @@ } // flag that indicates that the offline mode was enabled at the end of the previous app session - var tempIdModeWasEnabled = (getValueFromStorage("cly_id") === "[CLY]_temp_id"); + var tempIdModeWasEnabled = getValueFromStorage("cly_id") === "[CLY]_temp_id"; var developerSetDeviceId = getConfig("device_id", ob, undefined); if (typeof developerSetDeviceId === "number") { // device ID should always be string developerSetDeviceId = developerSetDeviceId.toString(); @@ -970,7 +1005,7 @@ }; var consentTimer; - var updateConsent = function() { + var updateConsent = function updateConsent() { if (consentTimer) { // delay syncing consents clearTimeout(consentTimer); @@ -1065,7 +1100,7 @@ } lastBeat = getTimestamp(); sessionStarted = true; - autoExtend = !(noHeartBeat); + autoExtend = !noHeartBeat; var expire = getValueFromStorage("cly_session"); log(logLevelEnums.VERBOSE, "begin_session, Session state, forced: [" + force + "], useSessionCookie: [" + useSessionCookie + "], seconds to expire: [" + (expire - lastBeat) + "], expired: [" + (parseInt(expire) <= getTimestamp()) + "] "); if (force || !useSessionCookie || !expire || parseInt(expire) <= getTimestamp()) { @@ -1078,7 +1113,7 @@ req.metrics = JSON.stringify(getMetrics()); toRequestQueue(req); } - setValueInStorage("cly_session", getTimestamp() + (sessionCookieTimeout * 60)); + setValueInStorage("cly_session", getTimestamp() + sessionCookieTimeout * 60); } } else { @@ -1346,8 +1381,8 @@ add_cly_events({ key: internalEventKeyEnums.ORIENTATION, segmentation: { - mode: orientation || getOrientation(), - }, + mode: orientation || getOrientation() + } }); } }; @@ -1429,7 +1464,7 @@ * - addToSet, creates an array property, if property does not exist, and adds unique value to array, only if it does not yet exist in array ************************* */ var customData = {}; - var change_custom_property = function(key, value, mod) { + var change_custom_property = function change_custom_property(key, value, mod) { if (self.check_consent(featureEnums.USERS)) { if (!customData[key]) { customData[key] = {}; @@ -1467,7 +1502,7 @@ * @param {string} key - name of the property to attach to user * @param {string|number} value - value to store under provided property * */ - set: function(key, value) { + set: function set(key, value) { log(logLevelEnums.INFO, "[userData] set, Setting user's custom property value: [" + value + "] under the key: [" + key + "]"); // truncate user's custom property value to internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData set", log); @@ -1479,7 +1514,7 @@ * @memberof Countly.userData * @param {string} key - name of the property to delete * */ - unset: function(key) { + unset: function unset(key) { log(logLevelEnums.INFO, "[userData] unset, Resetting user's custom property with key: [" + key + "] "); customData[key] = ""; }, @@ -1489,7 +1524,7 @@ * @param {string} key - name of the property to attach to user * @param {string|number} value - value to store under provided property * */ - set_once: function(key, value) { + set_once: function set_once(key, value) { log(logLevelEnums.INFO, "[userData] set_once, Setting user's unique custom property value: [" + value + "] under the key: [" + key + "] "); // truncate user's custom property value to internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData set_once", log); @@ -1501,7 +1536,7 @@ * @memberof Countly.userData * @param {string} key - name of the property to attach to user * */ - increment: function(key) { + increment: function increment(key) { log(logLevelEnums.INFO, "[userData] increment, Increasing user's custom property value under the key: [" + key + "] by one"); // truncate property name wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData increment", log); @@ -1513,7 +1548,7 @@ * @param {string} key - name of the property to attach to user * @param {number} value - value by which to increment server value * */ - increment_by: function(key, value) { + increment_by: function increment_by(key, value) { log(logLevelEnums.INFO, "[userData] increment_by, Increasing user's custom property value under the key: [" + key + "] by: [" + value + "]"); // truncate property name and value wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData increment_by", log); @@ -1526,7 +1561,7 @@ * @param {string} key - name of the property to attach to user * @param {number} value - value by which to multiply server value * */ - multiply: function(key, value) { + multiply: function multiply(key, value) { log(logLevelEnums.INFO, "[userData] multiply, Multiplying user's custom property value under the key: [" + key + "] by: [" + value + "]"); // truncate key value pair wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData multiply", log); @@ -1539,7 +1574,7 @@ * @param {string} key - name of the property to attach to user * @param {number} value - value which to compare to server's value and store maximal value of both provided * */ - max: function(key, value) { + max: function max(key, value) { log(logLevelEnums.INFO, "[userData] max, Saving user's maximum custom property value compared to the value: [" + value + "] under the key: [" + key + "]"); // truncate key value pair wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData max", log); @@ -1552,7 +1587,7 @@ * @param {string} key - name of the property to attach to user * @param {number} value - value which to compare to server's value and store minimal value of both provided * */ - min: function(key, value) { + min: function min(key, value) { log(logLevelEnums.INFO, "[userData] min, Saving user's minimum custom property value compared to the value: [" + value + "] under the key: [" + key + "]"); // truncate key value pair wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData min", log); @@ -1565,7 +1600,7 @@ * @param {string} key - name of the property to attach to user * @param {string|number} value - value which to add to array * */ - push: function(key, value) { + push: function push(key, value) { log(logLevelEnums.INFO, "[userData] push, Pushing a value: [" + value + "] under the key: [" + key + "] to user's custom property array"); // truncate key value pair wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData push", log); @@ -1578,7 +1613,7 @@ * @param {string} key - name of the property to attach to user * @param {string|number} value - value which to add to array * */ - push_unique: function(key, value) { + push_unique: function push_unique(key, value) { log(logLevelEnums.INFO, "[userData] push_unique, Pushing a unique value: [" + value + "] under the key: [" + key + "] to user's custom property array"); // truncate key value pair wrt internal limits key = truncateSingleValue(key, self.maxKeyLength, "userData push_unique", log); @@ -1591,7 +1626,7 @@ * @param {string} key - name of the property * @param {string|number} value - value which to remove from array * */ - pull: function(key, value) { + pull: function pull(key, value) { log(logLevelEnums.INFO, "[userData] pull, Removing the value: [" + value + "] under the key: [" + key + "] from user's custom property array"); change_custom_property(key, value, "$pull"); }, @@ -1599,7 +1634,7 @@ * Save changes made to user's custom properties object and send them to server * @memberof Countly.userData * */ - save: function() { + save: function save() { log(logLevelEnums.INFO, "[userData] save, Saving changes to user's custom property"); if (self.check_consent(featureEnums.USERS)) { sendEventsForced(); // flush events to event queue to prevent a drill issue @@ -1638,7 +1673,9 @@ var date = new Date(); e.hour = date.getHours(); e.dow = date.getDay(); - toRequestQueue({ apm: JSON.stringify(e) }); + toRequestQueue({ + apm: JSON.stringify(e) + }); log(logLevelEnums.INFO, "report_trace, Successfully adding APM trace: ", e); } }; @@ -1667,7 +1704,7 @@ } // fallback if no error object is present for older browsers, we create it instead else { - col = col || (window.event && window.event.errorCharacter); + col = col || window.event && window.event.errorCharacter; var error = ""; if (typeof msg !== "undefined") { error += msg + "\n"; @@ -1682,7 +1719,6 @@ error += ":" + col; } error += "\n"; - try { var stack = []; // deprecated, must be changed @@ -1693,8 +1729,7 @@ f = f.caller; } error += stack.join("\n"); - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "track_errors, Call stack generation experienced a problem: " + ex); } // false indicates fatal error (as in non_fatal:false) @@ -1783,7 +1818,6 @@ fetch_remote_config_explicit(keysFiltered, omitKeysFiltered, opt, null, callbackFiltered); return; } - log(logLevelEnums.WARNING, "fetch_remote_config, Fetching remote config, with legacy API"); fetch_remote_config_explicit(keysFiltered, omitKeysFiltered, null, "legacy", callbackFiltered); }; @@ -1839,25 +1873,24 @@ try { var configs = JSON.parse(responseText); if (request.keys || request.omit_keys) { - // we merge config + // we merge config for (var i in configs) { remoteConfigs[i] = configs[i]; } } else { - // we replace config + // we replace config remoteConfigs = configs; } setValueInStorage("cly_remote_configs", remoteConfigs); - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "fetch_remote_config_explicit, Had an issue while parsing the response: " + ex); } if (providedCall) { log(logLevelEnums.INFO, "fetch_remote_config_explicit, Callback function is provided"); providedCall(err, remoteConfigs); } - // JSON array can pass + // JSON array can pass }, true); } else { @@ -1892,8 +1925,7 @@ try { var resp = JSON.parse(responseText); log(logLevelEnums.DEBUG, "enrollUserToAb, Parsed the response's result: [" + resp.result + "]"); - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "enrollUserToAb, Had an issue while parsing the response: " + ex); } // JSON array can pass @@ -2013,7 +2045,6 @@ } inactivityCounter = 0; } - add_event_listener(window, "mousemove", resetInactivity); add_event_listener(window, "click", resetInactivity); add_event_listener(window, "keydown", resetInactivity); @@ -2069,7 +2100,6 @@ log(logLevelEnums.ERROR, "track_pageview, View name returned as null. Page view will be ignored."); return; } - if (ignoreList && ignoreList.length) { for (var i = 0; i < ignoreList.length; i++) { try { @@ -2078,8 +2108,7 @@ log(logLevelEnums.INFO, "track_pageview, Ignoring the page: " + page); return; } - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "track_pageview, Problem with finding ignore list item: " + ignoreList[i] + ", error: " + ex); } } @@ -2097,7 +2126,6 @@ if (this.track_domains) { segments.domain = window.location.hostname; } - if (useSessionCookie) { if (!sessionStarted) { // tracking view was called before tracking session, so we check expiration ourselves @@ -2143,7 +2171,6 @@ if (viewSegments) { viewSegments = truncateObject(viewSegments, self.maxKeyLength, self.maxValueSize, self.maxSegmentationValues, "track_pageview", log); - for (var key in viewSegments) { if (typeof segments[key] === "undefined") { segments[key] = viewSegments[key]; @@ -2249,7 +2276,6 @@ parent = parent || window; isScrollRegistryOpen = true; trackingScrolls = true; - add_event_listener(parent, "scroll", processScroll); add_event_listener(parent, "beforeunload", processScrollView); }; @@ -2275,7 +2301,6 @@ function processClick(event) { // get element which was clicked var elem = get_closest_element(get_event_target(event), "a"); - if (elem) { // cross browser click coordinates get_page_coord(event); @@ -2309,7 +2334,7 @@ log(logLevelEnums.WARNING, "track_forms, window object is not available. Not tracking forms."); return; } - log(logLevelEnums.INFO, "track_forms, Starting to track form submissions. DOM object provided:[" + (!!parent) + "] Tracking hidden inputs :[" + (!!trackHidden) + "]"); + log(logLevelEnums.INFO, "track_forms, Starting to track form submissions. DOM object provided:[" + !!parent + "] Tracking hidden inputs :[" + !!trackHidden + "]"); parent = parent || document; /** * Get name of the input @@ -2403,7 +2428,7 @@ log(logLevelEnums.WARNING, "collect_from_forms, window object is not available. Not collecting from forms."); return; } - log(logLevelEnums.INFO, "collect_from_forms, Starting to collect possible user data. DOM object provided:[" + (!!parent) + "] Submitting custom user property:[" + (!!useCustom) + "]"); + log(logLevelEnums.INFO, "collect_from_forms, Starting to collect possible user data. DOM object provided:[" + !!parent + "] Submitting custom user property:[" + !!useCustom + "]"); parent = parent || document; /** * Process form data @@ -2475,43 +2500,31 @@ } } // check for email - else if ((input.type && input.type.toLowerCase() === "email") - || (input.name && input.name.toLowerCase().indexOf("email") !== -1) - || (input.id && input.id.toLowerCase().indexOf("email") !== -1) - || (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("email") !== -1) - || (/[^@\s]+@[^@\s]+\.[^@\s]+/).test(value)) { + else if (input.type && input.type.toLowerCase() === "email" || input.name && input.name.toLowerCase().indexOf("email") !== -1 || input.id && input.id.toLowerCase().indexOf("email") !== -1 || input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("email") !== -1 || /[^@\s]+@[^@\s]+\.[^@\s]+/.test(value)) { if (!userdata.email) { userdata.email = value; } hasUserInfo = true; } - else if ((input.name && input.name.toLowerCase().indexOf("username") !== -1) - || (input.id && input.id.toLowerCase().indexOf("username") !== -1) - || (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("username") !== -1)) { + else if (input.name && input.name.toLowerCase().indexOf("username") !== -1 || input.id && input.id.toLowerCase().indexOf("username") !== -1 || input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("username") !== -1) { if (!userdata.username) { userdata.username = value; } hasUserInfo = true; } - else if ((input.name && (input.name.toLowerCase().indexOf("tel") !== -1 || input.name.toLowerCase().indexOf("phone") !== -1 || input.name.toLowerCase().indexOf("number") !== -1)) - || (input.id && (input.id.toLowerCase().indexOf("tel") !== -1 || input.id.toLowerCase().indexOf("phone") !== -1 || input.id.toLowerCase().indexOf("number") !== -1)) - || (input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf("tel") !== -1 || labelData[input.id].toLowerCase().indexOf("phone") !== -1 || labelData[input.id].toLowerCase().indexOf("number") !== -1))) { + else if (input.name && (input.name.toLowerCase().indexOf("tel") !== -1 || input.name.toLowerCase().indexOf("phone") !== -1 || input.name.toLowerCase().indexOf("number") !== -1) || input.id && (input.id.toLowerCase().indexOf("tel") !== -1 || input.id.toLowerCase().indexOf("phone") !== -1 || input.id.toLowerCase().indexOf("number") !== -1) || input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf("tel") !== -1 || labelData[input.id].toLowerCase().indexOf("phone") !== -1 || labelData[input.id].toLowerCase().indexOf("number") !== -1)) { if (!userdata.phone) { userdata.phone = value; } hasUserInfo = true; } - else if ((input.name && (input.name.toLowerCase().indexOf("org") !== -1 || input.name.toLowerCase().indexOf("company") !== -1)) - || (input.id && (input.id.toLowerCase().indexOf("org") !== -1 || input.id.toLowerCase().indexOf("company") !== -1)) - || (input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf("org") !== -1 || labelData[input.id].toLowerCase().indexOf("company") !== -1))) { + else if (input.name && (input.name.toLowerCase().indexOf("org") !== -1 || input.name.toLowerCase().indexOf("company") !== -1) || input.id && (input.id.toLowerCase().indexOf("org") !== -1 || input.id.toLowerCase().indexOf("company") !== -1) || input.id && labelData[input.id] && (labelData[input.id].toLowerCase().indexOf("org") !== -1 || labelData[input.id].toLowerCase().indexOf("company") !== -1)) { if (!userdata.organization) { userdata.organization = value; } hasUserInfo = true; } - else if ((input.name && input.name.toLowerCase().indexOf("name") !== -1) - || (input.id && input.id.toLowerCase().indexOf("name") !== -1) - || (input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("name") !== -1)) { + else if (input.name && input.name.toLowerCase().indexOf("name") !== -1 || input.id && input.id.toLowerCase().indexOf("name") !== -1 || input.id && labelData[input.id] && labelData[input.id].toLowerCase().indexOf("name") !== -1) { if (!userdata.name) { userdata.name = ""; } @@ -2527,7 +2540,9 @@ if (hasUserInfo) { log(logLevelEnums.INFO, "collect_from_forms, Gathered user data", userdata); if (useCustom) { - self.user_details({ custom: userdata }); + self.user_details({ + custom: userdata + }); } else { self.user_details(userdata); @@ -2723,7 +2738,6 @@ log(logLevelEnums.ERROR, "reportFeedbackWidgetManually, Feedback Widgets can not be reported in offline mode"); return; } - log(logLevelEnums.INFO, "reportFeedbackWidgetManually, Providing information about user with, provided result of the widget with ID: [ " + CountlyFeedbackWidget._id + " ] and type: [" + CountlyFeedbackWidget.type + "]"); // type specific checks to see if everything was provided @@ -2793,7 +2807,6 @@ app_version: this.metrics._app_version || this.app_version } }; - if (widgetResult === null) { event.segmentation.closed = 1; } @@ -2837,7 +2850,10 @@ log(logLevelEnums.ERROR, "presentRatingWidgetWithID, Cannot show ratingWidget popup in offline mode"); } else { - makeNetworkRequest("presentRatingWidgetWithID,", this.url + "/o/feedback/widget", { widget_id: id, av: self.app_version }, function(err, params, responseText) { + makeNetworkRequest("presentRatingWidgetWithID,", this.url + "/o/feedback/widget", { + widget_id: id, + av: self.app_version + }, function(err, params, responseText) { if (err) { // error has been logged by the request function return; @@ -2846,11 +2862,10 @@ // widget object var currentWidget = JSON.parse(responseText); processWidget(currentWidget, false); - } - catch (JSONParseError) { + } catch (JSONParseError) { log(logLevelEnums.ERROR, "presentRatingWidgetWithID, JSON parse failed: " + JSONParseError); } - // JSON array can pass + // JSON array can pass }, true); } }; @@ -2891,8 +2906,10 @@ while (stickers.length > 0) { stickers[0].remove(); } - - makeNetworkRequest("initializeRatingWidgets,", this.url + "/o/feedback/multiple-widgets-by-id", { widgets: JSON.stringify(enableWidgets), av: self.app_version }, function(err, params, responseText) { + makeNetworkRequest("initializeRatingWidgets,", this.url + "/o/feedback/multiple-widgets-by-id", { + widgets: JSON.stringify(enableWidgets), + av: self.app_version + }, function(err, params, responseText) { if (err) { // error has been logged by the request function return; @@ -2921,7 +2938,7 @@ var isWildcardMatched = pages[k].substr(0, pages[k].length - 1) === window.location.pathname.substr(0, pages[k].length - 1); var isFullPathMatched = pages[k] === window.location.pathname; var isContainAsterisk = pages[k].includes("*"); - if (((isContainAsterisk && isWildcardMatched) || isFullPathMatched) && !widgets[i].hide_sticker) { + if ((isContainAsterisk && isWildcardMatched || isFullPathMatched) && !widgets[i].hide_sticker) { processWidget(widgets[i], true); } } @@ -2929,11 +2946,10 @@ } } } - } - catch (JSONParseError) { + } catch (JSONParseError) { log(logLevelEnums.ERROR, "initializeRatingWidgets, JSON parse error: " + JSONParseError); } - // JSON array can pass + // JSON array can pass }, true); }; @@ -2976,7 +2992,6 @@ // get enable widgets by app_key // define xhr object var enableWidgets = params.popups || params.widgets; - if (enableWidgets.length > 0) { document.body.insertAdjacentHTML("beforeend", "
"); this.initializeRatingWidgets(enableWidgets); @@ -2992,19 +3007,17 @@ * @param {Function} callback - Callback function with two parameters, 1st for returned list, 2nd for error * */ this.get_available_feedback_widgets = function(callback) { - log(logLevelEnums.INFO, "get_available_feedback_widgets, Getting the feedback list, callback function is provided:[" + (!!callback) + "]"); + log(logLevelEnums.INFO, "get_available_feedback_widgets, Getting the feedback list, callback function is provided:[" + !!callback + "]"); if (!this.check_consent(featureEnums.FEEDBACK)) { if (callback) { callback(null, new Error("Consent for feedback not provided.")); } return; } - if (offlineMode) { log(logLevelEnums.ERROR, "get_available_feedback_widgets, Cannot enable feedback widgets in offline mode."); return; } - var url = this.url + readPath; var data = { method: featureEnums.FEEDBACK, @@ -3012,7 +3025,6 @@ app_key: this.app_key, av: self.app_version }; - makeNetworkRequest("get_available_feedback_widgets,", url, data, function(err, params, responseText) { if (err) { // error has been logged by the request function @@ -3021,21 +3033,19 @@ } return; } - try { var response = JSON.parse(responseText); var feedbacks = response.result || []; if (callback) { callback(feedbacks, null); } - } - catch (error) { + } catch (error) { log(logLevelEnums.ERROR, "get_available_feedback_widgets, Error while parsing feedback widgets list: " + error); if (callback) { callback(null, error); } } - // expected response is JSON object + // expected response is JSON object }, false); }; @@ -3049,19 +3059,17 @@ log(logLevelEnums.ERROR, "getFeedbackWidgetData, Expected the provided widget object to have a type but got: [" + JSON.stringify(CountlyFeedbackWidget) + "], aborting."); return; } - log(logLevelEnums.INFO, "getFeedbackWidgetData, Retrieving data for: [" + JSON.stringify(CountlyFeedbackWidget) + "], callback function is provided:[" + (!!callback) + "]"); + log(logLevelEnums.INFO, "getFeedbackWidgetData, Retrieving data for: [" + JSON.stringify(CountlyFeedbackWidget) + "], callback function is provided:[" + !!callback + "]"); if (!this.check_consent(featureEnums.FEEDBACK)) { if (callback) { callback(null, new Error("Consent for feedback not provided.")); } return; } - if (offlineMode) { log(logLevelEnums.ERROR, "getFeedbackWidgetData, Cannot enable feedback widgets in offline mode."); return; } - var url = this.url; var data = { widget_id: CountlyFeedbackWidget._id, @@ -3071,7 +3079,6 @@ platform: this.platform, app_version: this.app_version }; - if (CountlyFeedbackWidget.type === "nps") { url += "/o/surveys/nps/widget"; } @@ -3085,7 +3092,6 @@ log(logLevelEnums.ERROR, "getFeedbackWidgetData, Unknown type info: [" + CountlyFeedbackWidget.type + "]"); return; } - makeNetworkRequest("getFeedbackWidgetData,", url, data, responseCallback, true); /** @@ -3102,15 +3108,13 @@ } return; } - try { var response = JSON.parse(responseText); // return parsed response if (callback) { callback(response, null); } - } - catch (error) { + } catch (error) { log(logLevelEnums.ERROR, "getFeedbackWidgetData, Error while parsing feedback widgets list: " + error); if (callback) { callback(null, error); @@ -3133,28 +3137,20 @@ } // TODO: feedbackWidgetSegmentation implementation only assumes we want to send segmentation data. Change it if we add more data to the custom object. log(logLevelEnums.INFO, "present_feedback_widget, Presenting the feedback widget by appending to the element with ID: [ " + id + " ] and className: [ " + className + " ]"); - if (!this.check_consent(featureEnums.FEEDBACK)) { return; } - - if (!presentableFeedback - || (typeof presentableFeedback !== "object") - || Array.isArray(presentableFeedback) - ) { + if (!presentableFeedback || _typeof(presentableFeedback) !== "object" || Array.isArray(presentableFeedback)) { log(logLevelEnums.ERROR, "present_feedback_widget, Please provide at least one feedback widget object."); return; } - log(logLevelEnums.INFO, "present_feedback_widget, Adding segmentation to feedback widgets:[" + JSON.stringify(feedbackWidgetSegmentation) + "]"); - if (!feedbackWidgetSegmentation || typeof feedbackWidgetSegmentation !== "object" || Object.keys(feedbackWidgetSegmentation).length === 0) { + if (!feedbackWidgetSegmentation || _typeof(feedbackWidgetSegmentation) !== "object" || Object.keys(feedbackWidgetSegmentation).length === 0) { log(logLevelEnums.DEBUG, "present_feedback_widget, Segmentation is not an object or empty"); feedbackWidgetSegmentation = null; } - try { var url = this.url; - if (presentableFeedback.type === "nps") { log(logLevelEnums.DEBUG, "present_feedback_widget, Widget type: nps."); url += "/feedback/nps"; @@ -3171,7 +3167,6 @@ log(logLevelEnums.ERROR, "present_feedback_widget, Feedback widget only accepts nps, rating and survey types."); return; } - var passedOrigin = window.origin || window.location.origin; var feedbackWidgetFamily; @@ -3188,7 +3183,6 @@ loadCSS(this.url + "/surveys/stylesheets/countly-surveys.css"); feedbackWidgetFamily = "surveys"; } - url += "?widget_id=" + presentableFeedback._id; url += "&app_key=" + this.app_key; url += "&device_id=" + this.device_id; @@ -3205,12 +3199,10 @@ // Only web SDK passes origin and web url += "&origin=" + passedOrigin; url += "&widget_v=web"; - var iframe = document.createElement("iframe"); iframe.src = url; iframe.name = "countly-" + feedbackWidgetFamily + "-iframe"; iframe.id = "countly-" + feedbackWidgetFamily + "-iframe"; - var initiated = false; iframe.onload = function() { // This is used as a fallback for browsers where postMessage API doesn't work. @@ -3229,7 +3221,6 @@ initiated = true; log(logLevelEnums.DEBUG, "present_feedback_widget, Loaded iframe."); }; - var overlay = document.getElementById("csbg"); while (overlay) { // Remove any existing overlays @@ -3237,26 +3228,21 @@ overlay = document.getElementById("csbg"); log(logLevelEnums.DEBUG, "present_feedback_widget, Removing past overlay."); } - var wrapper = document.getElementsByClassName("countly-" + feedbackWidgetFamily + "-wrapper"); for (var i = 0; i < wrapper.length; i++) { // Remove any existing feedback wrappers wrapper[i].remove(); log(logLevelEnums.DEBUG, "present_feedback_widget, Removed a wrapper."); } - wrapper = document.createElement("div"); wrapper.className = "countly-" + feedbackWidgetFamily + "-wrapper"; wrapper.id = "countly-" + feedbackWidgetFamily + "-wrapper-" + presentableFeedback._id; - if (presentableFeedback.type === "survey") { // Set popup position wrapper.className = wrapper.className + " " + presentableFeedback.appearance.position; } - var element = document.body; var found = false; - if (id) { if (document.getElementById(id)) { element = document.getElementById(id); @@ -3266,7 +3252,6 @@ log(logLevelEnums.ERROR, "present_feedback_widget, Provided ID not found."); } } - if (!found) { // If the id element is not found check if a class was provided if (className) { @@ -3278,7 +3263,6 @@ } } } - element.insertAdjacentHTML("beforeend", ""); element.appendChild(wrapper); if (presentableFeedback.type === "rating") { @@ -3295,107 +3279,93 @@ document.getElementById("countly-ratings-wrapper-" + presentableFeedback._id).style.display = "none"; }); } - wrapper.appendChild(iframe); log(logLevelEnums.DEBUG, "present_feedback_widget, Appended the iframe"); - add_event_listener(window, "message", function(e) { var data = {}; try { data = JSON.parse(e.data); log(logLevelEnums.DEBUG, "present_feedback_widget, Parsed response message " + data); - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "present_feedback_widget, Error while parsing message body " + ex); } - if (!data.close) { log(logLevelEnums.DEBUG, "present_feedback_widget, Closing signal not sent yet"); return; } - document.getElementById("countly-" + feedbackWidgetFamily + "-wrapper-" + presentableFeedback._id).style.display = "none"; document.getElementById("csbg").style.display = "none"; }); - if (presentableFeedback.type === "survey") { var surveyShown = false; // Set popup show policy switch (presentableFeedback.showPolicy) { - case "afterPageLoad": - if (document.readyState === "complete") { - if (!surveyShown) { - surveyShown = true; - showSurvey(presentableFeedback); - } - } - else { - add_event_listener(document, "readystatechange", function(e) { - if (e.target.readyState === "complete") { - if (!surveyShown) { - surveyShown = true; - showSurvey(presentableFeedback); - } - } - }); - } - - break; - - case "afterConstantDelay": - setTimeout(function() { - if (!surveyShown) { - surveyShown = true; - showSurvey(presentableFeedback); - } - }, 10000); - - break; - - case "onAbandon": - if (document.readyState === "complete") { - add_event_listener(document, "mouseleave", function() { + case "afterPageLoad": + if (document.readyState === "complete") { if (!surveyShown) { surveyShown = true; showSurvey(presentableFeedback); } - }); - } - else { - add_event_listener(document, "readystatechange", function(e) { - if (e.target.readyState === "complete") { - add_event_listener(document, "mouseleave", function() { + } + else { + add_event_listener(document, "readystatechange", function(e) { + if (e.target.readyState === "complete") { if (!surveyShown) { surveyShown = true; showSurvey(presentableFeedback); } - }); - } - }); - } - - break; - - case "onScrollHalfwayDown": - add_event_listener(window, "scroll", function() { - if (!surveyShown) { - var scrollY = Math.max(window.scrollY, document.body.scrollTop, document.documentElement.scrollTop); - var documentHeight = getDocHeight(); - if (scrollY >= (documentHeight / 2)) { + } + }); + } + break; + case "afterConstantDelay": + setTimeout(function() { + if (!surveyShown) { surveyShown = true; showSurvey(presentableFeedback); } + }, 10000); + break; + case "onAbandon": + if (document.readyState === "complete") { + add_event_listener(document, "mouseleave", function() { + if (!surveyShown) { + surveyShown = true; + showSurvey(presentableFeedback); + } + }); + } + else { + add_event_listener(document, "readystatechange", function(e) { + if (e.target.readyState === "complete") { + add_event_listener(document, "mouseleave", function() { + if (!surveyShown) { + surveyShown = true; + showSurvey(presentableFeedback); + } + }); + } + }); + } + break; + case "onScrollHalfwayDown": + add_event_listener(window, "scroll", function() { + if (!surveyShown) { + var scrollY = Math.max(window.scrollY, document.body.scrollTop, document.documentElement.scrollTop); + var documentHeight = getDocHeight(); + if (scrollY >= documentHeight / 2) { + surveyShown = true; + showSurvey(presentableFeedback); + } + } + }); + break; + default: + if (!surveyShown) { + surveyShown = true; + showSurvey(presentableFeedback); } - }); - - break; - - default: - if (!surveyShown) { - surveyShown = true; - showSurvey(presentableFeedback); - } } } else if (presentableFeedback.type === "nps") { @@ -3404,7 +3374,6 @@ } else if (presentableFeedback.type === "rating") { var ratingShown = false; - if (document.readyState === "complete") { if (!ratingShown) { ratingShown = true; @@ -3422,8 +3391,7 @@ }); } } - } - catch (e) { + } catch (e) { log(logLevelEnums.ERROR, "present_feedback_widget, Something went wrong while presenting the widget: " + e); } @@ -3447,8 +3415,8 @@ // create sticker wrapper element var sticker = document.createElement("div"); sticker.innerText = feedback.appearance.text; - sticker.style.color = ((feedback.appearance.text_color.length < 7) ? "#" + feedback.appearance.text_color : feedback.appearance.text_color); - sticker.style.backgroundColor = ((feedback.appearance.bg_color.length < 7) ? "#" + feedback.appearance.bg_color : feedback.appearance.bg_color); + sticker.style.color = feedback.appearance.text_color.length < 7 ? "#" + feedback.appearance.text_color : feedback.appearance.text_color; + sticker.style.backgroundColor = feedback.appearance.bg_color.length < 7 ? "#" + feedback.appearance.bg_color : feedback.appearance.bg_color; sticker.className = "countly-feedback-sticker " + feedback.appearance.position + "-" + feedback.appearance.size; sticker.id = "countly-feedback-sticker-" + feedback._id; document.body.appendChild(sticker); @@ -3481,7 +3449,7 @@ // crashSegments, if not null, was set while enabling error tracking segments = segments || crashSegments; var error = ""; - if (typeof err === "object") { + if (_typeof(err) === "object") { if (typeof err.stack !== "undefined") { error = err.stack; } @@ -3507,7 +3475,7 @@ error = err + ""; } // character limit check - if (error.length > (self.maxStackTraceLineLength * self.maxStackTraceLinesPerThread)) { + if (error.length > self.maxStackTraceLineLength * self.maxStackTraceLinesPerThread) { log(logLevelEnums.DEBUG, "record_error, Error stack is too long will be truncated"); // convert error into an array split from each newline var splittedError = error.split("\n"); @@ -3524,56 +3492,51 @@ // turn modified array back into error string error = splittedError.join("\n"); } - - nonfatal = !!(nonfatal); + nonfatal = !!nonfatal; var metrics = getMetrics(); - var obj = { _resolution: metrics._resolution, _error: error, _app_version: metrics._app_version, _run: getTimestamp() - startTime }; - + var obj = { + _resolution: metrics._resolution, + _error: error, + _app_version: metrics._app_version, + _run: getTimestamp() - startTime + }; obj._not_os_specific = true; obj._javascript = true; - var battery = navigator.battery || navigator.webkitBattery || navigator.mozBattery || navigator.msBattery; if (battery) { obj._bat = Math.floor(battery.level * 100); } - if (typeof navigator.onLine !== "undefined") { - obj._online = !!(navigator.onLine); + obj._online = !!navigator.onLine; } - if (isBrowser) { - obj._background = !(document.hasFocus()); + obj._background = !document.hasFocus(); } - if (crashLogs.length > 0) { obj._logs = crashLogs.join("\n"); } crashLogs = []; - obj._nonfatal = nonfatal; - obj._view = this.getViewName(); - if (typeof segments !== "undefined") { // truncate custom crash segment's key value pairs segments = truncateObject(segments, self.maxKeyLength, self.maxValueSize, self.maxSegmentationValues, "record_error", log); obj._custom = segments; } - try { var canvas = document.createElement("canvas"); var gl = canvas.getContext("experimental-webgl"); obj._opengl = gl.getParameter(gl.VERSION); - } - catch (ex) { + } catch (ex) { log(logLevelEnums.ERROR, "Could not get the experimental-webgl context: " + ex); } // send userAgent string with the crash object incase it gets removed by a gateway var req = {}; req.crash = JSON.stringify(obj); - req.metrics = JSON.stringify({ _ua: metrics._ua }); - + req.metrics = JSON.stringify({ + _ua: metrics._ua + }); toRequestQueue(req); } }; @@ -3596,7 +3559,9 @@ function sendEventsForced() { if (eventQueue.length > 0) { log(logLevelEnums.DEBUG, "Flushing events"); - toRequestQueue({ events: JSON.stringify(eventQueue) }); + toRequestQueue({ + events: JSON.stringify(eventQueue) + }); eventQueue = []; setValueInStorage("cly_event", eventQueue); } @@ -3663,8 +3628,8 @@ stickerText.innerText = currentWidget.trigger_button_text; // create sticker wrapper element var sticker = document.createElement("div"); - sticker.style.color = ((currentWidget.trigger_font_color.length < 7) ? "#" + currentWidget.trigger_font_color : currentWidget.trigger_font_color); - sticker.style.backgroundColor = ((currentWidget.trigger_bg_color.length < 7) ? "#" + currentWidget.trigger_bg_color : currentWidget.trigger_bg_color); + sticker.style.color = currentWidget.trigger_font_color.length < 7 ? "#" + currentWidget.trigger_font_color : currentWidget.trigger_font_color; + sticker.style.backgroundColor = currentWidget.trigger_bg_color.length < 7 ? "#" + currentWidget.trigger_bg_color : currentWidget.trigger_bg_color; sticker.className = "countly-feedback-sticker " + currentWidget.trigger_position + "-" + currentWidget.trigger_size; sticker.id = "countly-feedback-sticker-" + currentWidget._id; svgIcon.appendChild(svgPath); @@ -3673,7 +3638,7 @@ document.body.appendChild(sticker); var smileySvg = document.getElementById("smileyPathInStickerSvg"); if (smileySvg) { - smileySvg.style.fill = ((currentWidget.trigger_font_color.length < 7) ? "#" + currentWidget.trigger_font_color : currentWidget.trigger_font_color); + smileySvg.style.fill = currentWidget.trigger_font_color.length < 7 ? "#" + currentWidget.trigger_font_color : currentWidget.trigger_font_color; } add_event_listener(document.getElementById("countly-feedback-sticker-" + currentWidget._id), "click", function() { document.getElementById("countly-iframe-wrapper-" + currentWidget._id).style.display = "block"; @@ -3684,8 +3649,7 @@ document.getElementById("countly-iframe-wrapper-" + currentWidget._id).style.display = "block"; document.getElementById("cfbg").style.display = "block"; } - } - catch (e) { + } catch (e) { log(logLevelEnums.ERROR, "Somethings went wrong while element injecting process: " + e); } } @@ -3720,7 +3684,7 @@ if (self.check_consent(featureEnums.VIEWS)) { add_cly_events({ key: internalEventKeyEnums.VIEW, - dur: (trackTime) ? getTimestamp() - lastViewTime : lastViewStoredDuration, + dur: trackTime ? getTimestamp() - lastViewTime : lastViewStoredDuration, segmentation: segments }, currentViewId); lastView = null; @@ -3748,7 +3712,7 @@ sessionStarted = false; self.begin_session(!autoExtend); } - setValueInStorage("cly_session", getTimestamp() + (sessionCookieTimeout * 60)); + setValueInStorage("cly_session", getTimestamp() + sessionCookieTimeout * 60); } } @@ -3763,28 +3727,29 @@ request.sdk_version = SDK_VERSION; request.t = deviceIdType; request.av = self.app_version; - var ua = getUA(); - if (!request.metrics) { // if metrics not provided pass useragent with this event - request.metrics = JSON.stringify({ _ua: ua }); + if (!request.metrics) { + // if metrics not provided pass useragent with this event + request.metrics = JSON.stringify({ + _ua: ua + }); } - else { // if metrics provided + else { + // if metrics provided var currentMetrics = JSON.parse(request.metrics); - if (!currentMetrics._ua) { // check if ua is present and if not add that + if (!currentMetrics._ua) { + // check if ua is present and if not add that currentMetrics._ua = ua; request.metrics = JSON.stringify(currentMetrics); } } - if (self.check_consent(featureEnums.LOCATION)) { if (self.country_code) { request.country_code = self.country_code; } - if (self.city) { request.city = self.city; } - if (self.ip_address !== null) { request.ip_address = self.ip_address; } @@ -3792,9 +3757,7 @@ else { request.location = ""; } - request.timestamp = getMsTimestamp(); - var date = new Date(); request.hour = date.getHours(); request.dow = date.getDay(); @@ -3810,18 +3773,14 @@ log(logLevelEnums.WARNING, "User is opt_out will ignore the request: " + request); return; } - if (!self.app_key || !self.device_id) { log(logLevelEnums.ERROR, "app_key or device_id is missing ", self.app_key, self.device_id); return; } - prepareRequest(request); - if (requestQueue.length > queueSize) { requestQueue.shift(); } - requestQueue.push(request); setValueInStorage("cly_queue", requestQueue, true); } @@ -3840,7 +3799,6 @@ log(logLevelEnums.WARNING, "User opt_out, no heartbeat"); return; } - hasPulse = true; var i = 0; // process queue @@ -3897,12 +3855,16 @@ // process event queue if (eventQueue.length > 0 && !self.test_mode_eq) { if (eventQueue.length <= maxEventBatch) { - toRequestQueue({ events: JSON.stringify(eventQueue) }); + toRequestQueue({ + events: JSON.stringify(eventQueue) + }); eventQueue = []; } else { var events = eventQueue.splice(0, maxEventBatch); - toRequestQueue({ events: JSON.stringify(events) }); + toRequestQueue({ + events: JSON.stringify(events) + }); } setValueInStorage("cly_event", eventQueue); } @@ -3921,16 +3883,15 @@ failTimeout = getTimestamp() + failTimeoutAmount; } else { - // remove first item from queue + // remove first item from queue requestQueue.shift(); } setValueInStorage("cly_queue", requestQueue, true); readyToProcess = true; - // expected response is only JSON object + // expected response is only JSON object }, false); } } - setTimeout(heartBeat, beatInterval); } @@ -3981,8 +3942,8 @@ // getting resolution if (isBrowser && screen.width) { - var width = (screen.width) ? parseInt(screen.width) : 0; - var height = (screen.height) ? parseInt(screen.height) : 0; + var width = screen.width ? parseInt(screen.width) : 0; + var height = screen.height ? parseInt(screen.height) : 0; if (width !== 0 && height !== 0) { var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform); if (iOS && window.devicePixelRatio) { @@ -4013,11 +3974,9 @@ if (typeof locale !== "undefined") { metrics._locale = metrics._locale || locale; } - if (isReferrerUsable()) { metrics._store = metrics._store || document.referrer; } - log(logLevelEnums.DEBUG, "Got metrics", metrics); return metrics; } @@ -4071,7 +4030,6 @@ } } } - return isReferrerLegit; } @@ -4084,7 +4042,7 @@ function log(level, message) { if (self.debug && typeof console !== "undefined") { // parse the arguments into a string if it is an object - if (arguments[2] && typeof arguments[2] === "object") { + if (arguments[2] && _typeof(arguments[2]) === "object") { arguments[2] = JSON.stringify(arguments[2]); } // append app_key to the start of the message if it is not the first instance (for multi instancing) @@ -4213,8 +4171,7 @@ else { xhr.send(data); } - } - catch (e) { + } catch (e) { // fallback log(logLevelEnums.ERROR, functionName + " Something went wrong while making an XML HTTP request: " + e); if (typeof callback === "function") { @@ -4235,15 +4192,15 @@ function sendFetchRequest(functionName, url, params, callback, useBroadResponseValidator) { useBroadResponseValidator = useBroadResponseValidator || false; var response; - try { log(logLevelEnums.DEBUG, "Sending Fetch request"); // Prepare request options var method = "GET"; - var headers = { "Content-type": "application/x-www-form-urlencoded" }; + var headers = { + "Content-type": "application/x-www-form-urlencoded" + }; var body = null; - params = params || {}; if (self.force_post || prepareParams(params).length >= 2000) { method = "POST"; @@ -4262,7 +4219,7 @@ fetch(url, { method: method, headers: headers, - body: body, + body: body }).then(function(res) { response = res; return response.text(); @@ -4275,7 +4232,6 @@ else { isResponseValidated = isResponseValid(response.status, data); } - if (isResponseValidated) { if (typeof callback === "function") { callback(false, params, data); @@ -4290,14 +4246,13 @@ callback(true, params, response.status, data); } } - }).catch(function(error) { + })["catch"](function(error) { log(logLevelEnums.ERROR, functionName + " Failed Fetch request: " + error); if (typeof callback === "function") { callback(true, params); } }); - } - catch (e) { + } catch (e) { // fallback log(logLevelEnums.ERROR, functionName + " Something went wrong with the Fetch request attempt: " + e); if (typeof callback === "function") { @@ -4331,10 +4286,8 @@ log(logLevelEnums.ERROR, "Http response is not JSON Object"); return false; } - - return !!(parsedResponse.result); - } - catch (e) { + return !!parsedResponse.result; + } catch (e) { log(logLevelEnums.ERROR, "Http response is not JSON: " + e); return false; } @@ -4360,15 +4313,14 @@ try { var parsedResponse = JSON.parse(str); // check if parsed response is a JSON object or JSON array, if not it is not valid - if ((Object.prototype.toString.call(parsedResponse) !== "[object Object]") && (!Array.isArray(parsedResponse))) { + if (Object.prototype.toString.call(parsedResponse) !== "[object Object]" && !Array.isArray(parsedResponse)) { log(logLevelEnums.ERROR, "Http response is not JSON Object nor JSON Array"); return false; } // request should be accepted even if does not have result field return true; - } - catch (e) { + } catch (e) { log(logLevelEnums.ERROR, "Http response is not JSON: " + e); return false; } @@ -4400,9 +4352,7 @@ isScrollRegistryOpen = false; var height = getDocHeight(); var width = getDocWidth(); - var viewportHeight = getViewportHeight(); - if (self.check_consent(featureEnums.SCROLLS)) { var segments = { type: "scroll", @@ -4411,7 +4361,7 @@ height: height, view: self.getViewUrl() }; - // truncate new segment + // truncate new segment segments = truncateObject(segments, self.maxKeyLength, self.maxValueSize, self.maxSegmentationValues, "processScrollView", log); if (self.track_domains) { segments.domain = window.location.hostname; @@ -4504,7 +4454,7 @@ */ function createCookie(cookieKey, cookieVal, exp) { var date = new Date(); - date.setTime(date.getTime() + (exp * 24 * 60 * 60 * 1000)); + date.setTime(date.getTime() + exp * 24 * 60 * 60 * 1000); // TODO: If we offer the developer the ability to manipulate the expiration date in the future, this part must be reworked var expires = "; expires=" + date.toGMTString(); document.cookie = cookieKey + "=" + cookieVal + expires + "; path=/"; @@ -4520,7 +4470,7 @@ */ function getValueFromStorage(key, useLocalStorage, useRawKey) { // check if we should use storage at all. If in worker context but no storage is available, return early - if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) { + if (self.storage === "none" || _typeof(self.storage) !== "object" && !isBrowser) { log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: [" + key + "] won't be retrieved"); return; } @@ -4532,10 +4482,9 @@ key = stripTrailingSlash(self.namespace) + "/" + key; } } - var data; // use dev provided storage if available - if (typeof self.storage === "object" && typeof self.storage.getItem === "function") { + if (_typeof(self.storage) === "object" && typeof self.storage.getItem === "function") { data = self.storage.getItem(key); return key.endsWith("cly_id") ? data : self.deserialize(data); } @@ -4546,10 +4495,12 @@ } // Get value - if (useLocalStorage) { // Native support + if (useLocalStorage) { + // Native support data = localStorage.getItem(key); } - else if (self.storage !== "localstorage") { // Use cookie + else if (self.storage !== "localstorage") { + // Use cookie data = readCookie(key); } @@ -4557,7 +4508,6 @@ if (key.endsWith("cly_id")) { return data; } - return self.deserialize(data); } @@ -4571,7 +4521,7 @@ */ function setValueInStorage(key, value, useLocalStorage, useRawKey) { // check if we should use storage options at all - if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) { + if (self.storage === "none" || _typeof(self.storage) !== "object" && !isBrowser) { log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: " + key + " won't be stored"); return; } @@ -4583,10 +4533,9 @@ key = stripTrailingSlash(self.namespace) + "/" + key; } } - if (typeof value !== "undefined" && value !== null) { // use dev provided storage if available - if (typeof self.storage === "object" && typeof self.storage.setItem === "function") { + if (_typeof(self.storage) === "object" && typeof self.storage.setItem === "function") { self.storage.setItem(key, value); return; } @@ -4595,13 +4544,14 @@ if (useLocalStorage === undefined) { useLocalStorage = lsSupport; } - value = self.serialize(value); // Set the store - if (useLocalStorage) { // Native support + if (useLocalStorage) { + // Native support localStorage.setItem(key, value); } - else if (self.storage !== "localstorage") { // Use Cookie + else if (self.storage !== "localstorage") { + // Use Cookie createCookie(key, value, 30); } } @@ -4616,7 +4566,7 @@ */ function removeValueFromStorage(key, useLocalStorage, useRawKey) { // check if we should use storage options at all - if (self.storage === "none" || (typeof self.storage !== "object" && !isBrowser)) { + if (self.storage === "none" || _typeof(self.storage) !== "object" && !isBrowser) { log(logLevelEnums.DEBUG, "Storage is disabled. Value with key: " + key + " won't be removed"); return; } @@ -4630,7 +4580,7 @@ } // use dev provided storage if available - if (typeof self.storage === "object" && typeof self.storage.removeItem === "function") { + if (_typeof(self.storage) === "object" && typeof self.storage.removeItem === "function") { self.storage.removeItem(key); return; } @@ -4639,11 +4589,12 @@ if (useLocalStorage === undefined) { useLocalStorage = lsSupport; } - - if (useLocalStorage) { // Native support + if (useLocalStorage) { + // Native support localStorage.removeItem(key); } - else if (self.storage !== "localstorage") { // Use cookie + else if (self.storage !== "localstorage") { + // Use cookie createCookie(key, "", -1); } } @@ -4696,28 +4647,27 @@ log(logLevelEnums.DEBUG, "onStorageChange, Applying storage changes for key:", key); log(logLevelEnums.DEBUG, "onStorageChange, Applying storage changes for value:", newValue); switch (key) { - // queue of requests - case "cly_queue": - requestQueue = self.deserialize(newValue || "[]"); - break; + // queue of requests + case "cly_queue": + requestQueue = self.deserialize(newValue || "[]"); + break; // queue of events - case "cly_event": - eventQueue = self.deserialize(newValue || "[]"); - break; - case "cly_remote_configs": - remoteConfigs = self.deserialize(newValue || "{}"); - break; - case "cly_ignore": - self.ignore_visitor = self.deserialize(newValue); - break; - case "cly_id": - self.device_id = newValue; - break; - case "cly_id_type": - deviceIdType = self.deserialize(newValue); - break; - default: - // do nothing + case "cly_event": + eventQueue = self.deserialize(newValue || "[]"); + break; + case "cly_remote_configs": + remoteConfigs = self.deserialize(newValue || "{}"); + break; + case "cly_ignore": + self.ignore_visitor = self.deserialize(newValue); + break; + case "cly_id": + self.device_id = newValue; + break; + case "cly_id_type": + deviceIdType = self.deserialize(newValue); + break; + // do nothing } }; @@ -4784,7 +4734,7 @@ * Clear queued data * @memberof Countly._internals */ - clearQueue: function() { + clearQueue: function clearQueue() { requestQueue = []; setValueInStorage("cly_queue", []); eventQueue = []; @@ -4794,7 +4744,7 @@ * For testing pusposes only * @returns {Object} - returns the local queues */ - getLocalQueues: function() { + getLocalQueues: function getLocalQueues() { return { eventQ: eventQueue, requestQ: requestQueue @@ -4876,7 +4826,9 @@ // prepare request var request = { hc: JSON.stringify(hc), - metrics: JSON.stringify({ _app_version: self.app_version }) + metrics: JSON.stringify({ + _app_version: self.app_version + }) }; // add common request params prepareRequest(request); @@ -4892,12 +4844,8 @@ // initialize Countly Class this.initialize(); - }; + }); - /** - * Countly class - exposing so plugins can extend its prototype - * @param {Object} ob - Configuration object - */ Countly.CountlyClass = CountlyClass; /** @@ -4977,7 +4925,7 @@ } var appKey = conf.app_key || Countly.app_key; if (!Countly.i || !Countly.i[appKey]) { - var inst = new Countly.CountlyClass(conf); + var inst = new CountlyClass(conf); if (!Countly.i) { Countly.i = {}; for (var key in inst) { @@ -5132,7 +5080,6 @@ // Append boomerang script to the head document.getElementsByTagName("head")[0].appendChild(boomerangScript); document.getElementsByTagName("head")[0].appendChild(countlyBoomerangScript); - var boomLoaded = false; var countlyBoomLoaded = false; boomerangScript.onload = function() { @@ -5141,14 +5088,13 @@ countlyBoomerangScript.onload = function() { countlyBoomLoaded = true; }; - var timeoutCounter = 0; var intervalDuration = 50; var timeoutLimit = 1500; // TODO: Configurable? Mb with Countly.apmScriptLoadTimeout? // init Countly only after boomerang is loaded var intervalID = setInterval(function() { timeoutCounter += intervalDuration; - if ((boomLoaded && countlyBoomLoaded) || (timeoutCounter >= timeoutLimit)) { + if (boomLoaded && countlyBoomLoaded || timeoutCounter >= timeoutLimit) { if (Countly.debug) { var message = "BoomerangJS loaded:[" + boomLoaded + "], countly_boomerang loaded:[" + countlyBoomLoaded + "]."; if (boomLoaded && countlyBoomLoaded) { @@ -5196,8 +5142,7 @@ // timestamp in milliseconds var timestamp = Date.now().toString(); - - return (id + timestamp); + return id + timestamp; } /** @@ -5223,7 +5168,7 @@ var regex = new RegExp(pattern, "g"); return str.replace(regex, function(c) { var r = (d + Math.random() * 16) % 16 | 0; - return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16); + return (c === "x" ? r : r & 0x3 | 0x8).toString(16); }); } @@ -5235,7 +5180,6 @@ function getTimestamp() { return Math.floor(new Date().getTime() / 1000); } - var lastMsTs = 0; /** * Get unique timestamp in milliseconds @@ -5421,7 +5365,7 @@ * @param {String} nodeName - tag/node name * @returns {HTMLElement} closest parent element */ - var get_closest_element = function(el, nodeName) { + function get_closest_element(el, nodeName) { nodeName = nodeName.toUpperCase(); while (el) { if (el.nodeName.toUpperCase() === nodeName) { @@ -5429,7 +5373,7 @@ } el = el.parentElement; } - }; + } /** * Listen to specific browser event @@ -5438,11 +5382,12 @@ * @param {String} type - event name or action * @param {Function} listener - callback when event is fired */ - var add_event_listener = function(element, type, listener) { + function add_event_listener(element, type, listener) { if (!isBrowser) { return; } - if (element === null || typeof element === "undefined") { // element can be null so lets check it first + if (element === null || typeof element === "undefined") { + // element can be null so lets check it first if (checkIfLoggingIsOn()) { // eslint-disable-next-line no-console console.warn("[WARNING] [Countly] add_event_listener, Can't bind [" + type + "] event to nonexisting element"); @@ -5456,7 +5401,7 @@ else { element.attachEvent("on" + type, listener); } - }; + } /** * Get element that fired event @@ -5464,7 +5409,7 @@ * @param {Event} event - event that was filed * @returns {HTMLElement} HTML element that caused event to fire */ - var get_event_target = function(event) { + function get_event_target(event) { if (!event) { return window.event.srcElement; } @@ -5472,7 +5417,7 @@ return event.target; } return event.srcElement; - }; + } /** * Returns raw user agent string @@ -5484,7 +5429,6 @@ if (uaOverride) { return uaOverride; } - var ua_raw = navigator.userAgent; // check if userAgentData is supported and userAgent is not available, use it if (!ua_raw) { @@ -5494,7 +5438,7 @@ return e.brand + ":" + e.version; }).join(); // add mobile info - ua_raw += (navigator.userAgentData.mobile ? " mobi " : " "); + ua_raw += navigator.userAgentData.mobile ? " mobi " : " "; // add platform info ua_raw += navigator.userAgentData.platform; } @@ -5564,9 +5508,7 @@ */ function get_page_coord(e) { // checking if pageY and pageX is already available - if (typeof e.pageY === "undefined" - && typeof e.clientX === "number" - && document.documentElement) { + if (typeof e.pageY === "undefined" && typeof e.clientX === "number" && document.documentElement) { // if not, then add scrolling positions e.pageX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; e.pageY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; @@ -5582,11 +5524,7 @@ */ function getDocHeight() { var D = document; - return Math.max( - Math.max(D.body.scrollHeight, D.documentElement.scrollHeight), - Math.max(D.body.offsetHeight, D.documentElement.offsetHeight), - Math.max(D.body.clientHeight, D.documentElement.clientHeight) - ); + return Math.max(Math.max(D.body.scrollHeight, D.documentElement.scrollHeight), Math.max(D.body.offsetHeight, D.documentElement.offsetHeight), Math.max(D.body.clientHeight, D.documentElement.clientHeight)); } /** @@ -5596,11 +5534,7 @@ */ function getDocWidth() { var D = document; - return Math.max( - Math.max(D.body.scrollWidth, D.documentElement.scrollWidth), - Math.max(D.body.offsetWidth, D.documentElement.offsetWidth), - Math.max(D.body.clientWidth, D.documentElement.clientWidth) - ); + return Math.max(Math.max(D.body.scrollWidth, D.documentElement.scrollWidth), Math.max(D.body.offsetWidth, D.documentElement.offsetWidth), Math.max(D.body.clientWidth, D.documentElement.clientWidth)); } /** @@ -5610,11 +5544,7 @@ */ function getViewportHeight() { var D = document; - return Math.min( - Math.min(D.body.clientHeight, D.documentElement.clientHeight), - Math.min(D.body.offsetHeight, D.documentElement.offsetHeight), - window.innerHeight - ); + return Math.min(Math.min(D.body.clientHeight, D.documentElement.clientHeight), Math.min(D.body.offsetHeight, D.documentElement.offsetHeight), window.innerHeight); } /** @@ -5629,7 +5559,7 @@ * Monitor parallel storage changes like other opened tabs */ if (isBrowser) { - window.addEventListener("storage", function(e) { + window.addEventListener("storage", function (e) { var parts = (e.key + "").split("/"); var key = parts.pop(); var appKey = parts.pop(); @@ -5653,7 +5583,7 @@ var loaded; fileRef.setAttribute(attr, type); fileRef.setAttribute(src, data); - var callbackFunction = function() { + var callbackFunction = function callbackFunction() { if (!loaded) { callback(); } @@ -5696,9 +5626,7 @@ } var loader = document.getElementById("cly-loader"); if (!loader) { - var css = "#cly-loader {height: 4px; width: 100%; position: absolute; z-index: 99999; overflow: hidden; background-color: #fff; top:0px; left:0px;}" - + "#cly-loader:before{display: block; position: absolute; content: ''; left: -200px; width: 200px; height: 4px; background-color: #2EB52B; animation: cly-loading 2s linear infinite;}" - + "@keyframes cly-loading { from {left: -200px; width: 30%;} 50% {width: 30%;} 70% {width: 70%;} 80% { left: 50%;} 95% {left: 120%;} to {left: 100%;}}"; + var css = "#cly-loader {height: 4px; width: 100%; position: absolute; z-index: 99999; overflow: hidden; background-color: #fff; top:0px; left:0px;}" + "#cly-loader:before{display: block; position: absolute; content: ''; left: -200px; width: 200px; height: 4px; background-color: #2EB52B; animation: cly-loading 2s linear infinite;}" + "@keyframes cly-loading { from {left: -200px; width: 30%;} 50% {width: 30%;} 70% {width: 70%;} 80% { left: 50%;} 95% {left: 120%;} to {left: 100%;}}"; var head = document.head || document.getElementsByTagName("head")[0]; var style = document.createElement("style"); style.type = "text/css"; @@ -5722,8 +5650,7 @@ } try { document.body.appendChild(loader); - } - catch (e) { + } catch (e) { if (checkIfLoggingIsOn()) { // eslint-disable-next-line no-console console.error("[ERROR] [Countly] showLoader, Body is not loaded for loader to append: " + e); @@ -5770,7 +5697,7 @@ * */ Countly.serialize = function(value) { // Convert object values to JSON - if (typeof value === "object") { + if (_typeof(value) === "object") { value = JSON.stringify(value); } return value; @@ -5782,20 +5709,19 @@ * @return {varies} deserialized value * */ Countly.deserialize = function(data) { - if (data === "") { // we expect string or null only. Empty sting would throw an error. + if (data === "") { + // we expect string or null only. Empty sting would throw an error. return data; } // Try to parse JSON... try { data = JSON.parse(data); - } - catch (e) { + } catch (e) { if (checkIfLoggingIsOn()) { // eslint-disable-next-line no-console console.warn("[WARNING] [Countly] deserialize, Could not parse the file:[" + data + "], error: " + e); } } - return data; }; @@ -5841,5 +5767,10 @@ SDK_GENERATED: DeviceIdTypeInternalEnums.SDK_GENERATED, TEMPORARY_ID: DeviceIdTypeInternalEnums.TEMPORARY_ID }; - return Countly; -})); + + + exports.default = Countly; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); \ No newline at end of file diff --git a/lib/countly.min.js b/lib/countly.min.js index 659a0ddb..48604067 100644 --- a/lib/countly.min.js +++ b/lib/countly.min.js @@ -1,151 +1,157 @@ -(function(n,ta){"function"===typeof define&&define.amd?define([],function(){return ta(n.Countly)}):"object"===typeof module&&module.exports?module.exports=ta(n.Countly):n.Countly=ta(n.Countly)})("undefined"!==typeof window?window:this,function(n){function ta(h){var p=document.createElement("script"),u=document.createElement("script");p.async=!0;u.async=!0;p.src=n.customSourceBoomerang||ob.BOOMERANG_SRC;u.src=n.customSourceCountlyBoomerang||ob.CLY_BOOMERANG_SRC;document.getElementsByTagName("head")[0].appendChild(p); -document.getElementsByTagName("head")[0].appendChild(u);var A=!1,B=!1;p.onload=function(){A=!0};u.onload=function(){B=!0};var L=0,T=setInterval(function(){L+=50;if(A&&B||1500<=L){if(n.debug){var R="BoomerangJS loaded:["+A+"], countly_boomerang loaded:["+B+"].";A&&B?console.log("[DEBUG] "+R):console.warn("[WARNING] "+R+" Initializing without APM.")}n.init(h);clearInterval(T)}},50)}function pb(h){var p=[];if("undefined"!==typeof h.options)for(var u=0;u'),this.initializeRatingWidgets(a)):b(d.ERROR,"enableRatingWidgets, You should provide at least one widget id as param. Read documentation for more detail. https://resources.count.ly/plugins/feedback")))};this.get_available_feedback_widgets=function(a){b(d.INFO,"get_available_feedback_widgets, Getting the feedback list, callback function is provided:["+ -!!a+"]");this.check_consent("feedback")?H?b(d.ERROR,"get_available_feedback_widgets, Cannot enable feedback widgets in offline mode."):aa("get_available_feedback_widgets,",this.url+Ma,{method:"feedback",device_id:this.device_id,app_key:this.app_key,av:f.app_version},function(c,e,k){if(c)b(d.ERROR,"get_available_feedback_widgets, Error occurred while fetching feedbacks: "+c),a&&a(null,c);else try{var l=JSON.parse(k).result||[];a&&a(l,null)}catch(g){b(d.ERROR,"get_available_feedback_widgets, Error while parsing feedback widgets list: "+ -g),a&&a(null,g)}},!1):a&&a(null,Error("Consent for feedback not provided."))};this.getFeedbackWidgetData=function(a,c){if(a.type)if(b(d.INFO,"getFeedbackWidgetData, Retrieving data for: ["+JSON.stringify(a)+"], callback function is provided:["+!!c+"]"),this.check_consent("feedback"))if(H)b(d.ERROR,"getFeedbackWidgetData, Cannot enable feedback widgets in offline mode.");else{var e=this.url,k={widget_id:a._id,shown:1,sdk_version:"23.6.3",sdk_name:"javascript_native_web",platform:this.platform,app_version:this.app_version}; -if("nps"===a.type)e+="/o/surveys/nps/widget";else if("survey"===a.type)e+="/o/surveys/survey/widget";else if("rating"===a.type)e+="/o/surveys/rating/widget";else{b(d.ERROR,"getFeedbackWidgetData, Unknown type info: ["+a.type+"]");return}aa("getFeedbackWidgetData,",e,k,function(l,g,m){if(l)b(d.ERROR,"getFeedbackWidgetData, Error occurred while fetching feedbacks: "+l),c&&c(null,l);else try{var q=JSON.parse(m);c&&c(q,null)}catch(t){b(d.ERROR,"getFeedbackWidgetData, Error while parsing feedback widgets list: "+ -t),c&&c(null,t)}},!0)}else c&&c(null,Error("Consent for feedback not provided."));else b(d.ERROR,"getFeedbackWidgetData, Expected the provided widget object to have a type but got: ["+JSON.stringify(a)+"], aborting.")};this.present_feedback_widget=function(a,c,e,k){function l(z){document.getElementById("countly-surveys-wrapper-"+z._id).style.display="block";document.getElementById("csbg").style.display="block"}function g(z){if(!z.appearance.hideS){b(d.DEBUG,"present_feedback_widget, handling the sticker as it was not set to hidden"); -var Q=document.createElement("div");Q.innerText=z.appearance.text;Q.style.color=7>z.appearance.text_color.length?"#"+z.appearance.text_color:z.appearance.text_color;Q.style.backgroundColor=7>z.appearance.bg_color.length?"#"+z.appearance.bg_color:z.appearance.bg_color;Q.className="countly-feedback-sticker "+z.appearance.position+"-"+z.appearance.size;Q.id="countly-feedback-sticker-"+z._id;document.body.appendChild(Q);y(document.getElementById("countly-feedback-sticker-"+z._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+ -z._id).style.display="flex";document.getElementById("csbg").style.display="block"})}y(document.getElementById("countly-feedback-close-icon-"+z._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+z._id).style.display="none";document.getElementById("csbg").style.display="none"})}b(d.INFO,"present_feedback_widget, Presenting the feedback widget by appending to the element with ID: [ "+c+" ] and className: [ "+e+" ]");if(this.check_consent("feedback"))if(!a||"object"!==typeof a|| -Array.isArray(a))b(d.ERROR,"present_feedback_widget, Please provide at least one feedback widget object.");else{b(d.INFO,"present_feedback_widget, Adding segmentation to feedback widgets:["+JSON.stringify(k)+"]");k&&"object"===typeof k&&0!==Object.keys(k).length||(b(d.DEBUG,"present_feedback_widget, Segmentation is not an object or empty"),k=null);try{var m=this.url;if("nps"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: nps."),m+="/feedback/nps";else if("survey"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: survey."), -m+="/feedback/survey";else if("rating"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: rating."),m+="/feedback/rating";else{b(d.ERROR,"present_feedback_widget, Feedback widget only accepts nps, rating and survey types.");return}var q=window.origin||window.location.origin;if("rating"===a.type){b(d.DEBUG,"present_feedback_widget, Loading css for rating widget.");var t="ratings";Ka(this.url+"/star-rating/stylesheets/countly-feedback-web.css")}else b(d.DEBUG,"present_feedback_widget, Loading css for survey or nps."), -Ka(this.url+"/surveys/stylesheets/countly-surveys.css"),t="surveys";m+="?widget_id="+a._id;m+="&app_key="+this.app_key;m+="&device_id="+this.device_id;m+="&sdk_name=javascript_native_web";m+="&platform="+this.platform;m+="&app_version="+this.app_version;m+="&sdk_version=23.6.3";if(k){var K={};K.sg=k;m+="&custom="+JSON.stringify(K)}m+="&origin="+q;m+="&widget_v=web";var N=document.createElement("iframe");N.src=m;N.name="countly-"+t+"-iframe";N.id="countly-"+t+"-iframe";var ka=!1;N.onload=function(){ka&& -(document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="none",document.getElementById("csbg").style.display="none");ka=!0;b(d.DEBUG,"present_feedback_widget, Loaded iframe.")};for(var ya=document.getElementById("csbg");ya;)ya.remove(),ya=document.getElementById("csbg"),b(d.DEBUG,"present_feedback_widget, Removing past overlay.");var X=document.getElementsByClassName("countly-"+t+"-wrapper");for(k=0;k');Xa.appendChild(X);if("rating"===a.type){var nb=document.createElement("div");nb.className="countly-ratings-overlay";nb.id="countly-ratings-overlay-"+a._id;X.appendChild(nb);b(d.DEBUG,"present_feedback_widget, appended the rating overlay to wrapper");y(document.getElementById("countly-ratings-overlay-"+a._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+a._id).style.display="none"})}X.appendChild(N);b(d.DEBUG,"present_feedback_widget, Appended the iframe"); -y(window,"message",function(z){var Q={};try{Q=JSON.parse(z.data),b(d.DEBUG,"present_feedback_widget, Parsed response message "+Q)}catch(Lb){b(d.ERROR,"present_feedback_widget, Error while parsing message body "+Lb)}Q.close?(document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="none",document.getElementById("csbg").style.display="none"):b(d.DEBUG,"present_feedback_widget, Closing signal not sent yet")});if("survey"===a.type){var M=!1;switch(a.showPolicy){case "afterPageLoad":"complete"=== -document.readyState?M||(M=!0,l(a)):y(document,"readystatechange",function(z){"complete"!==z.target.readyState||M||(M=!0,l(a))});break;case "afterConstantDelay":setTimeout(function(){M||(M=!0,l(a))},1E4);break;case "onAbandon":"complete"===document.readyState?y(document,"mouseleave",function(){M||(M=!0,l(a))}):y(document,"readystatechange",function(z){"complete"===z.target.readyState&&y(document,"mouseleave",function(){M||(M=!0,l(a))})});break;case "onScrollHalfwayDown":y(window,"scroll",function(){if(!M){var z= -Math.max(window.scrollY,document.body.scrollTop,document.documentElement.scrollTop),Q=Ja();z>=Q/2&&(M=!0,l(a))}});break;default:M||(M=!0,l(a))}}else if("nps"===a.type)document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="block",document.getElementById("csbg").style.display="block";else if("rating"===a.type){var Ya=!1;"complete"===document.readyState?Ya||(Ya=!0,g(a)):y(document,"readystatechange",function(z){"complete"!==z.target.readyState||Ya||(Ya=!0,g(a))})}}catch(z){b(d.ERROR, -"present_feedback_widget, Something went wrong while presenting the widget: "+z)}}};this.recordError=function(a,c,e){b(d.INFO,"recordError, Recording error");if(this.check_consent("crashes")&&a){e=e||jb;var k="";"object"===typeof a?"undefined"!==typeof a.stack?k=a.stack:("undefined"!==typeof a.name&&(k+=a.name+":"),"undefined"!==typeof a.message&&(k+=a.message+"\n"),"undefined"!==typeof a.fileName&&(k+="in "+a.fileName+"\n"),"undefined"!==typeof a.lineNumber&&(k+="on "+a.lineNumber),"undefined"!== -typeof a.columnNumber&&(k+=":"+a.columnNumber)):k=a+"";if(k.length>f.maxStackTraceLineLength*f.maxStackTraceLinesPerThread){b(d.DEBUG,"record_error, Error stack is too long will be truncated");a=k.split("\n");a.length>f.maxStackTraceLinesPerThread&&(a=a.splice(0,f.maxStackTraceLinesPerThread));k=0;for(var l=a.length;k f.maxStackTraceLineLength&&(a[k]=a[k].substring(0,f.maxStackTraceLineLength));k=a.join("\n")}c=!!c;a=La();k={_resolution:a._resolution,_error:k,_app_version:a._app_version, -_run:E()-Hb,_not_os_specific:!0,_javascript:!0};if(l=navigator.battery||navigator.webkitBattery||navigator.mozBattery||navigator.msBattery)k._bat=Math.floor(100*l.level);"undefined"!==typeof navigator.onLine&&(k._online=!!navigator.onLine);k._background=!document.hasFocus();0 =l?Na++:Na=l;return Na}function u(l,k,q){if(k&&Object.keys(k).length){if("undefined"!==typeof k[l])return k[l]}else if("undefined"!==typeof p[l])return p[l];return q}function gb(l,k,q){for(var v in p.i)p.i[v].tracking_crashes&&p.i[v].recordError(l,k,q)}function wa(l){var k=[],q;for(q in l)k.push(q+"="+encodeURIComponent(l[q]));return k.join("&")}function sa(l){return"string"=== +typeof l&&"/"===l.substring(l.length-1)?l.substring(0,l.length-1):l}function xa(l,k){for(var q={},v,G=0,Q=k.length;G v){var U={},ya=0,ma;for(ma in l)yak&&(G=l.substring(0,k),v(d.DEBUG,q+", Key: [ "+ +l+" ] is longer than accepted length. It will be truncated."));return G}function A(l,k,q){x&&(null===l||"undefined"===typeof l?Aa()&&console.warn("[WARNING] [Countly] add_event_listener, Can't bind ["+k+"] event to nonexisting element"):"undefined"!==typeof l.addEventListener?l.addEventListener(k,q,!1):l.attachEvent("on"+k,q))}function Oa(l){return l?"undefined"!==typeof l.target?l.target:l.srcElement:window.event.srcElement}function ta(l){if(l)return l;l=navigator.userAgent;!l&&navigator.userAgentData&& +(l=navigator.userAgentData.brands.map(function(k){return k.brand+":"+k.version}).join(),l+=navigator.userAgentData.mobile?" mobi ":" ",l+=navigator.userAgentData.platform);return l}function zb(l){if(!l){if(navigator.userAgentData.mobile)return"phone";l=ta()}l=l.toLowerCase();var k="desktop",q=/(mobi|ipod|phone|blackberry|opera mini|fennec|minimo|symbian|psp|nintendo ds|archos|skyfire|puffin|blazer|bolt|gobrowser|iris|maemo|semc|teashark|uzard)/;/(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(l)? +k="tablet":q.test(l)&&(k="phone");return k}function Ab(l){return/(CountlySiteBot|nuhk|Googlebot|GoogleSecurityScanner|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver|bingbot|Google Web Preview|Mediapartners-Google|AdsBot-Google|Baiduspider|Ezooms|YahooSeeker|AltaVista|AVSearch|Mercator|Scooter|InfoSeek|Ultraseek|Lycos|Wget|YandexBot|Yandex|YaDirectFetcher|SiteBot|Exabot|AhrefsBot|MJ12bot|TurnitinBot|magpie-crawler|Nutch Crawler|CMS Crawler|rogerbot|Domnutch|ssearch_bot|XoviBot|netseer|digincore|fr-crawler|wesee|AliasIO|contxbot|PingdomBot|BingPreview|HeadlessChrome)/.test(l|| +ta())}function hb(l){"undefined"===typeof l.pageY&&"number"===typeof l.clientX&&document.documentElement&&(l.pageX=l.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,l.pageY=l.clientY+document.body.scrollTop+document.documentElement.scrollTop);return l}function Pa(){var l=document;return Math.max(Math.max(l.body.scrollHeight,l.documentElement.scrollHeight),Math.max(l.body.offsetHeight,l.documentElement.offsetHeight),Math.max(l.body.clientHeight,l.documentElement.clientHeight))} +function ib(){var l=document;return Math.max(Math.max(l.body.scrollWidth,l.documentElement.scrollWidth),Math.max(l.body.offsetWidth,l.documentElement.offsetWidth),Math.max(l.body.clientWidth,l.documentElement.clientWidth))}function Bb(){var l=document;return Math.min(Math.min(l.body.clientHeight,l.documentElement.clientHeight),Math.min(l.body.offsetHeight,l.documentElement.offsetHeight),window.innerHeight)}function Cb(l,k,q,v,G,Q){l=document.createElement(l);var O;l.setAttribute(k,q);l.setAttribute(v, +G);k=function(){O||Q();O=!0};Q&&(l.onreadystatechange=k,l.onload=k);document.getElementsByTagName("head")[0].appendChild(l)}function Db(l,k){Cb("script","type","text/javascript","src",l,k)}function Qa(l,k){Cb("link","rel","stylesheet","href",l,k)}function Eb(){if(x){var l=document.getElementById("cly-loader");if(!l){var k=document.head||document.getElementsByTagName("head")[0],q=document.createElement("style");q.type="text/css";q.styleSheet?q.styleSheet.cssText="#cly-loader {height: 4px; width: 100%; position: absolute; z-index: 99999; overflow: hidden; background-color: #fff; top:0px; left:0px;}#cly-loader:before{display: block; position: absolute; content: ''; left: -200px; width: 200px; height: 4px; background-color: #2EB52B; animation: cly-loading 2s linear infinite;}@keyframes cly-loading { from {left: -200px; width: 30%;} 50% {width: 30%;} 70% {width: 70%;} 80% { left: 50%;} 95% {left: 120%;} to {left: 100%;}}": +q.appendChild(document.createTextNode("#cly-loader {height: 4px; width: 100%; position: absolute; z-index: 99999; overflow: hidden; background-color: #fff; top:0px; left:0px;}#cly-loader:before{display: block; position: absolute; content: ''; left: -200px; width: 200px; height: 4px; background-color: #2EB52B; animation: cly-loading 2s linear infinite;}@keyframes cly-loading { from {left: -200px; width: 30%;} 50% {width: 30%;} 70% {width: 70%;} 80% { left: 50%;} 95% {left: 120%;} to {left: 100%;}}")); +k.appendChild(q);l=document.createElement("div");l.setAttribute("id","cly-loader");document.body.onload=function(){if(p.showLoaderProtection)Aa()&&console.warn("[WARNING] [Countly] showloader, Loader is already on");else try{document.body.appendChild(l)}catch(v){Aa()&&console.error("[ERROR] [Countly] showLoader, Body is not loaded for loader to append: "+v)}}}l.style.display="block"}}function Aa(){return p&&p.debug&&"undefined"!==typeof console?!0:!1}function Fb(){if(x){p.showLoaderProtection=!0; +var l=document.getElementById("cly-loader");l&&(l.style.display="none")}}var x="undefined"!==typeof window,p=globalThis.Countly||{};p.features="sessions events views scrolls clicks forms crashes attribution users star-rating location apm feedback remote-config".split(" ");var M={NPS:"[CLY]_nps",SURVEY:"[CLY]_survey",STAR_RATING:"[CLY]_star_rating",VIEW:"[CLY]_view",ORIENTATION:"[CLY]_orientation",ACTION:"[CLY]_action"},Tb=Object.values(M),d={ERROR:"[ERROR] ",WARNING:"[WARNING] ",INFO:"[INFO] ",DEBUG:"[DEBUG] ", +VERBOSE:"[VERBOSE] "},wb={BOOMERANG_SRC:"https://cdn.jsdelivr.net/npm/countly-sdk-web@latest/plugin/boomerang/boomerang.min.js",CLY_BOOMERANG_SRC:"https://cdn.jsdelivr.net/npm/countly-sdk-web@latest/plugin/boomerang/countly_boomerang.js"},S=Object.freeze({errorCount:"cly_hc_error_count",warningCount:"cly_hc_warning_count",statusCode:"cly_hc_status_code",errorMessage:"cly_hc_error_message"});p.q=p.q||[];p.onload=p.onload||[];var Gb=/^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?::([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?::([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, +Hb=!0,Qb=function(l,k,q){k&&vb(l.prototype,k);q&&vb(l,q);Object.defineProperty(l,"prototype",{writable:!1});return l}(function q(k){function v(a,c){if(f.ignore_visitor)b(d.ERROR,"Adding event failed. Possible bot or user opt out");else if(a.key){a.count||(a.count=1);Tb.includes(a.key)||(a.key=z(a.key,f.maxKeyLength,"add_cly_event",b));a.segmentation=aa(a.segmentation,f.maxKeyLength,f.maxValueSize,f.maxSegmentationValues,"add_cly_event",b);a=xa(a,["key","count","sum","dur","segmentation"]);a.timestamp= +fb();var e=new Date;a.hour=e.getHours();a.dow=e.getDay();a.id=c||db();a.key===M.VIEW?a.pvid=Ba||"":a.cvid=ha||"";J.push(a);w("cly_event",J);b(d.INFO,"With event ID: ["+a.id+"], successfully adding the last event:",a)}else b(d.ERROR,"Adding event failed. Event must have a key property")}function G(a,c,e,h,m){b(d.INFO,"fetch_remote_config_explicit, Fetching sequence initiated");var g={method:"rc",av:f.app_version};a&&(g.keys=JSON.stringify(a));c&&(g.omit_keys=JSON.stringify(c));var n;"legacy"===h&& +(g.method="fetch_remote_config");0===e&&(g.oi=0);1===e&&(g.oi=1);"function"===typeof m&&(n=m);f.check_consent("sessions")&&(g.metrics=JSON.stringify(Ra()));f.check_consent("remote-config")?(Ca(g),ba("fetch_remote_config_explicit",f.url+Sa,g,function(r,t,I){if(!r){try{var C=JSON.parse(I);if(g.keys||g.omit_keys)for(var na in C)R[na]=C[na];else R=C;w("cly_remote_configs",R)}catch(Da){b(d.ERROR,"fetch_remote_config_explicit, Had an issue while parsing the response: "+Da)}n&&(b(d.INFO,"fetch_remote_config_explicit, Callback function is provided"), +n(r,R))}},!0)):(b(d.ERROR,"fetch_remote_config_explicit, Remote config requires explicit consent"),n&&n(Error("Remote config requires explicit consent"),R))}function Q(){f.ignore_prefetch&&x&&"undefined"!==typeof document.visibilityState&&"prerender"===document.visibilityState&&(f.ignore_visitor=!0);f.ignore_bots&&Ab()&&(f.ignore_visitor=!0)}function O(){0 a.trigger_font_color.length?"#"+a.trigger_font_color:a.trigger_font_color;t.style.backgroundColor=7>a.trigger_bg_color.length?"#"+a.trigger_bg_color:a.trigger_bg_color;t.className="countly-feedback-sticker "+a.trigger_position+"-"+a.trigger_size;t.id="countly-feedback-sticker-"+a._id;g.appendChild(n);t.appendChild(g);t.appendChild(r);document.body.appendChild(t);var I=document.getElementById("smileyPathInStickerSvg"); +I&&(I.style.fill=7>a.trigger_font_color.length?"#"+a.trigger_font_color:a.trigger_font_color);A(document.getElementById("countly-feedback-sticker-"+a._id),"click",function(){document.getElementById("countly-iframe-wrapper-"+a._id).style.display="block";document.getElementById("cfbg").style.display="block"})}else document.getElementById("countly-iframe-wrapper-"+a._id).style.display="block",document.getElementById("cfbg").style.display="block"}catch(C){b(d.ERROR,"Somethings went wrong while element injecting process: "+ +C)}else b(d.WARNING,"processWidget, window object is not available. Not processing widget.")}function ya(){var a;if("undefined"!==typeof f.onload&&0 Ta&&H.shift(),H.push(a),w("cly_queue",H,!0)):b(d.ERROR,"app_key or device_id is missing ",f.app_key,f.device_id)}function Ua(){ya();if(f.ignore_visitor)Va=!1,b(d.WARNING,"User opt_out, no heartbeat");else{Va=!0;var a=0;if(Wa&&"undefined"!==typeof p.q&&0 Xa&&(f.session_duration(a-ja),ja=a,0 jb&&(Ya=!1,a=H[0],a.rr=H.length,b(d.DEBUG,"Processing request",a),w("cly_queue",H,!0),f.test_mode||ba("send_request_queue",f.url+kb,a,function(n,r){n?jb=F()+Za:H.shift();w("cly_queue",H,!0);Ya=!0},!1));setTimeout(Ua,$a)}}function lb(){var a=y("cly_id");return a?(D=y("cly_id_type"),a):eb()}function Ib(){return f.metrics._ua|| +ta()}function Ra(){var a=JSON.parse(JSON.stringify(f.metrics||{}));a._app_version=a._app_version||f.app_version;a._ua=a._ua||ta();if(x&&screen.width){var c=screen.width?parseInt(screen.width):0,e=screen.height?parseInt(screen.height):0;if(0!==c&&0!==e){if(navigator.platform&&/iPad|iPhone|iPod/.test(navigator.platform)&&window.devicePixelRatio)c=Math.round(c*window.devicePixelRatio),e=Math.round(e*window.devicePixelRatio);else if(90===Math.abs(window.orientation)){var h=c;c=e;e=h}a._resolution=a._resolution|| +""+c+"x"+e}}x&&window.devicePixelRatio&&(a._density=a._density||window.devicePixelRatio);c=navigator.language||navigator.browserLanguage||navigator.systemLanguage||navigator.userLanguage;"undefined"!==typeof c&&(a._locale=a._locale||c);mb()&&(a._store=a._store||document.referrer);b(d.DEBUG,"Got metrics",a);return a}function mb(a){if(!x)return!1;a=a||document.referrer;var c=!1;if("undefined"===typeof a||0===a.length)b(d.DEBUG,"Invalid referrer:["+a+"], ignoring.");else{var e=Gb.exec(a);if(e)if(e[11])if(e[11]=== +window.location.hostname)b(d.DEBUG,"Referrer is current host:["+a+"], ignoring.");else if(ca&&ca.length)for(c=!0,e=0;e a))return b(d.ERROR,"Http response status code:["+a+"] is not within the expected range"),!1;try{var e=JSON.parse(c);return"[object Object]"!==Object.prototype.toString.call(e)?(b(d.ERROR,"Http response is not JSON Object"),!1):!!e.result}catch(h){return b(d.ERROR, +"Http response is not JSON: "+h),!1}}function nb(a,c){if(!(200<=a&&300>a))return b(d.ERROR,"Http response status code:["+a+"] is not within the expected range"),!1;try{var e=JSON.parse(c);return"[object Object]"===Object.prototype.toString.call(e)||Array.isArray(e)?!0:(b(d.ERROR,"Http response is not JSON Object nor JSON Array"),!1)}catch(h){return b(d.ERROR,"Http response is not JSON: "+h),!1}}function Lb(){x?Ja=Math.max(Ja,window.scrollY,document.body.scrollTop,document.documentElement.scrollTop): +b(d.WARNING,"processScroll, window object is not available. Not processing scroll.")}function pb(){if(!x)b(d.WARNING,"processScrollView, window object is not available. Not processing scroll view.");else if(Ka){Ka=!1;var a=Pa(),c=ib(),e=Bb();f.check_consent("scrolls")&&(a={type:"scroll",y:Ja+e,width:c,height:a,view:f.getViewUrl()},a=aa(a,f.maxKeyLength,f.maxValueSize,f.maxSegmentationValues,"processScrollView",b),f.track_domains&&(a.domain=window.location.hostname),v({key:M.ACTION,segmentation:a}))}} +function Mb(a){w("cly_token",a)}function Nb(a,c,e){var h=new Date;h.setTime(h.getTime()+864E5*e);e="; expires="+h.toGMTString();document.cookie=a+"="+c+e+"; path=/"}function y(a,c,e){if("none"===f.storage||"object"!==L(f.storage)&&!x)b(d.DEBUG,"Storage is disabled. Value with key: ["+a+"] won't be retrieved");else{e||(a=f.app_key+"/"+a,f.namespace&&(a=sa(f.namespace)+"/"+a));if("object"===L(f.storage)&&"function"===typeof f.storage.getItem){var h=f.storage.getItem(a);return a.endsWith("cly_id")?h: +f.deserialize(h)}void 0===c&&(c=qa);if(c)h=localStorage.getItem(a);else if("localstorage"!==f.storage)a:{c=a+"=";e=document.cookie.split(";");h=0;for(var m=e.length;h window.innerHeight?"landscape":"portrait")}})};this.report_conversion=function(a,c){b(d.WARNING,"report_conversion, Deprecated function call! Use 'recordDirectAttribution' in place of this call. Call will be redirected now!");this.recordDirectAttribution(a,c)};this.recordDirectAttribution=function(a,c){b(d.INFO,"recordDirectAttribution, Recording the attribution for campaign ID: ["+ +a+"] and the user ID: ["+c+"]");this.check_consent("attribution")&&(a=a||y("cly_cmp_id")||"cly_organic",(c=c||y("cly_cmp_uid"))?N({campaign_id:a,campaign_user:c}):N({campaign_id:a}))};this.user_details=function(a){b(d.INFO,"user_details, Trying to add user details: ",a);this.check_consent("users")&&(O(),b(d.INFO,"user_details, flushed the event queue"),a.name=z(a.name,f.maxValueSize,"user_details",b),a.username=z(a.username,f.maxValueSize,"user_details",b),a.email=z(a.email,f.maxValueSize,"user_details", +b),a.organization=z(a.organization,f.maxValueSize,"user_details",b),a.phone=z(a.phone,f.maxValueSize,"user_details",b),a.picture=z(a.picture,4096,"user_details",b),a.gender=z(a.gender,f.maxValueSize,"user_details",b),a.byear=z(a.byear,f.maxValueSize,"user_details",b),a.custom=aa(a.custom,f.maxKeyLength,f.maxValueSize,f.maxSegmentationValues,"user_details",b),N({user_details:JSON.stringify(xa(a,"name username email organization phone picture gender byear custom".split(" ")))}))};var Y={},fa=function(a, +c,e){f.check_consent("users")&&(Y[a]||(Y[a]={}),"$push"===e||"$pull"===e||"$addToSet"===e?(Y[a][e]||(Y[a][e]=[]),Y[a][e].push(c)):Y[a][e]=c)};this.userData={set:function(a,c){b(d.INFO,"[userData] set, Setting user's custom property value: ["+c+"] under the key: ["+a+"]");a=z(a,f.maxKeyLength,"userData set",b);c=z(c,f.maxValueSize,"userData set",b);Y[a]=c},unset:function(a){b(d.INFO,"[userData] unset, Resetting user's custom property with key: ["+a+"] ");Y[a]=""},set_once:function(a,c){b(d.INFO,"[userData] set_once, Setting user's unique custom property value: ["+ +c+"] under the key: ["+a+"] ");a=z(a,f.maxKeyLength,"userData set_once",b);c=z(c,f.maxValueSize,"userData set_once",b);fa(a,c,"$setOnce")},increment:function(a){b(d.INFO,"[userData] increment, Increasing user's custom property value under the key: ["+a+"] by one");a=z(a,f.maxKeyLength,"userData increment",b);fa(a,1,"$inc")},increment_by:function(a,c){b(d.INFO,"[userData] increment_by, Increasing user's custom property value under the key: ["+a+"] by: ["+c+"]");a=z(a,f.maxKeyLength,"userData increment_by", +b);c=z(c,f.maxValueSize,"userData increment_by",b);fa(a,c,"$inc")},multiply:function(a,c){b(d.INFO,"[userData] multiply, Multiplying user's custom property value under the key: ["+a+"] by: ["+c+"]");a=z(a,f.maxKeyLength,"userData multiply",b);c=z(c,f.maxValueSize,"userData multiply",b);fa(a,c,"$mul")},max:function(a,c){b(d.INFO,"[userData] max, Saving user's maximum custom property value compared to the value: ["+c+"] under the key: ["+a+"]");a=z(a,f.maxKeyLength,"userData max",b);c=z(c,f.maxValueSize, +"userData max",b);fa(a,c,"$max")},min:function(a,c){b(d.INFO,"[userData] min, Saving user's minimum custom property value compared to the value: ["+c+"] under the key: ["+a+"]");a=z(a,f.maxKeyLength,"userData min",b);c=z(c,f.maxValueSize,"userData min",b);fa(a,c,"$min")},push:function(a,c){b(d.INFO,"[userData] push, Pushing a value: ["+c+"] under the key: ["+a+"] to user's custom property array");a=z(a,f.maxKeyLength,"userData push",b);c=z(c,f.maxValueSize,"userData push",b);fa(a,c,"$push")},push_unique:function(a, +c){b(d.INFO,"[userData] push_unique, Pushing a unique value: ["+c+"] under the key: ["+a+"] to user's custom property array");a=z(a,f.maxKeyLength,"userData push_unique",b);c=z(c,f.maxValueSize,"userData push_unique",b);fa(a,c,"$addToSet")},pull:function(a,c){b(d.INFO,"[userData] pull, Removing the value: ["+c+"] under the key: ["+a+"] from user's custom property array");fa(a,c,"$pull")},save:function(){b(d.INFO,"[userData] save, Saving changes to user's custom property");f.check_consent("users")&& +(O(),b(d.INFO,"user_details, flushed the event queue"),N({user_details:JSON.stringify({custom:Y})}));Y={}}};this.report_trace=function(a){b(d.INFO,"report_trace, Reporting performance trace");if(this.check_consent("apm")){for(var c="type name stz etz apm_metrics apm_attr".split(" "),e=0;e =f.maxBreadcrumbCount;)ra.shift(),b(d.WARNING,"add_log, Reached maximum crashLogs size. Will erase the oldest one.");ra.push(a)}};this.fetch_remote_config=function(a,c,e){var h=null,m=null,g=null;a&&(e||"function"!==typeof a?Array.isArray(a)&& +(h=a):g=a);c&&(e||"function"!==typeof c?Array.isArray(c)&&(m=c):g=c);g||"function"!==typeof e||(g=e);this.useExplicitRcApi?(b(d.INFO,"fetch_remote_config, Fetching remote config"),G(h,m,this.rcAutoOptinAb?1:0,null,g)):(b(d.WARNING,"fetch_remote_config, Fetching remote config, with legacy API"),G(h,m,null,"legacy",g))};this.enrollUserToAb=function(a){b(d.INFO,"enrollUserToAb, Providing AB test keys to opt in for");a&&Array.isArray(a)&&0!==a.length?(a={method:"ab",keys:JSON.stringify(a),av:f.app_version}, +Ca(a),ba("enrollUserToAb",this.url+Sa,a,function(c,e,h){if(!c)try{var m=JSON.parse(h);b(d.DEBUG,"enrollUserToAb, Parsed the response's result: ["+m.result+"]")}catch(g){b(d.ERROR,"enrollUserToAb, Had an issue while parsing the response: "+g)}},!0)):b(d.ERROR,"enrollUserToAb, No keys provided")};this.get_remote_config=function(a){b(d.INFO,"get_remote_config, Getting remote config from storage");return"undefined"!==typeof a?R[a]:R};this.stop_time=function(){b(d.INFO,"stop_time, Stopping tracking duration"); +oa&&(oa=!1,rb=F()-ja,Fa=F()-Ea)};this.start_time=function(){b(d.INFO,"start_time, Starting tracking duration");oa||(oa=!0,ja=F()-rb,Ea=F()-Fa,Fa=0,za())};this.track_sessions=function(){function a(){document[e]||!document.hasFocus()?f.stop_time():f.start_time()}function c(){Ma>=La&&f.start_time();Ma=0}if(x){b(d.INFO,"track_session, Starting tracking user session");this.begin_session();this.start_time();A(window,"beforeunload",function(){O();f.end_session()});var e="hidden";A(window,"focus",a);A(window, +"blur",a);A(window,"pageshow",a);A(window,"pagehide",a);"onfocusin"in document&&(A(window,"focusin",a),A(window,"focusout",a));e in document?document.addEventListener("visibilitychange",a):"mozHidden"in document?(e="mozHidden",document.addEventListener("mozvisibilitychange",a)):"webkitHidden"in document?(e="webkitHidden",document.addEventListener("webkitvisibilitychange",a)):"msHidden"in document&&(e="msHidden",document.addEventListener("msvisibilitychange",a));A(window,"mousemove",c);A(window,"click", +c);A(window,"keydown",c);A(window,"scroll",c);setInterval(function(){Ma++;Ma>=La&&f.stop_time()},6E4)}else b(d.WARNING,"track_sessions, window object is not available. Not tracking sessions.")};this.track_pageview=function(a,c,e){if(x||a)if(b(d.INFO,"track_pageview, Tracking page views"),b(d.VERBOSE,"track_pageview, last view is:["+W+"], current view ID is:["+ha+"], previous view ID is:["+Ba+"]"),W&&sb&&(b(d.DEBUG,"track_pageview, Scroll registry triggered"),pb(),Ka=!0,Ja=0),ma(),Ba=ha,ha=db(),(a= +z(a,f.maxKeyLength,"track_pageview",b))&&Array.isArray(a)&&(c=a,a=null),a||(a=this.getViewName()),void 0===a||""===a)b(d.ERROR,"track_pageview, No page name to track (it is either undefined or empty string). No page view can be tracked.");else if(null===a)b(d.ERROR,"track_pageview, View name returned as null. Page view will be ignored.");else{if(c&&c.length)for(var h=0;h c.segmentation.rating&&(b(d.WARNING,"recordRatingWidgetWithID, You have entered a rating lower than 1. Changing it back to 1 now."), +c.segmentation.rating=1);b(d.INFO,"recordRatingWidgetWithID, Reporting Rating Widget: ",c);v(c)}else b(d.ERROR,"recordRatingWidgetWithID, Rating Widget must contain rating property");else b(d.ERROR,"recordRatingWidgetWithID, Rating Widget must contain widget_id property")};this.reportFeedbackWidgetManually=function(a,c,e){if(this.check_consent("feedback"))if(a&&c)if(a._id)if(K)b(d.ERROR,"reportFeedbackWidgetManually, Feedback Widgets can not be reported in offline mode");else{b(d.INFO,"reportFeedbackWidgetManually, Providing information about user with, provided result of the widget with ID: [ "+ +a._id+" ] and type: ["+a.type+"]");var h=[];c=a.type;if("nps"===c){if(e){if(!e.rating){b(d.ERROR,"reportFeedbackWidgetManually, Widget must contain rating property");return}e.rating=Math.round(e.rating);10 e.rating&&(b(d.WARNING,"reportFeedbackWidgetManually, You have entered a rating lower than 0. Changing it back to 0 now."),e.rating=0);h=["rating","comment"]}var m= +M.NPS}else if("survey"===c){if(e){if(1>Object.keys(e).length){b(d.ERROR,"reportFeedbackWidgetManually, Widget should have answers to be reported");return}h=Object.keys(e)}m=M.SURVEY}else if("rating"===c){if(e){if(!e.rating){b(d.ERROR,"reportFeedbackWidgetManually, Widget must contain rating property");return}e.rating=Math.round(e.rating);5 e.rating&&(b(d.WARNING, +"reportFeedbackWidgetManually, You have entered a rating lower than 1. Changing it back to 1 now."),e.rating=1);h=["rating","comment","email","contactMe"]}m=M.STAR_RATING}else{b(d.ERROR,"reportFeedbackWidgetManually, Widget has an unacceptable type");return}a={key:m,count:1,segmentation:{widget_id:a._id,platform:this.platform,app_version:this.metrics._app_version||this.app_version}};if(null===e)a.segmentation.closed=1;else{m=a.segmentation;if(h){for(var g,n=0,r=h.length;n '),this.initializeRatingWidgets(a)):b(d.ERROR,"enableRatingWidgets, You should provide at least one widget id as param. Read documentation for more detail. https://resources.count.ly/plugins/feedback")))): +b(d.WARNING,"enableRatingWidgets, window object is not available. Not enabling rating widgets.")};this.get_available_feedback_widgets=function(a){b(d.INFO,"get_available_feedback_widgets, Getting the feedback list, callback function is provided:["+!!a+"]");this.check_consent("feedback")?K?b(d.ERROR,"get_available_feedback_widgets, Cannot enable feedback widgets in offline mode."):ba("get_available_feedback_widgets,",this.url+Sa,{method:"feedback",device_id:this.device_id,app_key:this.app_key,av:f.app_version}, +function(c,e,h){if(c)a&&a(null,c);else try{var m=JSON.parse(h).result||[];a&&a(m,null)}catch(g){b(d.ERROR,"get_available_feedback_widgets, Error while parsing feedback widgets list: "+g),a&&a(null,g)}},!1):a&&a(null,Error("Consent for feedback not provided."))};this.getFeedbackWidgetData=function(a,c){if(a.type)if(b(d.INFO,"getFeedbackWidgetData, Retrieving data for: ["+JSON.stringify(a)+"], callback function is provided:["+!!c+"]"),this.check_consent("feedback"))if(K)b(d.ERROR,"getFeedbackWidgetData, Cannot enable feedback widgets in offline mode."); +else{var e=this.url,h={widget_id:a._id,shown:1,sdk_version:"23.12.0",sdk_name:"javascript_native_web",platform:this.platform,app_version:this.app_version};if("nps"===a.type)e+="/o/surveys/nps/widget";else if("survey"===a.type)e+="/o/surveys/survey/widget";else if("rating"===a.type)e+="/o/surveys/rating/widget";else{b(d.ERROR,"getFeedbackWidgetData, Unknown type info: ["+a.type+"]");return}ba("getFeedbackWidgetData,",e,h,function(m,g,n){if(m)c&&c(null,m);else try{var r=JSON.parse(n);c&&c(r,null)}catch(t){b(d.ERROR, +"getFeedbackWidgetData, Error while parsing feedback widgets list: "+t),c&&c(null,t)}},!0)}else c&&c(null,Error("Consent for feedback not provided."));else b(d.ERROR,"getFeedbackWidgetData, Expected the provided widget object to have a type but got: ["+JSON.stringify(a)+"], aborting.")};this.present_feedback_widget=function(a,c,e,h){function m(B){document.getElementById("countly-surveys-wrapper-"+B._id).style.display="block";document.getElementById("csbg").style.display="block"}function g(B){if(!B.appearance.hideS){b(d.DEBUG, +"present_feedback_widget, handling the sticker as it was not set to hidden");var T=document.createElement("div");T.innerText=B.appearance.text;T.style.color=7>B.appearance.text_color.length?"#"+B.appearance.text_color:B.appearance.text_color;T.style.backgroundColor=7>B.appearance.bg_color.length?"#"+B.appearance.bg_color:B.appearance.bg_color;T.className="countly-feedback-sticker "+B.appearance.position+"-"+B.appearance.size;T.id="countly-feedback-sticker-"+B._id;document.body.appendChild(T);A(document.getElementById("countly-feedback-sticker-"+ +B._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+B._id).style.display="flex";document.getElementById("csbg").style.display="block"})}A(document.getElementById("countly-feedback-close-icon-"+B._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+B._id).style.display="none";document.getElementById("csbg").style.display="none"})}if(x){if(b(d.INFO,"present_feedback_widget, Presenting the feedback widget by appending to the element with ID: [ "+c+" ] and className: [ "+ +e+" ]"),this.check_consent("feedback"))if(!a||"object"!==L(a)||Array.isArray(a))b(d.ERROR,"present_feedback_widget, Please provide at least one feedback widget object.");else{b(d.INFO,"present_feedback_widget, Adding segmentation to feedback widgets:["+JSON.stringify(h)+"]");h&&"object"===L(h)&&0!==Object.keys(h).length||(b(d.DEBUG,"present_feedback_widget, Segmentation is not an object or empty"),h=null);try{var n=this.url;if("nps"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: nps."), +n+="/feedback/nps";else if("survey"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: survey."),n+="/feedback/survey";else if("rating"===a.type)b(d.DEBUG,"present_feedback_widget, Widget type: rating."),n+="/feedback/rating";else{b(d.ERROR,"present_feedback_widget, Feedback widget only accepts nps, rating and survey types.");return}var r=window.origin||window.location.origin;if("rating"===a.type){b(d.DEBUG,"present_feedback_widget, Loading css for rating widget.");var t="ratings";Qa(this.url+ +"/star-rating/stylesheets/countly-feedback-web.css")}else b(d.DEBUG,"present_feedback_widget, Loading css for survey or nps."),Qa(this.url+"/surveys/stylesheets/countly-surveys.css"),t="surveys";n+="?widget_id="+a._id;n+="&app_key="+this.app_key;n+="&device_id="+this.device_id;n+="&sdk_name=javascript_native_web";n+="&platform="+this.platform;n+="&app_version="+this.app_version;n+="&sdk_version=23.12.0";if(h){var I={};I.sg=h;n+="&custom="+JSON.stringify(I)}n+="&origin="+r;n+="&widget_v=web";var C= +document.createElement("iframe");C.src=n;C.name="countly-"+t+"-iframe";C.id="countly-"+t+"-iframe";var na=!1;C.onload=function(){na&&(document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="none",document.getElementById("csbg").style.display="none");na=!0;b(d.DEBUG,"present_feedback_widget, Loaded iframe.")};for(var Da=document.getElementById("csbg");Da;)Da.remove(),Da=document.getElementById("csbg"),b(d.DEBUG,"present_feedback_widget, Removing past overlay.");var Z=document.getElementsByClassName("countly-"+ +t+"-wrapper");for(h=0;h ');bb.appendChild(Z);if("rating"===a.type){var ub=document.createElement("div");ub.className="countly-ratings-overlay";ub.id="countly-ratings-overlay-"+a._id;Z.appendChild(ub);b(d.DEBUG,"present_feedback_widget, appended the rating overlay to wrapper");A(document.getElementById("countly-ratings-overlay-"+a._id),"click",function(){document.getElementById("countly-ratings-wrapper-"+ +a._id).style.display="none"})}Z.appendChild(C);b(d.DEBUG,"present_feedback_widget, Appended the iframe");A(window,"message",function(B){var T={};try{T=JSON.parse(B.data),b(d.DEBUG,"present_feedback_widget, Parsed response message "+T)}catch(Vb){b(d.ERROR,"present_feedback_widget, Error while parsing message body "+Vb)}T.close?(document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="none",document.getElementById("csbg").style.display="none"):b(d.DEBUG,"present_feedback_widget, Closing signal not sent yet")}); +if("survey"===a.type){var P=!1;switch(a.showPolicy){case "afterPageLoad":"complete"===document.readyState?P||(P=!0,m(a)):A(document,"readystatechange",function(B){"complete"!==B.target.readyState||P||(P=!0,m(a))});break;case "afterConstantDelay":setTimeout(function(){P||(P=!0,m(a))},1E4);break;case "onAbandon":"complete"===document.readyState?A(document,"mouseleave",function(){P||(P=!0,m(a))}):A(document,"readystatechange",function(B){"complete"===B.target.readyState&&A(document,"mouseleave",function(){P|| +(P=!0,m(a))})});break;case "onScrollHalfwayDown":A(window,"scroll",function(){if(!P){var B=Math.max(window.scrollY,document.body.scrollTop,document.documentElement.scrollTop),T=Pa();B>=T/2&&(P=!0,m(a))}});break;default:P||(P=!0,m(a))}}else if("nps"===a.type)document.getElementById("countly-"+t+"-wrapper-"+a._id).style.display="block",document.getElementById("csbg").style.display="block";else if("rating"===a.type){var cb=!1;"complete"===document.readyState?cb||(cb=!0,g(a)):A(document,"readystatechange", +function(B){"complete"!==B.target.readyState||cb||(cb=!0,g(a))})}}catch(B){b(d.ERROR,"present_feedback_widget, Something went wrong while presenting the widget: "+B)}}}else b(d.WARNING,"present_feedback_widget, window object is not available. Not presenting feedback widget.")};this.recordError=function(a,c,e){b(d.INFO,"recordError, Recording error");if(this.check_consent("crashes")&&a){e=e||qb;var h="";"object"===L(a)?"undefined"!==typeof a.stack?h=a.stack:("undefined"!==typeof a.name&&(h+=a.name+ +":"),"undefined"!==typeof a.message&&(h+=a.message+"\n"),"undefined"!==typeof a.fileName&&(h+="in "+a.fileName+"\n"),"undefined"!==typeof a.lineNumber&&(h+="on "+a.lineNumber),"undefined"!==typeof a.columnNumber&&(h+=":"+a.columnNumber)):h=a+"";if(h.length>f.maxStackTraceLineLength*f.maxStackTraceLinesPerThread){b(d.DEBUG,"record_error, Error stack is too long will be truncated");a=h.split("\n");a.length>f.maxStackTraceLinesPerThread&&(a=a.splice(0,f.maxStackTraceLinesPerThread));h=0;for(var m=a.length;h< +m;h++)a[h].length>f.maxStackTraceLineLength&&(a[h]=a[h].substring(0,f.maxStackTraceLineLength));h=a.join("\n")}c=!!c;a=Ra();h={_resolution:a._resolution,_error:h,_app_version:a._app_version,_run:F()-Ob,_not_os_specific:!0,_javascript:!0};if(m=navigator.battery||navigator.webkitBattery||navigator.mozBattery||navigator.msBattery)h._bat=Math.floor(100*m.level);"undefined"!==typeof navigator.onLine&&(h._online=!!navigator.onLine);x&&(h._background=!document.hasFocus());0