UNPKG

58.8 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var app = require('@firebase/app');
6var tslib = require('tslib');
7var logger$1 = require('@firebase/logger');
8var util = require('@firebase/util');
9var component = require('@firebase/component');
10require('@firebase/installations');
11
12/**
13 * @license
14 * Copyright 2019 Google LLC
15 *
16 * Licensed under the Apache License, Version 2.0 (the "License");
17 * you may not use this file except in compliance with the License.
18 * You may obtain a copy of the License at
19 *
20 * http://www.apache.org/licenses/LICENSE-2.0
21 *
22 * Unless required by applicable law or agreed to in writing, software
23 * distributed under the License is distributed on an "AS IS" BASIS,
24 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 * See the License for the specific language governing permissions and
26 * limitations under the License.
27 */
28/**
29 * Type constant for Firebase Analytics.
30 */
31var ANALYTICS_TYPE = 'analytics';
32// Key to attach FID to in gtag params.
33var GA_FID_KEY = 'firebase_id';
34var ORIGIN_KEY = 'origin';
35var FETCH_TIMEOUT_MILLIS = 60 * 1000;
36var DYNAMIC_CONFIG_URL = 'https://firebase.googleapis.com/v1alpha/projects/-/apps/{app-id}/webConfig';
37var GTAG_URL = 'https://www.googletagmanager.com/gtag/js';
38
39/**
40 * @license
41 * Copyright 2019 Google LLC
42 *
43 * Licensed under the Apache License, Version 2.0 (the "License");
44 * you may not use this file except in compliance with the License.
45 * You may obtain a copy of the License at
46 *
47 * http://www.apache.org/licenses/LICENSE-2.0
48 *
49 * Unless required by applicable law or agreed to in writing, software
50 * distributed under the License is distributed on an "AS IS" BASIS,
51 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 * See the License for the specific language governing permissions and
53 * limitations under the License.
54 */
55var logger = new logger$1.Logger('@firebase/analytics');
56
57/**
58 * @license
59 * Copyright 2019 Google LLC
60 *
61 * Licensed under the Apache License, Version 2.0 (the "License");
62 * you may not use this file except in compliance with the License.
63 * You may obtain a copy of the License at
64 *
65 * http://www.apache.org/licenses/LICENSE-2.0
66 *
67 * Unless required by applicable law or agreed to in writing, software
68 * distributed under the License is distributed on an "AS IS" BASIS,
69 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70 * See the License for the specific language governing permissions and
71 * limitations under the License.
72 */
73/**
74 * Makeshift polyfill for Promise.allSettled(). Resolves when all promises
75 * have either resolved or rejected.
76 *
77 * @param promises Array of promises to wait for.
78 */
79function promiseAllSettled(promises) {
80 return Promise.all(promises.map(function (promise) { return promise.catch(function (e) { return e; }); }));
81}
82/**
83 * Inserts gtag script tag into the page to asynchronously download gtag.
84 * @param dataLayerName Name of datalayer (most often the default, "_dataLayer").
85 */
86function insertScriptTag(dataLayerName, measurementId) {
87 var script = document.createElement('script');
88 // We are not providing an analyticsId in the URL because it would trigger a `page_view`
89 // without fid. We will initialize ga-id using gtag (config) command together with fid.
90 script.src = GTAG_URL + "?l=" + dataLayerName + "&id=" + measurementId;
91 script.async = true;
92 document.head.appendChild(script);
93}
94/**
95 * Get reference to, or create, global datalayer.
96 * @param dataLayerName Name of datalayer (most often the default, "_dataLayer").
97 */
98function getOrCreateDataLayer(dataLayerName) {
99 // Check for existing dataLayer and create if needed.
100 var dataLayer = [];
101 if (Array.isArray(window[dataLayerName])) {
102 dataLayer = window[dataLayerName];
103 }
104 else {
105 window[dataLayerName] = dataLayer;
106 }
107 return dataLayer;
108}
109/**
110 * Wrapped gtag logic when gtag is called with 'config' command.
111 *
112 * @param gtagCore Basic gtag function that just appends to dataLayer.
113 * @param initializationPromisesMap Map of appIds to their initialization promises.
114 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
115 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
116 * @param measurementId GA Measurement ID to set config for.
117 * @param gtagParams Gtag config params to set.
118 */
119function gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams) {
120 return tslib.__awaiter(this, void 0, void 0, function () {
121 var correspondingAppId, dynamicConfigResults, foundConfig, e_1;
122 return tslib.__generator(this, function (_a) {
123 switch (_a.label) {
124 case 0:
125 correspondingAppId = measurementIdToAppId[measurementId];
126 _a.label = 1;
127 case 1:
128 _a.trys.push([1, 7, , 8]);
129 if (!correspondingAppId) return [3 /*break*/, 3];
130 return [4 /*yield*/, initializationPromisesMap[correspondingAppId]];
131 case 2:
132 _a.sent();
133 return [3 /*break*/, 6];
134 case 3: return [4 /*yield*/, promiseAllSettled(dynamicConfigPromisesList)];
135 case 4:
136 dynamicConfigResults = _a.sent();
137 foundConfig = dynamicConfigResults.find(function (config) { return config.measurementId === measurementId; });
138 if (!foundConfig) return [3 /*break*/, 6];
139 return [4 /*yield*/, initializationPromisesMap[foundConfig.appId]];
140 case 5:
141 _a.sent();
142 _a.label = 6;
143 case 6: return [3 /*break*/, 8];
144 case 7:
145 e_1 = _a.sent();
146 logger.error(e_1);
147 return [3 /*break*/, 8];
148 case 8:
149 gtagCore("config" /* CONFIG */, measurementId, gtagParams);
150 return [2 /*return*/];
151 }
152 });
153 });
154}
155/**
156 * Wrapped gtag logic when gtag is called with 'event' command.
157 *
158 * @param gtagCore Basic gtag function that just appends to dataLayer.
159 * @param initializationPromisesMap Map of appIds to their initialization promises.
160 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
161 * @param measurementId GA Measurement ID to log event to.
162 * @param gtagParams Params to log with this event.
163 */
164function gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams) {
165 return tslib.__awaiter(this, void 0, void 0, function () {
166 var initializationPromisesToWaitFor, gaSendToList, dynamicConfigResults, _loop_1, _i, gaSendToList_1, sendToId, state_1, e_2;
167 return tslib.__generator(this, function (_a) {
168 switch (_a.label) {
169 case 0:
170 _a.trys.push([0, 4, , 5]);
171 initializationPromisesToWaitFor = [];
172 if (!(gtagParams && gtagParams['send_to'])) return [3 /*break*/, 2];
173 gaSendToList = gtagParams['send_to'];
174 // Make it an array if is isn't, so it can be dealt with the same way.
175 if (!Array.isArray(gaSendToList)) {
176 gaSendToList = [gaSendToList];
177 }
178 return [4 /*yield*/, promiseAllSettled(dynamicConfigPromisesList)];
179 case 1:
180 dynamicConfigResults = _a.sent();
181 _loop_1 = function (sendToId) {
182 // Any fetched dynamic measurement ID that matches this 'send_to' ID
183 var foundConfig = dynamicConfigResults.find(function (config) { return config.measurementId === sendToId; });
184 var initializationPromise = foundConfig && initializationPromisesMap[foundConfig.appId];
185 if (initializationPromise) {
186 initializationPromisesToWaitFor.push(initializationPromise);
187 }
188 else {
189 // Found an item in 'send_to' that is not associated
190 // directly with an FID, possibly a group. Empty this array,
191 // exit the loop early, and let it get populated below.
192 initializationPromisesToWaitFor = [];
193 return "break";
194 }
195 };
196 for (_i = 0, gaSendToList_1 = gaSendToList; _i < gaSendToList_1.length; _i++) {
197 sendToId = gaSendToList_1[_i];
198 state_1 = _loop_1(sendToId);
199 if (state_1 === "break")
200 break;
201 }
202 _a.label = 2;
203 case 2:
204 // This will be unpopulated if there was no 'send_to' field , or
205 // if not all entries in the 'send_to' field could be mapped to
206 // a FID. In these cases, wait on all pending initialization promises.
207 if (initializationPromisesToWaitFor.length === 0) {
208 initializationPromisesToWaitFor = Object.values(initializationPromisesMap);
209 }
210 // Run core gtag function with args after all relevant initialization
211 // promises have been resolved.
212 return [4 /*yield*/, Promise.all(initializationPromisesToWaitFor)];
213 case 3:
214 // Run core gtag function with args after all relevant initialization
215 // promises have been resolved.
216 _a.sent();
217 // Workaround for http://b/141370449 - third argument cannot be undefined.
218 gtagCore("event" /* EVENT */, measurementId, gtagParams || {});
219 return [3 /*break*/, 5];
220 case 4:
221 e_2 = _a.sent();
222 logger.error(e_2);
223 return [3 /*break*/, 5];
224 case 5: return [2 /*return*/];
225 }
226 });
227 });
228}
229/**
230 * Wraps a standard gtag function with extra code to wait for completion of
231 * relevant initialization promises before sending requests.
232 *
233 * @param gtagCore Basic gtag function that just appends to dataLayer.
234 * @param initializationPromisesMap Map of appIds to their initialization promises.
235 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
236 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
237 */
238function wrapGtag(gtagCore,
239/**
240 * Allows wrapped gtag calls to wait on whichever intialization promises are required,
241 * depending on the contents of the gtag params' `send_to` field, if any.
242 */
243initializationPromisesMap,
244/**
245 * Wrapped gtag calls sometimes require all dynamic config fetches to have returned
246 * before determining what initialization promises (which include FIDs) to wait for.
247 */
248dynamicConfigPromisesList,
249/**
250 * Wrapped gtag config calls can narrow down which initialization promise (with FID)
251 * to wait for if the measurementId is already fetched, by getting the corresponding appId,
252 * which is the key for the initialization promises map.
253 */
254measurementIdToAppId) {
255 /**
256 * Wrapper around gtag that ensures FID is sent with gtag calls.
257 * @param command Gtag command type.
258 * @param idOrNameOrParams Measurement ID if command is EVENT/CONFIG, params if command is SET.
259 * @param gtagParams Params if event is EVENT/CONFIG.
260 */
261 function gtagWrapper(command, idOrNameOrParams, gtagParams) {
262 return tslib.__awaiter(this, void 0, void 0, function () {
263 var e_3;
264 return tslib.__generator(this, function (_a) {
265 switch (_a.label) {
266 case 0:
267 _a.trys.push([0, 6, , 7]);
268 if (!(command === "event" /* EVENT */)) return [3 /*break*/, 2];
269 // If EVENT, second arg must be measurementId.
270 return [4 /*yield*/, gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, idOrNameOrParams, gtagParams)];
271 case 1:
272 // If EVENT, second arg must be measurementId.
273 _a.sent();
274 return [3 /*break*/, 5];
275 case 2:
276 if (!(command === "config" /* CONFIG */)) return [3 /*break*/, 4];
277 // If CONFIG, second arg must be measurementId.
278 return [4 /*yield*/, gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, idOrNameOrParams, gtagParams)];
279 case 3:
280 // If CONFIG, second arg must be measurementId.
281 _a.sent();
282 return [3 /*break*/, 5];
283 case 4:
284 // If SET, second arg must be params.
285 gtagCore("set" /* SET */, idOrNameOrParams);
286 _a.label = 5;
287 case 5: return [3 /*break*/, 7];
288 case 6:
289 e_3 = _a.sent();
290 logger.error(e_3);
291 return [3 /*break*/, 7];
292 case 7: return [2 /*return*/];
293 }
294 });
295 });
296 }
297 return gtagWrapper;
298}
299/**
300 * Creates global gtag function or wraps existing one if found.
301 * This wrapped function attaches Firebase instance ID (FID) to gtag 'config' and
302 * 'event' calls that belong to the GAID associated with this Firebase instance.
303 *
304 * @param initializationPromisesMap Map of appIds to their initialization promises.
305 * @param dynamicConfigPromisesList Array of dynamic config fetch promises.
306 * @param measurementIdToAppId Map of GA measurementIDs to corresponding Firebase appId.
307 * @param dataLayerName Name of global GA datalayer array.
308 * @param gtagFunctionName Name of global gtag function ("gtag" if not user-specified).
309 */
310function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagFunctionName) {
311 // Create a basic core gtag function
312 var gtagCore = function () {
313 var _args = [];
314 for (var _i = 0; _i < arguments.length; _i++) {
315 _args[_i] = arguments[_i];
316 }
317 // Must push IArguments object, not an array.
318 window[dataLayerName].push(arguments);
319 };
320 // Replace it with existing one if found
321 if (window[gtagFunctionName] &&
322 typeof window[gtagFunctionName] === 'function') {
323 // @ts-ignore
324 gtagCore = window[gtagFunctionName];
325 }
326 window[gtagFunctionName] = wrapGtag(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId);
327 return {
328 gtagCore: gtagCore,
329 wrappedGtag: window[gtagFunctionName]
330 };
331}
332/**
333 * Returns first script tag in DOM matching our gtag url pattern.
334 */
335function findGtagScriptOnPage() {
336 var scriptTags = window.document.getElementsByTagName('script');
337 for (var _i = 0, _a = Object.values(scriptTags); _i < _a.length; _i++) {
338 var tag = _a[_i];
339 if (tag.src && tag.src.includes(GTAG_URL)) {
340 return tag;
341 }
342 }
343 return null;
344}
345
346/**
347 * @license
348 * Copyright 2019 Google LLC
349 *
350 * Licensed under the Apache License, Version 2.0 (the "License");
351 * you may not use this file except in compliance with the License.
352 * You may obtain a copy of the License at
353 *
354 * http://www.apache.org/licenses/LICENSE-2.0
355 *
356 * Unless required by applicable law or agreed to in writing, software
357 * distributed under the License is distributed on an "AS IS" BASIS,
358 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
359 * See the License for the specific language governing permissions and
360 * limitations under the License.
361 */
362var _a;
363var ERRORS = (_a = {},
364 _a["already-exists" /* ALREADY_EXISTS */] = 'A Firebase Analytics instance with the appId {$id} ' +
365 ' already exists. ' +
366 'Only one Firebase Analytics instance can be created for each appId.',
367 _a["already-initialized" /* ALREADY_INITIALIZED */] = 'initializeAnalytics() cannot be called again with different options than those ' +
368 'it was initially called with. It can be called again with the same options to ' +
369 'return the existing instance, or getAnalytics() can be used ' +
370 'to get a reference to the already-intialized instance.',
371 _a["already-initialized-settings" /* ALREADY_INITIALIZED_SETTINGS */] = 'Firebase Analytics has already been initialized.' +
372 'settings() must be called before initializing any Analytics instance' +
373 'or it will have no effect.',
374 _a["interop-component-reg-failed" /* INTEROP_COMPONENT_REG_FAILED */] = 'Firebase Analytics Interop Component failed to instantiate: {$reason}',
375 _a["invalid-analytics-context" /* INVALID_ANALYTICS_CONTEXT */] = 'Firebase Analytics is not supported in this environment. ' +
376 'Wrap initialization of analytics in analytics.isSupported() ' +
377 'to prevent initialization in unsupported environments. Details: {$errorInfo}',
378 _a["indexeddb-unavailable" /* INDEXEDDB_UNAVAILABLE */] = 'IndexedDB unavailable or restricted in this environment. ' +
379 'Wrap initialization of analytics in analytics.isSupported() ' +
380 'to prevent initialization in unsupported environments. Details: {$errorInfo}',
381 _a["fetch-throttle" /* FETCH_THROTTLE */] = 'The config fetch request timed out while in an exponential backoff state.' +
382 ' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',
383 _a["config-fetch-failed" /* CONFIG_FETCH_FAILED */] = 'Dynamic config fetch failed: [{$httpStatus}] {$responseMessage}',
384 _a["no-api-key" /* NO_API_KEY */] = 'The "apiKey" field is empty in the local Firebase config. Firebase Analytics requires this field to' +
385 'contain a valid API key.',
386 _a["no-app-id" /* NO_APP_ID */] = 'The "appId" field is empty in the local Firebase config. Firebase Analytics requires this field to' +
387 'contain a valid app ID.',
388 _a);
389var ERROR_FACTORY = new util.ErrorFactory('analytics', 'Analytics', ERRORS);
390
391/**
392 * @license
393 * Copyright 2020 Google LLC
394 *
395 * Licensed under the Apache License, Version 2.0 (the "License");
396 * you may not use this file except in compliance with the License.
397 * You may obtain a copy of the License at
398 *
399 * http://www.apache.org/licenses/LICENSE-2.0
400 *
401 * Unless required by applicable law or agreed to in writing, software
402 * distributed under the License is distributed on an "AS IS" BASIS,
403 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
404 * See the License for the specific language governing permissions and
405 * limitations under the License.
406 */
407/**
408 * Backoff factor for 503 errors, which we want to be conservative about
409 * to avoid overloading servers. Each retry interval will be
410 * BASE_INTERVAL_MILLIS * LONG_RETRY_FACTOR ^ retryCount, so the second one
411 * will be ~30 seconds (with fuzzing).
412 */
413var LONG_RETRY_FACTOR = 30;
414/**
415 * Base wait interval to multiplied by backoffFactor^backoffCount.
416 */
417var BASE_INTERVAL_MILLIS = 1000;
418/**
419 * Stubbable retry data storage class.
420 */
421var RetryData = /** @class */ (function () {
422 function RetryData(throttleMetadata, intervalMillis) {
423 if (throttleMetadata === void 0) { throttleMetadata = {}; }
424 if (intervalMillis === void 0) { intervalMillis = BASE_INTERVAL_MILLIS; }
425 this.throttleMetadata = throttleMetadata;
426 this.intervalMillis = intervalMillis;
427 }
428 RetryData.prototype.getThrottleMetadata = function (appId) {
429 return this.throttleMetadata[appId];
430 };
431 RetryData.prototype.setThrottleMetadata = function (appId, metadata) {
432 this.throttleMetadata[appId] = metadata;
433 };
434 RetryData.prototype.deleteThrottleMetadata = function (appId) {
435 delete this.throttleMetadata[appId];
436 };
437 return RetryData;
438}());
439var defaultRetryData = new RetryData();
440/**
441 * Set GET request headers.
442 * @param apiKey App API key.
443 */
444function getHeaders(apiKey) {
445 return new Headers({
446 Accept: 'application/json',
447 'x-goog-api-key': apiKey
448 });
449}
450/**
451 * Fetches dynamic config from backend.
452 * @param app Firebase app to fetch config for.
453 */
454function fetchDynamicConfig(appFields) {
455 var _a;
456 return tslib.__awaiter(this, void 0, void 0, function () {
457 var appId, apiKey, request, appUrl, response, errorMessage, jsonResponse;
458 return tslib.__generator(this, function (_b) {
459 switch (_b.label) {
460 case 0:
461 appId = appFields.appId, apiKey = appFields.apiKey;
462 request = {
463 method: 'GET',
464 headers: getHeaders(apiKey)
465 };
466 appUrl = DYNAMIC_CONFIG_URL.replace('{app-id}', appId);
467 return [4 /*yield*/, fetch(appUrl, request)];
468 case 1:
469 response = _b.sent();
470 if (!(response.status !== 200 && response.status !== 304)) return [3 /*break*/, 6];
471 errorMessage = '';
472 _b.label = 2;
473 case 2:
474 _b.trys.push([2, 4, , 5]);
475 return [4 /*yield*/, response.json()];
476 case 3:
477 jsonResponse = (_b.sent());
478 if ((_a = jsonResponse.error) === null || _a === void 0 ? void 0 : _a.message) {
479 errorMessage = jsonResponse.error.message;
480 }
481 return [3 /*break*/, 5];
482 case 4:
483 _b.sent();
484 return [3 /*break*/, 5];
485 case 5: throw ERROR_FACTORY.create("config-fetch-failed" /* CONFIG_FETCH_FAILED */, {
486 httpStatus: response.status,
487 responseMessage: errorMessage
488 });
489 case 6: return [2 /*return*/, response.json()];
490 }
491 });
492 });
493}
494/**
495 * Fetches dynamic config from backend, retrying if failed.
496 * @param app Firebase app to fetch config for.
497 */
498function fetchDynamicConfigWithRetry(app,
499// retryData and timeoutMillis are parameterized to allow passing a different value for testing.
500retryData, timeoutMillis) {
501 if (retryData === void 0) { retryData = defaultRetryData; }
502 return tslib.__awaiter(this, void 0, void 0, function () {
503 var _a, appId, apiKey, measurementId, throttleMetadata, signal;
504 var _this = this;
505 return tslib.__generator(this, function (_b) {
506 _a = app.options, appId = _a.appId, apiKey = _a.apiKey, measurementId = _a.measurementId;
507 if (!appId) {
508 throw ERROR_FACTORY.create("no-app-id" /* NO_APP_ID */);
509 }
510 if (!apiKey) {
511 if (measurementId) {
512 return [2 /*return*/, {
513 measurementId: measurementId,
514 appId: appId
515 }];
516 }
517 throw ERROR_FACTORY.create("no-api-key" /* NO_API_KEY */);
518 }
519 throttleMetadata = retryData.getThrottleMetadata(appId) || {
520 backoffCount: 0,
521 throttleEndTimeMillis: Date.now()
522 };
523 signal = new AnalyticsAbortSignal();
524 setTimeout(function () { return tslib.__awaiter(_this, void 0, void 0, function () {
525 return tslib.__generator(this, function (_a) {
526 // Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
527 signal.abort();
528 return [2 /*return*/];
529 });
530 }); }, timeoutMillis !== undefined ? timeoutMillis : FETCH_TIMEOUT_MILLIS);
531 return [2 /*return*/, attemptFetchDynamicConfigWithRetry({ appId: appId, apiKey: apiKey, measurementId: measurementId }, throttleMetadata, signal, retryData)];
532 });
533 });
534}
535/**
536 * Runs one retry attempt.
537 * @param appFields Necessary app config fields.
538 * @param throttleMetadata Ongoing metadata to determine throttling times.
539 * @param signal Abort signal.
540 */
541function attemptFetchDynamicConfigWithRetry(appFields, _a, signal, retryData // for testing
542) {
543 var _b, _c;
544 var throttleEndTimeMillis = _a.throttleEndTimeMillis, backoffCount = _a.backoffCount;
545 if (retryData === void 0) { retryData = defaultRetryData; }
546 return tslib.__awaiter(this, void 0, void 0, function () {
547 var appId, measurementId, e_1, response, e_2, error, backoffMillis, throttleMetadata;
548 return tslib.__generator(this, function (_d) {
549 switch (_d.label) {
550 case 0:
551 appId = appFields.appId, measurementId = appFields.measurementId;
552 _d.label = 1;
553 case 1:
554 _d.trys.push([1, 3, , 4]);
555 return [4 /*yield*/, setAbortableTimeout(signal, throttleEndTimeMillis)];
556 case 2:
557 _d.sent();
558 return [3 /*break*/, 4];
559 case 3:
560 e_1 = _d.sent();
561 if (measurementId) {
562 logger.warn("Timed out fetching this Firebase app's measurement ID from the server." +
563 (" Falling back to the measurement ID " + measurementId) +
564 (" provided in the \"measurementId\" field in the local Firebase config. [" + ((_b = e_1) === null || _b === void 0 ? void 0 : _b.message) + "]"));
565 return [2 /*return*/, { appId: appId, measurementId: measurementId }];
566 }
567 throw e_1;
568 case 4:
569 _d.trys.push([4, 6, , 7]);
570 return [4 /*yield*/, fetchDynamicConfig(appFields)];
571 case 5:
572 response = _d.sent();
573 // Note the SDK only clears throttle state if response is success or non-retriable.
574 retryData.deleteThrottleMetadata(appId);
575 return [2 /*return*/, response];
576 case 6:
577 e_2 = _d.sent();
578 error = e_2;
579 if (!isRetriableError(error)) {
580 retryData.deleteThrottleMetadata(appId);
581 if (measurementId) {
582 logger.warn("Failed to fetch this Firebase app's measurement ID from the server." +
583 (" Falling back to the measurement ID " + measurementId) +
584 (" provided in the \"measurementId\" field in the local Firebase config. [" + (error === null || error === void 0 ? void 0 : error.message) + "]"));
585 return [2 /*return*/, { appId: appId, measurementId: measurementId }];
586 }
587 else {
588 throw e_2;
589 }
590 }
591 backoffMillis = Number((_c = error === null || error === void 0 ? void 0 : error.customData) === null || _c === void 0 ? void 0 : _c.httpStatus) === 503
592 ? util.calculateBackoffMillis(backoffCount, retryData.intervalMillis, LONG_RETRY_FACTOR)
593 : util.calculateBackoffMillis(backoffCount, retryData.intervalMillis);
594 throttleMetadata = {
595 throttleEndTimeMillis: Date.now() + backoffMillis,
596 backoffCount: backoffCount + 1
597 };
598 // Persists state.
599 retryData.setThrottleMetadata(appId, throttleMetadata);
600 logger.debug("Calling attemptFetch again in " + backoffMillis + " millis");
601 return [2 /*return*/, attemptFetchDynamicConfigWithRetry(appFields, throttleMetadata, signal, retryData)];
602 case 7: return [2 /*return*/];
603 }
604 });
605 });
606}
607/**
608 * Supports waiting on a backoff by:
609 *
610 * <ul>
611 * <li>Promisifying setTimeout, so we can set a timeout in our Promise chain</li>
612 * <li>Listening on a signal bus for abort events, just like the Fetch API</li>
613 * <li>Failing in the same way the Fetch API fails, so timing out a live request and a throttled
614 * request appear the same.</li>
615 * </ul>
616 *
617 * <p>Visible for testing.
618 */
619function setAbortableTimeout(signal, throttleEndTimeMillis) {
620 return new Promise(function (resolve, reject) {
621 // Derives backoff from given end time, normalizing negative numbers to zero.
622 var backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);
623 var timeout = setTimeout(resolve, backoffMillis);
624 // Adds listener, rather than sets onabort, because signal is a shared object.
625 signal.addEventListener(function () {
626 clearTimeout(timeout);
627 // If the request completes before this timeout, the rejection has no effect.
628 reject(ERROR_FACTORY.create("fetch-throttle" /* FETCH_THROTTLE */, {
629 throttleEndTimeMillis: throttleEndTimeMillis
630 }));
631 });
632 });
633}
634/**
635 * Returns true if the {@link Error} indicates a fetch request may succeed later.
636 */
637function isRetriableError(e) {
638 if (!(e instanceof util.FirebaseError) || !e.customData) {
639 return false;
640 }
641 // Uses string index defined by ErrorData, which FirebaseError implements.
642 var httpStatus = Number(e.customData['httpStatus']);
643 return (httpStatus === 429 ||
644 httpStatus === 500 ||
645 httpStatus === 503 ||
646 httpStatus === 504);
647}
648/**
649 * Shims a minimal AbortSignal (copied from Remote Config).
650 *
651 * <p>AbortController's AbortSignal conveniently decouples fetch timeout logic from other aspects
652 * of networking, such as retries. Firebase doesn't use AbortController enough to justify a
653 * polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be
654 * swapped out if/when we do.
655 */
656var AnalyticsAbortSignal = /** @class */ (function () {
657 function AnalyticsAbortSignal() {
658 this.listeners = [];
659 }
660 AnalyticsAbortSignal.prototype.addEventListener = function (listener) {
661 this.listeners.push(listener);
662 };
663 AnalyticsAbortSignal.prototype.abort = function () {
664 this.listeners.forEach(function (listener) { return listener(); });
665 };
666 return AnalyticsAbortSignal;
667}());
668
669/**
670 * @license
671 * Copyright 2020 Google LLC
672 *
673 * Licensed under the Apache License, Version 2.0 (the "License");
674 * you may not use this file except in compliance with the License.
675 * You may obtain a copy of the License at
676 *
677 * http://www.apache.org/licenses/LICENSE-2.0
678 *
679 * Unless required by applicable law or agreed to in writing, software
680 * distributed under the License is distributed on an "AS IS" BASIS,
681 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
682 * See the License for the specific language governing permissions and
683 * limitations under the License.
684 */
685function validateIndexedDB() {
686 var _a;
687 return tslib.__awaiter(this, void 0, void 0, function () {
688 var e_1;
689 return tslib.__generator(this, function (_b) {
690 switch (_b.label) {
691 case 0:
692 if (!!util.isIndexedDBAvailable()) return [3 /*break*/, 1];
693 logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* INDEXEDDB_UNAVAILABLE */, {
694 errorInfo: 'IndexedDB is not available in this environment.'
695 }).message);
696 return [2 /*return*/, false];
697 case 1:
698 _b.trys.push([1, 3, , 4]);
699 return [4 /*yield*/, util.validateIndexedDBOpenable()];
700 case 2:
701 _b.sent();
702 return [3 /*break*/, 4];
703 case 3:
704 e_1 = _b.sent();
705 logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* INDEXEDDB_UNAVAILABLE */, {
706 errorInfo: (_a = e_1) === null || _a === void 0 ? void 0 : _a.toString()
707 }).message);
708 return [2 /*return*/, false];
709 case 4: return [2 /*return*/, true];
710 }
711 });
712 });
713}
714/**
715 * Initialize the analytics instance in gtag.js by calling config command with fid.
716 *
717 * NOTE: We combine analytics initialization and setting fid together because we want fid to be
718 * part of the `page_view` event that's sent during the initialization
719 * @param app Firebase app
720 * @param gtagCore The gtag function that's not wrapped.
721 * @param dynamicConfigPromisesList Array of all dynamic config promises.
722 * @param measurementIdToAppId Maps measurementID to appID.
723 * @param installations _FirebaseInstallationsInternal instance.
724 *
725 * @returns Measurement ID.
726 */
727function _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCore, dataLayerName, options) {
728 var _a;
729 return tslib.__awaiter(this, void 0, void 0, function () {
730 var dynamicConfigPromise, fidPromise, _b, dynamicConfig, fid, configProperties;
731 return tslib.__generator(this, function (_c) {
732 switch (_c.label) {
733 case 0:
734 dynamicConfigPromise = fetchDynamicConfigWithRetry(app);
735 // Once fetched, map measurementIds to appId, for ease of lookup in wrapped gtag function.
736 dynamicConfigPromise
737 .then(function (config) {
738 measurementIdToAppId[config.measurementId] = config.appId;
739 if (app.options.measurementId &&
740 config.measurementId !== app.options.measurementId) {
741 logger.warn("The measurement ID in the local Firebase config (" + app.options.measurementId + ")" +
742 (" does not match the measurement ID fetched from the server (" + config.measurementId + ").") +
743 " To ensure analytics events are always sent to the correct Analytics property," +
744 " update the" +
745 " measurement ID field in the local config or remove it from the local config.");
746 }
747 })
748 .catch(function (e) { return logger.error(e); });
749 // Add to list to track state of all dynamic config promises.
750 dynamicConfigPromisesList.push(dynamicConfigPromise);
751 fidPromise = validateIndexedDB().then(function (envIsValid) {
752 if (envIsValid) {
753 return installations.getId();
754 }
755 else {
756 return undefined;
757 }
758 });
759 return [4 /*yield*/, Promise.all([
760 dynamicConfigPromise,
761 fidPromise
762 ])];
763 case 1:
764 _b = _c.sent(), dynamicConfig = _b[0], fid = _b[1];
765 // Detect if user has already put the gtag <script> tag on this page.
766 if (!findGtagScriptOnPage()) {
767 insertScriptTag(dataLayerName, dynamicConfig.measurementId);
768 }
769 // This command initializes gtag.js and only needs to be called once for the entire web app,
770 // but since it is idempotent, we can call it multiple times.
771 // We keep it together with other initialization logic for better code structure.
772 // eslint-disable-next-line @typescript-eslint/no-explicit-any
773 gtagCore('js', new Date());
774 configProperties = (_a = options === null || options === void 0 ? void 0 : options.config) !== null && _a !== void 0 ? _a : {};
775 // guard against developers accidentally setting properties with prefix `firebase_`
776 configProperties[ORIGIN_KEY] = 'firebase';
777 configProperties.update = true;
778 if (fid != null) {
779 configProperties[GA_FID_KEY] = fid;
780 }
781 // It should be the first config command called on this GA-ID
782 // Initialize this GA-ID and set FID on it using the gtag config API.
783 // Note: This will trigger a page_view event unless 'send_page_view' is set to false in
784 // `configProperties`.
785 gtagCore("config" /* CONFIG */, dynamicConfig.measurementId, configProperties);
786 return [2 /*return*/, dynamicConfig.measurementId];
787 }
788 });
789 });
790}
791
792/**
793 * @license
794 * Copyright 2019 Google LLC
795 *
796 * Licensed under the Apache License, Version 2.0 (the "License");
797 * you may not use this file except in compliance with the License.
798 * You may obtain a copy of the License at
799 *
800 * http://www.apache.org/licenses/LICENSE-2.0
801 *
802 * Unless required by applicable law or agreed to in writing, software
803 * distributed under the License is distributed on an "AS IS" BASIS,
804 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
805 * See the License for the specific language governing permissions and
806 * limitations under the License.
807 */
808/**
809 * Analytics Service class.
810 */
811var AnalyticsService = /** @class */ (function () {
812 function AnalyticsService(app) {
813 this.app = app;
814 }
815 AnalyticsService.prototype._delete = function () {
816 delete initializationPromisesMap[this.app.options.appId];
817 return Promise.resolve();
818 };
819 return AnalyticsService;
820}());
821/**
822 * Maps appId to full initialization promise. Wrapped gtag calls must wait on
823 * all or some of these, depending on the call's `send_to` param and the status
824 * of the dynamic config fetches (see below).
825 */
826var initializationPromisesMap = {};
827/**
828 * List of dynamic config fetch promises. In certain cases, wrapped gtag calls
829 * wait on all these to be complete in order to determine if it can selectively
830 * wait for only certain initialization (FID) promises or if it must wait for all.
831 */
832var dynamicConfigPromisesList = [];
833/**
834 * Maps fetched measurementIds to appId. Populated when the app's dynamic config
835 * fetch completes. If already populated, gtag config calls can use this to
836 * selectively wait for only this app's initialization promise (FID) instead of all
837 * initialization promises.
838 */
839var measurementIdToAppId = {};
840/**
841 * Name for window global data layer array used by GA: defaults to 'dataLayer'.
842 */
843var dataLayerName = 'dataLayer';
844/**
845 * Name for window global gtag function used by GA: defaults to 'gtag'.
846 */
847var gtagName = 'gtag';
848/**
849 * Reproduction of standard gtag function or reference to existing
850 * gtag function on window object.
851 */
852var gtagCoreFunction;
853/**
854 * Wrapper around gtag function that ensures FID is sent with all
855 * relevant event and config calls.
856 */
857var wrappedGtagFunction;
858/**
859 * Flag to ensure page initialization steps (creation or wrapping of
860 * dataLayer and gtag script) are only run once per page load.
861 */
862var globalInitDone = false;
863/**
864 * Configures Firebase Analytics to use custom `gtag` or `dataLayer` names.
865 * Intended to be used if `gtag.js` script has been installed on
866 * this page independently of Firebase Analytics, and is using non-default
867 * names for either the `gtag` function or for `dataLayer`.
868 * Must be called before calling `getAnalytics()` or it won't
869 * have any effect.
870 *
871 * @public
872 *
873 * @param options - Custom gtag and dataLayer names.
874 */
875function settings(options) {
876 if (globalInitDone) {
877 throw ERROR_FACTORY.create("already-initialized" /* ALREADY_INITIALIZED */);
878 }
879 if (options.dataLayerName) {
880 dataLayerName = options.dataLayerName;
881 }
882 if (options.gtagName) {
883 gtagName = options.gtagName;
884 }
885}
886/**
887 * Returns true if no environment mismatch is found.
888 * If environment mismatches are found, throws an INVALID_ANALYTICS_CONTEXT
889 * error that also lists details for each mismatch found.
890 */
891function warnOnBrowserContextMismatch() {
892 var mismatchedEnvMessages = [];
893 if (util.isBrowserExtension()) {
894 mismatchedEnvMessages.push('This is a browser extension environment.');
895 }
896 if (!util.areCookiesEnabled()) {
897 mismatchedEnvMessages.push('Cookies are not available.');
898 }
899 if (mismatchedEnvMessages.length > 0) {
900 var details = mismatchedEnvMessages
901 .map(function (message, index) { return "(" + (index + 1) + ") " + message; })
902 .join(' ');
903 var err = ERROR_FACTORY.create("invalid-analytics-context" /* INVALID_ANALYTICS_CONTEXT */, {
904 errorInfo: details
905 });
906 logger.warn(err.message);
907 }
908}
909/**
910 * Analytics instance factory.
911 * @internal
912 */
913function factory(app, installations, options) {
914 warnOnBrowserContextMismatch();
915 var appId = app.options.appId;
916 if (!appId) {
917 throw ERROR_FACTORY.create("no-app-id" /* NO_APP_ID */);
918 }
919 if (!app.options.apiKey) {
920 if (app.options.measurementId) {
921 logger.warn("The \"apiKey\" field is empty in the local Firebase config. This is needed to fetch the latest" +
922 (" measurement ID for this Firebase app. Falling back to the measurement ID " + app.options.measurementId) +
923 " provided in the \"measurementId\" field in the local Firebase config.");
924 }
925 else {
926 throw ERROR_FACTORY.create("no-api-key" /* NO_API_KEY */);
927 }
928 }
929 if (initializationPromisesMap[appId] != null) {
930 throw ERROR_FACTORY.create("already-exists" /* ALREADY_EXISTS */, {
931 id: appId
932 });
933 }
934 if (!globalInitDone) {
935 // Steps here should only be done once per page: creation or wrapping
936 // of dataLayer and global gtag function.
937 getOrCreateDataLayer(dataLayerName);
938 var _a = wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagName), wrappedGtag = _a.wrappedGtag, gtagCore = _a.gtagCore;
939 wrappedGtagFunction = wrappedGtag;
940 gtagCoreFunction = gtagCore;
941 globalInitDone = true;
942 }
943 // Async but non-blocking.
944 // This map reflects the completion state of all promises for each appId.
945 initializationPromisesMap[appId] = _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCoreFunction, dataLayerName, options);
946 var analyticsInstance = new AnalyticsService(app);
947 return analyticsInstance;
948}
949
950/**
951 * @license
952 * Copyright 2019 Google LLC
953 *
954 * Licensed under the Apache License, Version 2.0 (the "License");
955 * you may not use this file except in compliance with the License.
956 * You may obtain a copy of the License at
957 *
958 * http://www.apache.org/licenses/LICENSE-2.0
959 *
960 * Unless required by applicable law or agreed to in writing, software
961 * distributed under the License is distributed on an "AS IS" BASIS,
962 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
963 * See the License for the specific language governing permissions and
964 * limitations under the License.
965 */
966/**
967 * Logs an analytics event through the Firebase SDK.
968 *
969 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
970 * @param eventName Google Analytics event name, choose from standard list or use a custom string.
971 * @param eventParams Analytics event parameters.
972 */
973function logEvent$1(gtagFunction, initializationPromise, eventName, eventParams, options) {
974 return tslib.__awaiter(this, void 0, void 0, function () {
975 var measurementId, params;
976 return tslib.__generator(this, function (_a) {
977 switch (_a.label) {
978 case 0:
979 if (!(options && options.global)) return [3 /*break*/, 1];
980 gtagFunction("event" /* EVENT */, eventName, eventParams);
981 return [2 /*return*/];
982 case 1: return [4 /*yield*/, initializationPromise];
983 case 2:
984 measurementId = _a.sent();
985 params = tslib.__assign(tslib.__assign({}, eventParams), { 'send_to': measurementId });
986 gtagFunction("event" /* EVENT */, eventName, params);
987 _a.label = 3;
988 case 3: return [2 /*return*/];
989 }
990 });
991 });
992}
993/**
994 * Set screen_name parameter for this Google Analytics ID.
995 *
996 * @deprecated Use {@link logEvent} with `eventName` as 'screen_view' and add relevant `eventParams`.
997 * See {@link https://firebase.google.com/docs/analytics/screenviews | Track Screenviews}.
998 *
999 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
1000 * @param screenName Screen name string to set.
1001 */
1002function setCurrentScreen$1(gtagFunction, initializationPromise, screenName, options) {
1003 return tslib.__awaiter(this, void 0, void 0, function () {
1004 var measurementId;
1005 return tslib.__generator(this, function (_a) {
1006 switch (_a.label) {
1007 case 0:
1008 if (!(options && options.global)) return [3 /*break*/, 1];
1009 gtagFunction("set" /* SET */, { 'screen_name': screenName });
1010 return [2 /*return*/, Promise.resolve()];
1011 case 1: return [4 /*yield*/, initializationPromise];
1012 case 2:
1013 measurementId = _a.sent();
1014 gtagFunction("config" /* CONFIG */, measurementId, {
1015 update: true,
1016 'screen_name': screenName
1017 });
1018 _a.label = 3;
1019 case 3: return [2 /*return*/];
1020 }
1021 });
1022 });
1023}
1024/**
1025 * Set user_id parameter for this Google Analytics ID.
1026 *
1027 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
1028 * @param id User ID string to set
1029 */
1030function setUserId$1(gtagFunction, initializationPromise, id, options) {
1031 return tslib.__awaiter(this, void 0, void 0, function () {
1032 var measurementId;
1033 return tslib.__generator(this, function (_a) {
1034 switch (_a.label) {
1035 case 0:
1036 if (!(options && options.global)) return [3 /*break*/, 1];
1037 gtagFunction("set" /* SET */, { 'user_id': id });
1038 return [2 /*return*/, Promise.resolve()];
1039 case 1: return [4 /*yield*/, initializationPromise];
1040 case 2:
1041 measurementId = _a.sent();
1042 gtagFunction("config" /* CONFIG */, measurementId, {
1043 update: true,
1044 'user_id': id
1045 });
1046 _a.label = 3;
1047 case 3: return [2 /*return*/];
1048 }
1049 });
1050 });
1051}
1052/**
1053 * Set all other user properties other than user_id and screen_name.
1054 *
1055 * @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
1056 * @param properties Map of user properties to set
1057 */
1058function setUserProperties$1(gtagFunction, initializationPromise, properties, options) {
1059 return tslib.__awaiter(this, void 0, void 0, function () {
1060 var flatProperties, _i, _a, key, measurementId;
1061 return tslib.__generator(this, function (_b) {
1062 switch (_b.label) {
1063 case 0:
1064 if (!(options && options.global)) return [3 /*break*/, 1];
1065 flatProperties = {};
1066 for (_i = 0, _a = Object.keys(properties); _i < _a.length; _i++) {
1067 key = _a[_i];
1068 // use dot notation for merge behavior in gtag.js
1069 flatProperties["user_properties." + key] = properties[key];
1070 }
1071 gtagFunction("set" /* SET */, flatProperties);
1072 return [2 /*return*/, Promise.resolve()];
1073 case 1: return [4 /*yield*/, initializationPromise];
1074 case 2:
1075 measurementId = _b.sent();
1076 gtagFunction("config" /* CONFIG */, measurementId, {
1077 update: true,
1078 'user_properties': properties
1079 });
1080 _b.label = 3;
1081 case 3: return [2 /*return*/];
1082 }
1083 });
1084 });
1085}
1086/**
1087 * Set whether collection is enabled for this ID.
1088 *
1089 * @param enabled If true, collection is enabled for this ID.
1090 */
1091function setAnalyticsCollectionEnabled$1(initializationPromise, enabled) {
1092 return tslib.__awaiter(this, void 0, void 0, function () {
1093 var measurementId;
1094 return tslib.__generator(this, function (_a) {
1095 switch (_a.label) {
1096 case 0: return [4 /*yield*/, initializationPromise];
1097 case 1:
1098 measurementId = _a.sent();
1099 window["ga-disable-" + measurementId] = !enabled;
1100 return [2 /*return*/];
1101 }
1102 });
1103 });
1104}
1105
1106/* eslint-disable @typescript-eslint/no-explicit-any */
1107/**
1108 * Returns an {@link Analytics} instance for the given app.
1109 *
1110 * @public
1111 *
1112 * @param app - The {@link @firebase/app#FirebaseApp} to use.
1113 */
1114function getAnalytics(app$1) {
1115 if (app$1 === void 0) { app$1 = app.getApp(); }
1116 app$1 = util.getModularInstance(app$1);
1117 // Dependencies
1118 var analyticsProvider = app._getProvider(app$1, ANALYTICS_TYPE);
1119 if (analyticsProvider.isInitialized()) {
1120 return analyticsProvider.getImmediate();
1121 }
1122 return initializeAnalytics(app$1);
1123}
1124/**
1125 * Returns an {@link Analytics} instance for the given app.
1126 *
1127 * @public
1128 *
1129 * @param app - The {@link @firebase/app#FirebaseApp} to use.
1130 */
1131function initializeAnalytics(app$1, options) {
1132 if (options === void 0) { options = {}; }
1133 // Dependencies
1134 var analyticsProvider = app._getProvider(app$1, ANALYTICS_TYPE);
1135 if (analyticsProvider.isInitialized()) {
1136 var existingInstance = analyticsProvider.getImmediate();
1137 if (util.deepEqual(options, analyticsProvider.getOptions())) {
1138 return existingInstance;
1139 }
1140 else {
1141 throw ERROR_FACTORY.create("already-initialized" /* ALREADY_INITIALIZED */);
1142 }
1143 }
1144 var analyticsInstance = analyticsProvider.initialize({ options: options });
1145 return analyticsInstance;
1146}
1147/**
1148 * This is a public static method provided to users that wraps four different checks:
1149 *
1150 * 1. Check if it's not a browser extension environment.
1151 * 2. Check if cookies are enabled in current browser.
1152 * 3. Check if IndexedDB is supported by the browser environment.
1153 * 4. Check if the current browser context is valid for using `IndexedDB.open()`.
1154 *
1155 * @public
1156 *
1157 */
1158function isSupported() {
1159 return tslib.__awaiter(this, void 0, void 0, function () {
1160 var isDBOpenable;
1161 return tslib.__generator(this, function (_a) {
1162 switch (_a.label) {
1163 case 0:
1164 if (util.isBrowserExtension()) {
1165 return [2 /*return*/, false];
1166 }
1167 if (!util.areCookiesEnabled()) {
1168 return [2 /*return*/, false];
1169 }
1170 if (!util.isIndexedDBAvailable()) {
1171 return [2 /*return*/, false];
1172 }
1173 _a.label = 1;
1174 case 1:
1175 _a.trys.push([1, 3, , 4]);
1176 return [4 /*yield*/, util.validateIndexedDBOpenable()];
1177 case 2:
1178 isDBOpenable = _a.sent();
1179 return [2 /*return*/, isDBOpenable];
1180 case 3:
1181 _a.sent();
1182 return [2 /*return*/, false];
1183 case 4: return [2 /*return*/];
1184 }
1185 });
1186 });
1187}
1188/**
1189 * Use gtag `config` command to set `screen_name`.
1190 *
1191 * @public
1192 *
1193 * @deprecated Use {@link logEvent} with `eventName` as 'screen_view' and add relevant `eventParams`.
1194 * See {@link https://firebase.google.com/docs/analytics/screenviews | Track Screenviews}.
1195 *
1196 * @param analyticsInstance - The {@link Analytics} instance.
1197 * @param screenName - Screen name to set.
1198 */
1199function setCurrentScreen(analyticsInstance, screenName, options) {
1200 analyticsInstance = util.getModularInstance(analyticsInstance);
1201 setCurrentScreen$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], screenName, options).catch(function (e) { return logger.error(e); });
1202}
1203/**
1204 * Use gtag `config` command to set `user_id`.
1205 *
1206 * @public
1207 *
1208 * @param analyticsInstance - The {@link Analytics} instance.
1209 * @param id - User ID to set.
1210 */
1211function setUserId(analyticsInstance, id, options) {
1212 analyticsInstance = util.getModularInstance(analyticsInstance);
1213 setUserId$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], id, options).catch(function (e) { return logger.error(e); });
1214}
1215/**
1216 * Use gtag `config` command to set all params specified.
1217 *
1218 * @public
1219 */
1220function setUserProperties(analyticsInstance, properties, options) {
1221 analyticsInstance = util.getModularInstance(analyticsInstance);
1222 setUserProperties$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], properties, options).catch(function (e) { return logger.error(e); });
1223}
1224/**
1225 * Sets whether Google Analytics collection is enabled for this app on this device.
1226 * Sets global `window['ga-disable-analyticsId'] = true;`
1227 *
1228 * @public
1229 *
1230 * @param analyticsInstance - The {@link Analytics} instance.
1231 * @param enabled - If true, enables collection, if false, disables it.
1232 */
1233function setAnalyticsCollectionEnabled(analyticsInstance, enabled) {
1234 analyticsInstance = util.getModularInstance(analyticsInstance);
1235 setAnalyticsCollectionEnabled$1(initializationPromisesMap[analyticsInstance.app.options.appId], enabled).catch(function (e) { return logger.error(e); });
1236}
1237/**
1238 * Sends a Google Analytics event with given `eventParams`. This method
1239 * automatically associates this logged event with this Firebase web
1240 * app instance on this device.
1241 * List of official event parameters can be found in the gtag.js
1242 * reference documentation:
1243 * {@link https://developers.google.com/gtagjs/reference/ga4-events
1244 * | the GA4 reference documentation}.
1245 *
1246 * @public
1247 */
1248function logEvent(analyticsInstance, eventName, eventParams, options) {
1249 analyticsInstance = util.getModularInstance(analyticsInstance);
1250 logEvent$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], eventName, eventParams, options).catch(function (e) { return logger.error(e); });
1251}
1252
1253var name = "@firebase/analytics";
1254var version = "0.7.11";
1255
1256/**
1257 * Firebase Analytics
1258 *
1259 * @packageDocumentation
1260 */
1261function registerAnalytics() {
1262 app._registerComponent(new component.Component(ANALYTICS_TYPE, function (container, _a) {
1263 var analyticsOptions = _a.options;
1264 // getImmediate for FirebaseApp will always succeed
1265 var app = container.getProvider('app').getImmediate();
1266 var installations = container
1267 .getProvider('installations-internal')
1268 .getImmediate();
1269 return factory(app, installations, analyticsOptions);
1270 }, "PUBLIC" /* PUBLIC */));
1271 app._registerComponent(new component.Component('analytics-internal', internalFactory, "PRIVATE" /* PRIVATE */));
1272 app.registerVersion(name, version);
1273 // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
1274 app.registerVersion(name, version, 'cjs5');
1275 function internalFactory(container) {
1276 try {
1277 var analytics_1 = container.getProvider(ANALYTICS_TYPE).getImmediate();
1278 return {
1279 logEvent: function (eventName, eventParams, options) { return logEvent(analytics_1, eventName, eventParams, options); }
1280 };
1281 }
1282 catch (e) {
1283 throw ERROR_FACTORY.create("interop-component-reg-failed" /* INTEROP_COMPONENT_REG_FAILED */, {
1284 reason: e
1285 });
1286 }
1287 }
1288}
1289registerAnalytics();
1290
1291exports.getAnalytics = getAnalytics;
1292exports.initializeAnalytics = initializeAnalytics;
1293exports.isSupported = isSupported;
1294exports.logEvent = logEvent;
1295exports.setAnalyticsCollectionEnabled = setAnalyticsCollectionEnabled;
1296exports.setCurrentScreen = setCurrentScreen;
1297exports.setUserId = setUserId;
1298exports.setUserProperties = setUserProperties;
1299exports.settings = settings;
1300//# sourceMappingURL=index.cjs.js.map