Visible for testing */ const MAX_VALUE_MILLIS = 4 * 60 * 60 * 1000; // Four hours, like iOS and Android. /** * The percentage of backoff time to randomize by. * See * http://go/safe-client-behavior#step-1-determine-the-appropriate-retry-interval-to-handle-spike-traffic * for context. * *
Visible for testing */ const RANDOM_FACTOR = 0.5; /** * Based on the backoff method from * https://github.com/google/closure-library/blob/master/closure/goog/math/exponentialbackoff.js. * Extracted here so we don't need to pass metadata and a stateful ExponentialBackoff object around. */ function calculateBackoffMillis(backoffCount, intervalMillis = DEFAULT_INTERVAL_MILLIS, backoffFactor = DEFAULT_BACKOFF_FACTOR) { // Calculates an exponentially increasing value. // Deviation: calculates value from count and a constant interval, so we only need to save value // and count to restore state. const currBaseValue = intervalMillis * Math.pow(backoffFactor, backoffCount); // A random "fuzz" to avoid waves of retries. // Deviation: randomFactor is required. const randomWait = Math.round( // A fraction of the backoff value to add/subtract. // Deviation: changes multiplication order to improve readability. RANDOM_FACTOR * currBaseValue * ( // A random float (rounded to int by Math.round above) in the range [-1, 1]. Determines // if we add or subtract. Math.random() - 0.5) * 2); // Limits backoff to max to avoid effectively permanent backoff. return Math.min(MAX_VALUE_MILLIS, currBaseValue + randomWait); } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Provide English ordinal letters after a number */ function ordinal(i) { if (!Number.isFinite(i)) { return `${i}`; } return i + indicator(i); } function indicator(i) { i = Math.abs(i); const cent = i % 100; if (cent >= 10 && cent <= 20) { return 'th'; } const dec = i % 10; if (dec === 1) { return 'st'; } if (dec === 2) { return 'nd'; } if (dec === 3) { return 'rd'; } return 'th'; } /** * @license * Copyright 2021 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function getModularInstance(service) { if (service && service._delegate) { return service._delegate; } else { return service; } } /***/ }), /***/ 43763: /*!***************************************************************!*\ !*** ./node_modules/firebase/analytics/dist/esm/index.esm.js ***! \***************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "getAnalytics": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.getAnalytics), /* harmony export */ "getGoogleAnalyticsClientId": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.getGoogleAnalyticsClientId), /* harmony export */ "initializeAnalytics": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.initializeAnalytics), /* harmony export */ "isSupported": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.isSupported), /* harmony export */ "logEvent": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.logEvent), /* harmony export */ "setAnalyticsCollectionEnabled": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setAnalyticsCollectionEnabled), /* harmony export */ "setConsent": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setConsent), /* harmony export */ "setCurrentScreen": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setCurrentScreen), /* harmony export */ "setDefaultEventParameters": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setDefaultEventParameters), /* harmony export */ "setUserId": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setUserId), /* harmony export */ "setUserProperties": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.setUserProperties), /* harmony export */ "settings": () => (/* reexport safe */ _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__.settings) /* harmony export */ }); /* harmony import */ var _firebase_analytics__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @firebase/analytics */ 73493); /***/ }), /***/ 73493: /*!******************************************************************************************!*\ !*** ./node_modules/firebase/node_modules/@firebase/analytics/dist/esm/index.esm2017.js ***! \******************************************************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "getAnalytics": () => (/* binding */ getAnalytics), /* harmony export */ "getGoogleAnalyticsClientId": () => (/* binding */ getGoogleAnalyticsClientId), /* harmony export */ "initializeAnalytics": () => (/* binding */ initializeAnalytics), /* harmony export */ "isSupported": () => (/* binding */ isSupported), /* harmony export */ "logEvent": () => (/* binding */ logEvent), /* harmony export */ "setAnalyticsCollectionEnabled": () => (/* binding */ setAnalyticsCollectionEnabled), /* harmony export */ "setConsent": () => (/* binding */ setConsent), /* harmony export */ "setCurrentScreen": () => (/* binding */ setCurrentScreen), /* harmony export */ "setDefaultEventParameters": () => (/* binding */ setDefaultEventParameters), /* harmony export */ "setUserId": () => (/* binding */ setUserId), /* harmony export */ "setUserProperties": () => (/* binding */ setUserProperties), /* harmony export */ "settings": () => (/* binding */ settings) /* harmony export */ }); /* harmony import */ var _Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js */ 71670); /* harmony import */ var _firebase_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @firebase/app */ 93087); /* harmony import */ var _firebase_logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @firebase/logger */ 36883); /* harmony import */ var _firebase_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @firebase/util */ 84850); /* harmony import */ var _firebase_component__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @firebase/component */ 21707); /* harmony import */ var _firebase_installations__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @firebase/installations */ 43206); /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Type constant for Firebase Analytics. */ const ANALYTICS_TYPE = 'analytics'; // Key to attach FID to in gtag params. const GA_FID_KEY = 'firebase_id'; const ORIGIN_KEY = 'origin'; const FETCH_TIMEOUT_MILLIS = 60 * 1000; const DYNAMIC_CONFIG_URL = 'https://firebase.googleapis.com/v1alpha/projects/-/apps/{app-id}/webConfig'; const GTAG_URL = 'https://www.googletagmanager.com/gtag/js'; /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const logger = new _firebase_logger__WEBPACK_IMPORTED_MODULE_2__.Logger('@firebase/analytics'); /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const ERRORS = { ["already-exists" /* AnalyticsError.ALREADY_EXISTS */ ]: 'A Firebase Analytics instance with the appId {$id} ' + ' already exists. ' + 'Only one Firebase Analytics instance can be created for each appId.', ["already-initialized" /* AnalyticsError.ALREADY_INITIALIZED */ ]: 'initializeAnalytics() cannot be called again with different options than those ' + 'it was initially called with. It can be called again with the same options to ' + 'return the existing instance, or getAnalytics() can be used ' + 'to get a reference to the already-initialized instance.', ["already-initialized-settings" /* AnalyticsError.ALREADY_INITIALIZED_SETTINGS */ ]: 'Firebase Analytics has already been initialized.' + 'settings() must be called before initializing any Analytics instance' + 'or it will have no effect.', ["interop-component-reg-failed" /* AnalyticsError.INTEROP_COMPONENT_REG_FAILED */ ]: 'Firebase Analytics Interop Component failed to instantiate: {$reason}', ["invalid-analytics-context" /* AnalyticsError.INVALID_ANALYTICS_CONTEXT */ ]: 'Firebase Analytics is not supported in this environment. ' + 'Wrap initialization of analytics in analytics.isSupported() ' + 'to prevent initialization in unsupported environments. Details: {$errorInfo}', ["indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */ ]: 'IndexedDB unavailable or restricted in this environment. ' + 'Wrap initialization of analytics in analytics.isSupported() ' + 'to prevent initialization in unsupported environments. Details: {$errorInfo}', ["fetch-throttle" /* AnalyticsError.FETCH_THROTTLE */ ]: 'The config fetch request timed out while in an exponential backoff state.' + ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.', ["config-fetch-failed" /* AnalyticsError.CONFIG_FETCH_FAILED */ ]: 'Dynamic config fetch failed: [{$httpStatus}] {$responseMessage}', ["no-api-key" /* AnalyticsError.NO_API_KEY */ ]: 'The "apiKey" field is empty in the local Firebase config. Firebase Analytics requires this field to' + 'contain a valid API key.', ["no-app-id" /* AnalyticsError.NO_APP_ID */ ]: 'The "appId" field is empty in the local Firebase config. Firebase Analytics requires this field to' + 'contain a valid app ID.', ["no-client-id" /* AnalyticsError.NO_CLIENT_ID */ ]: 'The "client_id" field is empty.', ["invalid-gtag-resource" /* AnalyticsError.INVALID_GTAG_RESOURCE */ ]: 'Trusted Types detected an invalid gtag resource: {$gtagURL}.' }; const ERROR_FACTORY = new _firebase_util__WEBPACK_IMPORTED_MODULE_3__.ErrorFactory('analytics', 'Analytics', ERRORS); /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Verifies and creates a TrustedScriptURL. */ function createGtagTrustedTypesScriptURL(url) { if (!url.startsWith(GTAG_URL)) { const err = ERROR_FACTORY.create("invalid-gtag-resource" /* AnalyticsError.INVALID_GTAG_RESOURCE */ , { gtagURL: url }); logger.warn(err.message); return ''; } return url; } /** * Makeshift polyfill for Promise.allSettled(). Resolves when all promises * have either resolved or rejected. * * @param promises Array of promises to wait for. */ function promiseAllSettled(promises) { return Promise.all(promises.map(promise => promise.catch(e => e))); } /** * Creates a TrustedTypePolicy object that implements the rules passed as policyOptions. * * @param policyName A string containing the name of the policy * @param policyOptions Object containing implementations of instance methods for TrustedTypesPolicy, see {@link https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy#instance_methods * | the TrustedTypePolicy reference documentation}. */ function createTrustedTypesPolicy(policyName, policyOptions) { // Create a TrustedTypes policy that we can use for updating src // properties let trustedTypesPolicy; if (window.trustedTypes) { trustedTypesPolicy = window.trustedTypes.createPolicy(policyName, policyOptions); } return trustedTypesPolicy; } /** * Inserts gtag script tag into the page to asynchronously download gtag. * @param dataLayerName Name of datalayer (most often the default, "_dataLayer"). */ function insertScriptTag(dataLayerName, measurementId) { const trustedTypesPolicy = createTrustedTypesPolicy('firebase-js-sdk-policy', { createScriptURL: createGtagTrustedTypesScriptURL }); const script = document.createElement('script'); // We are not providing an analyticsId in the URL because it would trigger a `page_view` // without fid. We will initialize ga-id using gtag (config) command together with fid. const gtagScriptURL = `${GTAG_URL}?l=${dataLayerName}&id=${measurementId}`; script.src = trustedTypesPolicy ? trustedTypesPolicy === null || trustedTypesPolicy === void 0 ? void 0 : trustedTypesPolicy.createScriptURL(gtagScriptURL) : gtagScriptURL; script.async = true; document.head.appendChild(script); } /** * Get reference to, or create, global datalayer. * @param dataLayerName Name of datalayer (most often the default, "_dataLayer"). */ function getOrCreateDataLayer(dataLayerName) { // Check for existing dataLayer and create if needed. let dataLayer = []; if (Array.isArray(window[dataLayerName])) { dataLayer = window[dataLayerName]; } else { window[dataLayerName] = dataLayer; } return dataLayer; } /** * Wrapped gtag logic when gtag is called with 'config' command. * * @param gtagCore Basic gtag function that just appends to dataLayer. * @param initializationPromisesMap Map of appIds to their initialization promises. * @param dynamicConfigPromisesList Array of dynamic config fetch promises. * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId. * @param measurementId GA Measurement ID to set config for. * @param gtagParams Gtag config params to set. */ function gtagOnConfig(_x, _x2, _x3, _x4, _x5, _x6) { return _gtagOnConfig.apply(this, arguments); } /** * Wrapped gtag logic when gtag is called with 'event' command. * * @param gtagCore Basic gtag function that just appends to dataLayer. * @param initializationPromisesMap Map of appIds to their initialization promises. * @param dynamicConfigPromisesList Array of dynamic config fetch promises. * @param measurementId GA Measurement ID to log event to. * @param gtagParams Params to log with this event. */ function _gtagOnConfig() { _gtagOnConfig = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams) { // If config is already fetched, we know the appId and can use it to look up what FID promise we /// are waiting for, and wait only on that one. const correspondingAppId = measurementIdToAppId[measurementId]; try { if (correspondingAppId) { yield initializationPromisesMap[correspondingAppId]; } else { // If config is not fetched yet, wait for all configs (we don't know which one we need) and // find the appId (if any) corresponding to this measurementId. If there is one, wait on // that appId's initialization promise. If there is none, promise resolves and gtag // call goes through. const dynamicConfigResults = yield promiseAllSettled(dynamicConfigPromisesList); const foundConfig = dynamicConfigResults.find(config => config.measurementId === measurementId); if (foundConfig) { yield initializationPromisesMap[foundConfig.appId]; } } } catch (e) { logger.error(e); } gtagCore("config" /* GtagCommand.CONFIG */ , measurementId, gtagParams); }); return _gtagOnConfig.apply(this, arguments); } function gtagOnEvent(_x7, _x8, _x9, _x0, _x1) { return _gtagOnEvent.apply(this, arguments); } /** * Wraps a standard gtag function with extra code to wait for completion of * relevant initialization promises before sending requests. * * @param gtagCore Basic gtag function that just appends to dataLayer. * @param initializationPromisesMap Map of appIds to their initialization promises. * @param dynamicConfigPromisesList Array of dynamic config fetch promises. * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId. */ function _gtagOnEvent() { _gtagOnEvent = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams) { try { let initializationPromisesToWaitFor = []; // If there's a 'send_to' param, check if any ID specified matches // an initializeIds() promise we are waiting for. if (gtagParams && gtagParams['send_to']) { let gaSendToList = gtagParams['send_to']; // Make it an array if is isn't, so it can be dealt with the same way. if (!Array.isArray(gaSendToList)) { gaSendToList = [gaSendToList]; } // Checking 'send_to' fields requires having all measurement ID results back from // the dynamic config fetch. const dynamicConfigResults = yield promiseAllSettled(dynamicConfigPromisesList); for (const sendToId of gaSendToList) { // Any fetched dynamic measurement ID that matches this 'send_to' ID const foundConfig = dynamicConfigResults.find(config => config.measurementId === sendToId); const initializationPromise = foundConfig && initializationPromisesMap[foundConfig.appId]; if (initializationPromise) { initializationPromisesToWaitFor.push(initializationPromise); } else { // Found an item in 'send_to' that is not associated // directly with an FID, possibly a group. Empty this array, // exit the loop early, and let it get populated below. initializationPromisesToWaitFor = []; break; } } } // This will be unpopulated if there was no 'send_to' field , or // if not all entries in the 'send_to' field could be mapped to // a FID. In these cases, wait on all pending initialization promises. if (initializationPromisesToWaitFor.length === 0) { /* eslint-disable-next-line @typescript-eslint/no-floating-promises */ initializationPromisesToWaitFor = Object.values(initializationPromisesMap); } // Run core gtag function with args after all relevant initialization // promises have been resolved. yield Promise.all(initializationPromisesToWaitFor); // Workaround for http://b/141370449 - third argument cannot be undefined. gtagCore("event" /* GtagCommand.EVENT */ , measurementId, gtagParams || {}); } catch (e) { logger.error(e); } }); return _gtagOnEvent.apply(this, arguments); } function wrapGtag(gtagCore, /** * Allows wrapped gtag calls to wait on whichever initialization promises are required, * depending on the contents of the gtag params' `send_to` field, if any. */ initializationPromisesMap, /** * Wrapped gtag calls sometimes require all dynamic config fetches to have returned * before determining what initialization promises (which include FIDs) to wait for. */ dynamicConfigPromisesList, /** * Wrapped gtag config calls can narrow down which initialization promise (with FID) * to wait for if the measurementId is already fetched, by getting the corresponding appId, * which is the key for the initialization promises map. */ measurementIdToAppId) { /** * Wrapper around gtag that ensures FID is sent with gtag calls. * @param command Gtag command type. * @param idOrNameOrParams Measurement ID if command is EVENT/CONFIG, params if command is SET. * @param gtagParams Params if event is EVENT/CONFIG. */ function gtagWrapper(_x10) { return _gtagWrapper.apply(this, arguments); } function _gtagWrapper() { _gtagWrapper = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (command, ...args) { try { // If event, check that relevant initialization promises have completed. if (command === "event" /* GtagCommand.EVENT */ ) { const [measurementId, gtagParams] = args; // If EVENT, second arg must be measurementId. yield gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams); } else if (command === "config" /* GtagCommand.CONFIG */ ) { const [measurementId, gtagParams] = args; // If CONFIG, second arg must be measurementId. yield gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams); } else if (command === "consent" /* GtagCommand.CONSENT */ ) { const [consentAction, gtagParams] = args; // consentAction can be one of 'default' or 'update'. gtagCore("consent" /* GtagCommand.CONSENT */ , consentAction, gtagParams); } else if (command === "get" /* GtagCommand.GET */ ) { const [measurementId, fieldName, callback] = args; gtagCore("get" /* GtagCommand.GET */ , measurementId, fieldName, callback); } else if (command === "set" /* GtagCommand.SET */ ) { const [customParams] = args; // If SET, second arg must be params. gtagCore("set" /* GtagCommand.SET */ , customParams); } else { gtagCore(command, ...args); } } catch (e) { logger.error(e); } }); return _gtagWrapper.apply(this, arguments); } return gtagWrapper; } /** * Creates global gtag function or wraps existing one if found. * This wrapped function attaches Firebase instance ID (FID) to gtag 'config' and * 'event' calls that belong to the GAID associated with this Firebase instance. * * @param initializationPromisesMap Map of appIds to their initialization promises. * @param dynamicConfigPromisesList Array of dynamic config fetch promises. * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId. * @param dataLayerName Name of global GA datalayer array. * @param gtagFunctionName Name of global gtag function ("gtag" if not user-specified). */ function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagFunctionName) { // Create a basic core gtag function let gtagCore = function (..._args) { // Must push IArguments object, not an array. window[dataLayerName].push(arguments); }; // Replace it with existing one if found if (window[gtagFunctionName] && typeof window[gtagFunctionName] === 'function') { // @ts-ignore gtagCore = window[gtagFunctionName]; } window[gtagFunctionName] = wrapGtag(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId); return { gtagCore, wrappedGtag: window[gtagFunctionName] }; } /** * Returns the script tag in the DOM matching both the gtag url pattern * and the provided data layer name. */ function findGtagScriptOnPage(dataLayerName) { const scriptTags = window.document.getElementsByTagName('script'); for (const tag of Object.values(scriptTags)) { if (tag.src && tag.src.includes(GTAG_URL) && tag.src.includes(dataLayerName)) { return tag; } } return null; } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Backoff factor for 503 errors, which we want to be conservative about * to avoid overloading servers. Each retry interval will be * BASE_INTERVAL_MILLIS * LONG_RETRY_FACTOR ^ retryCount, so the second one * will be ~30 seconds (with fuzzing). */ const LONG_RETRY_FACTOR = 30; /** * Base wait interval to multiplied by backoffFactor^backoffCount. */ const BASE_INTERVAL_MILLIS = 1000; /** * Stubbable retry data storage class. */ class RetryData { constructor(throttleMetadata = {}, intervalMillis = BASE_INTERVAL_MILLIS) { this.throttleMetadata = throttleMetadata; this.intervalMillis = intervalMillis; } getThrottleMetadata(appId) { return this.throttleMetadata[appId]; } setThrottleMetadata(appId, metadata) { this.throttleMetadata[appId] = metadata; } deleteThrottleMetadata(appId) { delete this.throttleMetadata[appId]; } } const defaultRetryData = new RetryData(); /** * Set GET request headers. * @param apiKey App API key. */ function getHeaders(apiKey) { return new Headers({ Accept: 'application/json', 'x-goog-api-key': apiKey }); } /** * Fetches dynamic config from backend. * @param app Firebase app to fetch config for. */ function fetchDynamicConfig(_x11) { return _fetchDynamicConfig.apply(this, arguments); } /** * Fetches dynamic config from backend, retrying if failed. * @param app Firebase app to fetch config for. */ function _fetchDynamicConfig() { _fetchDynamicConfig = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appFields) { var _a; const { appId, apiKey } = appFields; const request = { method: 'GET', headers: getHeaders(apiKey) }; const appUrl = DYNAMIC_CONFIG_URL.replace('{app-id}', appId); const response = yield fetch(appUrl, request); if (response.status !== 200 && response.status !== 304) { let errorMessage = ''; try { // Try to get any error message text from server response. const jsonResponse = yield response.json(); if ((_a = jsonResponse.error) === null || _a === void 0 ? void 0 : _a.message) { errorMessage = jsonResponse.error.message; } } catch (_ignored) {} throw ERROR_FACTORY.create("config-fetch-failed" /* AnalyticsError.CONFIG_FETCH_FAILED */ , { httpStatus: response.status, responseMessage: errorMessage }); } return response.json(); }); return _fetchDynamicConfig.apply(this, arguments); } function fetchDynamicConfigWithRetry(_x12) { return _fetchDynamicConfigWithRetry.apply(this, arguments); } /** * Runs one retry attempt. * @param appFields Necessary app config fields. * @param throttleMetadata Ongoing metadata to determine throttling times. * @param signal Abort signal. */ function _fetchDynamicConfigWithRetry() { _fetchDynamicConfigWithRetry = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app, // retryData and timeoutMillis are parameterized to allow passing a different value for testing. retryData = defaultRetryData, timeoutMillis) { const { appId, apiKey, measurementId } = app.options; if (!appId) { throw ERROR_FACTORY.create("no-app-id" /* AnalyticsError.NO_APP_ID */ ); } if (!apiKey) { if (measurementId) { return { measurementId, appId }; } throw ERROR_FACTORY.create("no-api-key" /* AnalyticsError.NO_API_KEY */ ); } const throttleMetadata = retryData.getThrottleMetadata(appId) || { backoffCount: 0, throttleEndTimeMillis: Date.now() }; const signal = new AnalyticsAbortSignal(); setTimeout( /*#__PURE__*/(0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { // Note a very low delay, eg < 10ms, can elapse before listeners are initialized. signal.abort(); }), timeoutMillis !== undefined ? timeoutMillis : FETCH_TIMEOUT_MILLIS); return attemptFetchDynamicConfigWithRetry({ appId, apiKey, measurementId }, throttleMetadata, signal, retryData); }); return _fetchDynamicConfigWithRetry.apply(this, arguments); } function attemptFetchDynamicConfigWithRetry(_x13, _x14, _x15) { return _attemptFetchDynamicConfigWithRetry.apply(this, arguments); } /** * Supports waiting on a backoff by: * *
Visible for testing. */ function _attemptFetchDynamicConfigWithRetry() { _attemptFetchDynamicConfigWithRetry = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (appFields, { throttleEndTimeMillis, backoffCount }, signal, retryData = defaultRetryData // for testing ) { var _a; const { appId, measurementId } = appFields; // Starts with a (potentially zero) timeout to support resumption from stored state. // Ensures the throttle end time is honored if the last attempt timed out. // Note the SDK will never make a request if the fetch timeout expires at this point. try { yield setAbortableTimeout(signal, throttleEndTimeMillis); } catch (e) { if (measurementId) { logger.warn(`Timed out fetching this Firebase app's measurement ID from the server.` + ` Falling back to the measurement ID ${measurementId}` + ` provided in the "measurementId" field in the local Firebase config. [${e === null || e === void 0 ? void 0 : e.message}]`); return { appId, measurementId }; } throw e; } try { const response = yield fetchDynamicConfig(appFields); // Note the SDK only clears throttle state if response is success or non-retriable. retryData.deleteThrottleMetadata(appId); return response; } catch (e) { const error = e; if (!isRetriableError(error)) { retryData.deleteThrottleMetadata(appId); if (measurementId) { logger.warn(`Failed to fetch this Firebase app's measurement ID from the server.` + ` Falling back to the measurement ID ${measurementId}` + ` provided in the "measurementId" field in the local Firebase config. [${error === null || error === void 0 ? void 0 : error.message}]`); return { appId, measurementId }; } else { throw e; } } const backoffMillis = Number((_a = error === null || error === void 0 ? void 0 : error.customData) === null || _a === void 0 ? void 0 : _a.httpStatus) === 503 ? (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.calculateBackoffMillis)(backoffCount, retryData.intervalMillis, LONG_RETRY_FACTOR) : (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.calculateBackoffMillis)(backoffCount, retryData.intervalMillis); // Increments backoff state. const throttleMetadata = { throttleEndTimeMillis: Date.now() + backoffMillis, backoffCount: backoffCount + 1 }; // Persists state. retryData.setThrottleMetadata(appId, throttleMetadata); logger.debug(`Calling attemptFetch again in ${backoffMillis} millis`); return attemptFetchDynamicConfigWithRetry(appFields, throttleMetadata, signal, retryData); } }); return _attemptFetchDynamicConfigWithRetry.apply(this, arguments); } function setAbortableTimeout(signal, throttleEndTimeMillis) { return new Promise((resolve, reject) => { // Derives backoff from given end time, normalizing negative numbers to zero. const backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0); const timeout = setTimeout(resolve, backoffMillis); // Adds listener, rather than sets onabort, because signal is a shared object. signal.addEventListener(() => { clearTimeout(timeout); // If the request completes before this timeout, the rejection has no effect. reject(ERROR_FACTORY.create("fetch-throttle" /* AnalyticsError.FETCH_THROTTLE */ , { throttleEndTimeMillis })); }); }); } /** * Returns true if the {@link Error} indicates a fetch request may succeed later. */ function isRetriableError(e) { if (!(e instanceof _firebase_util__WEBPACK_IMPORTED_MODULE_3__.FirebaseError) || !e.customData) { return false; } // Uses string index defined by ErrorData, which FirebaseError implements. const httpStatus = Number(e.customData['httpStatus']); return httpStatus === 429 || httpStatus === 500 || httpStatus === 503 || httpStatus === 504; } /** * Shims a minimal AbortSignal (copied from Remote Config). * *
AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects * of networking, such as retries. Firebase doesn't use AbortController enough to justify a * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be * swapped out if/when we do. */ class AnalyticsAbortSignal { constructor() { this.listeners = []; } addEventListener(listener) { this.listeners.push(listener); } abort() { this.listeners.forEach(listener => listener()); } } /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Event parameters to set on 'gtag' during initialization. */ let defaultEventParametersForInit; /** * Logs an analytics event through the Firebase SDK. * * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event * @param eventName Google Analytics event name, choose from standard list or use a custom string. * @param eventParams Analytics event parameters. */ function logEvent$1(_x16, _x17, _x18, _x19, _x20) { return _logEvent$.apply(this, arguments); } /** * Set screen_name parameter for this Google Analytics ID. * * @deprecated Use {@link logEvent} with `eventName` as 'screen_view' and add relevant `eventParams`. * See {@link https://firebase.google.com/docs/analytics/screenviews | Track Screenviews}. * * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event * @param screenName Screen name string to set. */ function _logEvent$() { _logEvent$ = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, eventName, eventParams, options) { if (options && options.global) { gtagFunction("event" /* GtagCommand.EVENT */ , eventName, eventParams); return; } else { const measurementId = yield initializationPromise; const params = Object.assign(Object.assign({}, eventParams), { 'send_to': measurementId }); gtagFunction("event" /* GtagCommand.EVENT */ , eventName, params); } }); return _logEvent$.apply(this, arguments); } function setCurrentScreen$1(_x21, _x22, _x23, _x24) { return _setCurrentScreen$.apply(this, arguments); } /** * Set user_id parameter for this Google Analytics ID. * * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event * @param id User ID string to set */ function _setCurrentScreen$() { _setCurrentScreen$ = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, screenName, options) { if (options && options.global) { gtagFunction("set" /* GtagCommand.SET */ , { 'screen_name': screenName }); return Promise.resolve(); } else { const measurementId = yield initializationPromise; gtagFunction("config" /* GtagCommand.CONFIG */ , measurementId, { update: true, 'screen_name': screenName }); } }); return _setCurrentScreen$.apply(this, arguments); } function setUserId$1(_x25, _x26, _x27, _x28) { return _setUserId$.apply(this, arguments); } /** * Set all other user properties other than user_id and screen_name. * * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event * @param properties Map of user properties to set */ function _setUserId$() { _setUserId$ = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, id, options) { if (options && options.global) { gtagFunction("set" /* GtagCommand.SET */ , { 'user_id': id }); return Promise.resolve(); } else { const measurementId = yield initializationPromise; gtagFunction("config" /* GtagCommand.CONFIG */ , measurementId, { update: true, 'user_id': id }); } }); return _setUserId$.apply(this, arguments); } function setUserProperties$1(_x29, _x30, _x31, _x32) { return _setUserProperties$.apply(this, arguments); } /** * Retrieves a unique Google Analytics identifier for the web client. * See {@link https://developers.google.com/analytics/devguides/collection/ga4/reference/config#client_id | client_id}. * * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event */ function _setUserProperties$() { _setUserProperties$ = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise, properties, options) { if (options && options.global) { const flatProperties = {}; for (const key of Object.keys(properties)) { // use dot notation for merge behavior in gtag.js flatProperties[`user_properties.${key}`] = properties[key]; } gtagFunction("set" /* GtagCommand.SET */ , flatProperties); return Promise.resolve(); } else { const measurementId = yield initializationPromise; gtagFunction("config" /* GtagCommand.CONFIG */ , measurementId, { update: true, 'user_properties': properties }); } }); return _setUserProperties$.apply(this, arguments); } function internalGetGoogleAnalyticsClientId(_x33, _x34) { return _internalGetGoogleAnalyticsClientId.apply(this, arguments); } /** * Set whether collection is enabled for this ID. * * @param enabled If true, collection is enabled for this ID. */ function _internalGetGoogleAnalyticsClientId() { _internalGetGoogleAnalyticsClientId = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (gtagFunction, initializationPromise) { const measurementId = yield initializationPromise; return new Promise((resolve, reject) => { gtagFunction("get" /* GtagCommand.GET */ , measurementId, 'client_id', clientId => { if (!clientId) { reject(ERROR_FACTORY.create("no-client-id" /* AnalyticsError.NO_CLIENT_ID */ )); } resolve(clientId); }); }); }); return _internalGetGoogleAnalyticsClientId.apply(this, arguments); } function setAnalyticsCollectionEnabled$1(_x35, _x36) { return _setAnalyticsCollectionEnabled$.apply(this, arguments); } /** * Consent parameters to default to during 'gtag' initialization. */ function _setAnalyticsCollectionEnabled$() { _setAnalyticsCollectionEnabled$ = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (initializationPromise, enabled) { const measurementId = yield initializationPromise; window[`ga-disable-${measurementId}`] = !enabled; }); return _setAnalyticsCollectionEnabled$.apply(this, arguments); } let defaultConsentSettingsForInit; /** * Sets the variable {@link defaultConsentSettingsForInit} for use in the initialization of * analytics. * * @param consentSettings Maps the applicable end user consent state for gtag.js. */ function _setConsentDefaultForInit(consentSettings) { defaultConsentSettingsForInit = consentSettings; } /** * Sets the variable `defaultEventParametersForInit` for use in the initialization of * analytics. * * @param customParams Any custom params the user may pass to gtag.js. */ function _setDefaultEventParametersForInit(customParams) { defaultEventParametersForInit = customParams; } /** * @license * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ function validateIndexedDB() { return _validateIndexedDB.apply(this, arguments); } /** * Initialize the analytics instance in gtag.js by calling config command with fid. * * NOTE: We combine analytics initialization and setting fid together because we want fid to be * part of the `page_view` event that's sent during the initialization * @param app Firebase app * @param gtagCore The gtag function that's not wrapped. * @param dynamicConfigPromisesList Array of all dynamic config promises. * @param measurementIdToAppId Maps measurementID to appID. * @param installations _FirebaseInstallationsInternal instance. * * @returns Measurement ID. */ function _validateIndexedDB() { _validateIndexedDB = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* () { if (!(0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.isIndexedDBAvailable)()) { logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */ , { errorInfo: 'IndexedDB is not available in this environment.' }).message); return false; } else { try { yield (0,_firebase_util__WEBPACK_IMPORTED_MODULE_3__.validateIndexedDBOpenable)(); } catch (e) { logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */ , { errorInfo: e === null || e === void 0 ? void 0 : e.toString() }).message); return false; } } return true; }); return _validateIndexedDB.apply(this, arguments); } function _initializeAnalytics(_x37, _x38, _x39, _x40, _x41, _x42, _x43) { return _initializeAnalytics2.apply(this, arguments); } /** * @license * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Analytics Service class. */ function _initializeAnalytics2() { _initializeAnalytics2 = (0,_Volumes_case_workspace_work_APPS_KA_APP_WORK_NOW_KA_PASS_V2_2_6_node_modules_babel_runtime_helpers_esm_asyncToGenerator_js__WEBPACK_IMPORTED_MODULE_0__["default"])(function* (app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCore, dataLayerName, options) { var _a; const dynamicConfigPromise = fetchDynamicConfigWithRetry(app); // Once fetched, map measurementIds to appId, for ease of lookup in wrapped gtag function. dynamicConfigPromise.then(config => { measurementIdToAppId[config.measurementId] = config.appId; if (app.options.measurementId && config.measurementId !== app.options.measurementId) { logger.warn(`The measurement ID in the local Firebase config (${app.options.measurementId})` + ` does not match the measurement ID fetched from the server (${config.measurementId}).` + ` To ensure analytics events are always sent to the correct Analytics property,` + ` update the` + ` measurement ID field in the local config or remove it from the local config.`); } }).catch(e => logger.error(e)); // Add to list to track state of all dynamic config promises. dynamicConfigPromisesList.push(dynamicConfigPromise); const fidPromise = validateIndexedDB().then(envIsValid => { if (envIsValid) { return installations.getId(); } else { return undefined; } }); const [dynamicConfig, fid] = yield Promise.all([dynamicConfigPromise, fidPromise]); // Detect if user has already put the gtag