@firebase/analytics 0.10.8 → 0.10.9-canary.a97ac88db
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.esm2017.js +2 -2
- package/dist/esm/index.esm2017.js.map +1 -1
- package/dist/index.cjs.js +461 -649
- package/dist/index.cjs.js.map +1 -1
- package/package.json +7 -9
- package/dist/esm/index.esm.js +0 -1459
- package/dist/esm/index.esm.js.map +0 -1
package/dist/index.cjs.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var app = require('@firebase/app');
|
|
6
|
-
var tslib = require('tslib');
|
|
7
6
|
var logger$1 = require('@firebase/logger');
|
|
8
7
|
var util = require('@firebase/util');
|
|
9
8
|
var component = require('@firebase/component');
|
|
@@ -28,13 +27,13 @@ require('@firebase/installations');
|
|
|
28
27
|
/**
|
|
29
28
|
* Type constant for Firebase Analytics.
|
|
30
29
|
*/
|
|
31
|
-
|
|
30
|
+
const ANALYTICS_TYPE = 'analytics';
|
|
32
31
|
// Key to attach FID to in gtag params.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
const GA_FID_KEY = 'firebase_id';
|
|
33
|
+
const ORIGIN_KEY = 'origin';
|
|
34
|
+
const FETCH_TIMEOUT_MILLIS = 60 * 1000;
|
|
35
|
+
const DYNAMIC_CONFIG_URL = 'https://firebase.googleapis.com/v1alpha/projects/-/apps/{app-id}/webConfig';
|
|
36
|
+
const GTAG_URL = 'https://www.googletagmanager.com/gtag/js';
|
|
38
37
|
|
|
39
38
|
/**
|
|
40
39
|
* @license
|
|
@@ -52,7 +51,7 @@ var GTAG_URL = 'https://www.googletagmanager.com/gtag/js';
|
|
|
52
51
|
* See the License for the specific language governing permissions and
|
|
53
52
|
* limitations under the License.
|
|
54
53
|
*/
|
|
55
|
-
|
|
54
|
+
const logger = new logger$1.Logger('@firebase/analytics');
|
|
56
55
|
|
|
57
56
|
/**
|
|
58
57
|
* @license
|
|
@@ -70,36 +69,35 @@ var logger = new logger$1.Logger('@firebase/analytics');
|
|
|
70
69
|
* See the License for the specific language governing permissions and
|
|
71
70
|
* limitations under the License.
|
|
72
71
|
*/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
_a["already-exists" /* AnalyticsError.ALREADY_EXISTS */] = 'A Firebase Analytics instance with the appId {$id} ' +
|
|
72
|
+
const ERRORS = {
|
|
73
|
+
["already-exists" /* AnalyticsError.ALREADY_EXISTS */]: 'A Firebase Analytics instance with the appId {$id} ' +
|
|
76
74
|
' already exists. ' +
|
|
77
75
|
'Only one Firebase Analytics instance can be created for each appId.',
|
|
78
|
-
|
|
76
|
+
["already-initialized" /* AnalyticsError.ALREADY_INITIALIZED */]: 'initializeAnalytics() cannot be called again with different options than those ' +
|
|
79
77
|
'it was initially called with. It can be called again with the same options to ' +
|
|
80
78
|
'return the existing instance, or getAnalytics() can be used ' +
|
|
81
79
|
'to get a reference to the already-initialized instance.',
|
|
82
|
-
|
|
80
|
+
["already-initialized-settings" /* AnalyticsError.ALREADY_INITIALIZED_SETTINGS */]: 'Firebase Analytics has already been initialized.' +
|
|
83
81
|
'settings() must be called before initializing any Analytics instance' +
|
|
84
82
|
'or it will have no effect.',
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
["interop-component-reg-failed" /* AnalyticsError.INTEROP_COMPONENT_REG_FAILED */]: 'Firebase Analytics Interop Component failed to instantiate: {$reason}',
|
|
84
|
+
["invalid-analytics-context" /* AnalyticsError.INVALID_ANALYTICS_CONTEXT */]: 'Firebase Analytics is not supported in this environment. ' +
|
|
87
85
|
'Wrap initialization of analytics in analytics.isSupported() ' +
|
|
88
86
|
'to prevent initialization in unsupported environments. Details: {$errorInfo}',
|
|
89
|
-
|
|
87
|
+
["indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */]: 'IndexedDB unavailable or restricted in this environment. ' +
|
|
90
88
|
'Wrap initialization of analytics in analytics.isSupported() ' +
|
|
91
89
|
'to prevent initialization in unsupported environments. Details: {$errorInfo}',
|
|
92
|
-
|
|
90
|
+
["fetch-throttle" /* AnalyticsError.FETCH_THROTTLE */]: 'The config fetch request timed out while in an exponential backoff state.' +
|
|
93
91
|
' Unix timestamp in milliseconds when fetch request throttling ends: {$throttleEndTimeMillis}.',
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
["config-fetch-failed" /* AnalyticsError.CONFIG_FETCH_FAILED */]: 'Dynamic config fetch failed: [{$httpStatus}] {$responseMessage}',
|
|
93
|
+
["no-api-key" /* AnalyticsError.NO_API_KEY */]: 'The "apiKey" field is empty in the local Firebase config. Firebase Analytics requires this field to' +
|
|
96
94
|
'contain a valid API key.',
|
|
97
|
-
|
|
95
|
+
["no-app-id" /* AnalyticsError.NO_APP_ID */]: 'The "appId" field is empty in the local Firebase config. Firebase Analytics requires this field to' +
|
|
98
96
|
'contain a valid app ID.',
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
["no-client-id" /* AnalyticsError.NO_CLIENT_ID */]: 'The "client_id" field is empty.',
|
|
98
|
+
["invalid-gtag-resource" /* AnalyticsError.INVALID_GTAG_RESOURCE */]: 'Trusted Types detected an invalid gtag resource: {$gtagURL}.'
|
|
99
|
+
};
|
|
100
|
+
const ERROR_FACTORY = new util.ErrorFactory('analytics', 'Analytics', ERRORS);
|
|
103
101
|
|
|
104
102
|
/**
|
|
105
103
|
* @license
|
|
@@ -122,7 +120,7 @@ var ERROR_FACTORY = new util.ErrorFactory('analytics', 'Analytics', ERRORS);
|
|
|
122
120
|
*/
|
|
123
121
|
function createGtagTrustedTypesScriptURL(url) {
|
|
124
122
|
if (!url.startsWith(GTAG_URL)) {
|
|
125
|
-
|
|
123
|
+
const err = ERROR_FACTORY.create("invalid-gtag-resource" /* AnalyticsError.INVALID_GTAG_RESOURCE */, {
|
|
126
124
|
gtagURL: url
|
|
127
125
|
});
|
|
128
126
|
logger.warn(err.message);
|
|
@@ -137,7 +135,7 @@ function createGtagTrustedTypesScriptURL(url) {
|
|
|
137
135
|
* @param promises Array of promises to wait for.
|
|
138
136
|
*/
|
|
139
137
|
function promiseAllSettled(promises) {
|
|
140
|
-
return Promise.all(promises.map(
|
|
138
|
+
return Promise.all(promises.map(promise => promise.catch(e => e)));
|
|
141
139
|
}
|
|
142
140
|
/**
|
|
143
141
|
* Creates a TrustedTypePolicy object that implements the rules passed as policyOptions.
|
|
@@ -149,7 +147,7 @@ function promiseAllSettled(promises) {
|
|
|
149
147
|
function createTrustedTypesPolicy(policyName, policyOptions) {
|
|
150
148
|
// Create a TrustedTypes policy that we can use for updating src
|
|
151
149
|
// properties
|
|
152
|
-
|
|
150
|
+
let trustedTypesPolicy;
|
|
153
151
|
if (window.trustedTypes) {
|
|
154
152
|
trustedTypesPolicy = window.trustedTypes.createPolicy(policyName, policyOptions);
|
|
155
153
|
}
|
|
@@ -160,13 +158,13 @@ function createTrustedTypesPolicy(policyName, policyOptions) {
|
|
|
160
158
|
* @param dataLayerName Name of datalayer (most often the default, "_dataLayer").
|
|
161
159
|
*/
|
|
162
160
|
function insertScriptTag(dataLayerName, measurementId) {
|
|
163
|
-
|
|
161
|
+
const trustedTypesPolicy = createTrustedTypesPolicy('firebase-js-sdk-policy', {
|
|
164
162
|
createScriptURL: createGtagTrustedTypesScriptURL
|
|
165
163
|
});
|
|
166
|
-
|
|
164
|
+
const script = document.createElement('script');
|
|
167
165
|
// We are not providing an analyticsId in the URL because it would trigger a `page_view`
|
|
168
166
|
// without fid. We will initialize ga-id using gtag (config) command together with fid.
|
|
169
|
-
|
|
167
|
+
const gtagScriptURL = `${GTAG_URL}?l=${dataLayerName}&id=${measurementId}`;
|
|
170
168
|
script.src = trustedTypesPolicy
|
|
171
169
|
? trustedTypesPolicy === null || trustedTypesPolicy === void 0 ? void 0 : trustedTypesPolicy.createScriptURL(gtagScriptURL)
|
|
172
170
|
: gtagScriptURL;
|
|
@@ -179,7 +177,7 @@ function insertScriptTag(dataLayerName, measurementId) {
|
|
|
179
177
|
*/
|
|
180
178
|
function getOrCreateDataLayer(dataLayerName) {
|
|
181
179
|
// Check for existing dataLayer and create if needed.
|
|
182
|
-
|
|
180
|
+
let dataLayer = [];
|
|
183
181
|
if (Array.isArray(window[dataLayerName])) {
|
|
184
182
|
dataLayer = window[dataLayerName];
|
|
185
183
|
}
|
|
@@ -198,41 +196,30 @@ function getOrCreateDataLayer(dataLayerName) {
|
|
|
198
196
|
* @param measurementId GA Measurement ID to set config for.
|
|
199
197
|
* @param gtagParams Gtag config params to set.
|
|
200
198
|
*/
|
|
201
|
-
function gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
dynamicConfigResults = _a.sent();
|
|
219
|
-
foundConfig = dynamicConfigResults.find(function (config) { return config.measurementId === measurementId; });
|
|
220
|
-
if (!foundConfig) return [3 /*break*/, 6];
|
|
221
|
-
return [4 /*yield*/, initializationPromisesMap[foundConfig.appId]];
|
|
222
|
-
case 5:
|
|
223
|
-
_a.sent();
|
|
224
|
-
_a.label = 6;
|
|
225
|
-
case 6: return [3 /*break*/, 8];
|
|
226
|
-
case 7:
|
|
227
|
-
e_1 = _a.sent();
|
|
228
|
-
logger.error(e_1);
|
|
229
|
-
return [3 /*break*/, 8];
|
|
230
|
-
case 8:
|
|
231
|
-
gtagCore("config" /* GtagCommand.CONFIG */, measurementId, gtagParams);
|
|
232
|
-
return [2 /*return*/];
|
|
199
|
+
async function gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams) {
|
|
200
|
+
// If config is already fetched, we know the appId and can use it to look up what FID promise we
|
|
201
|
+
/// are waiting for, and wait only on that one.
|
|
202
|
+
const correspondingAppId = measurementIdToAppId[measurementId];
|
|
203
|
+
try {
|
|
204
|
+
if (correspondingAppId) {
|
|
205
|
+
await initializationPromisesMap[correspondingAppId];
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
// If config is not fetched yet, wait for all configs (we don't know which one we need) and
|
|
209
|
+
// find the appId (if any) corresponding to this measurementId. If there is one, wait on
|
|
210
|
+
// that appId's initialization promise. If there is none, promise resolves and gtag
|
|
211
|
+
// call goes through.
|
|
212
|
+
const dynamicConfigResults = await promiseAllSettled(dynamicConfigPromisesList);
|
|
213
|
+
const foundConfig = dynamicConfigResults.find(config => config.measurementId === measurementId);
|
|
214
|
+
if (foundConfig) {
|
|
215
|
+
await initializationPromisesMap[foundConfig.appId];
|
|
233
216
|
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
logger.error(e);
|
|
221
|
+
}
|
|
222
|
+
gtagCore("config" /* GtagCommand.CONFIG */, measurementId, gtagParams);
|
|
236
223
|
}
|
|
237
224
|
/**
|
|
238
225
|
* Wrapped gtag logic when gtag is called with 'event' command.
|
|
@@ -243,71 +230,52 @@ function gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromises
|
|
|
243
230
|
* @param measurementId GA Measurement ID to log event to.
|
|
244
231
|
* @param gtagParams Params to log with this event.
|
|
245
232
|
*/
|
|
246
|
-
function gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
233
|
+
async function gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams) {
|
|
234
|
+
try {
|
|
235
|
+
let initializationPromisesToWaitFor = [];
|
|
236
|
+
// If there's a 'send_to' param, check if any ID specified matches
|
|
237
|
+
// an initializeIds() promise we are waiting for.
|
|
238
|
+
if (gtagParams && gtagParams['send_to']) {
|
|
239
|
+
let gaSendToList = gtagParams['send_to'];
|
|
240
|
+
// Make it an array if is isn't, so it can be dealt with the same way.
|
|
241
|
+
if (!Array.isArray(gaSendToList)) {
|
|
242
|
+
gaSendToList = [gaSendToList];
|
|
243
|
+
}
|
|
244
|
+
// Checking 'send_to' fields requires having all measurement ID results back from
|
|
245
|
+
// the dynamic config fetch.
|
|
246
|
+
const dynamicConfigResults = await promiseAllSettled(dynamicConfigPromisesList);
|
|
247
|
+
for (const sendToId of gaSendToList) {
|
|
248
|
+
// Any fetched dynamic measurement ID that matches this 'send_to' ID
|
|
249
|
+
const foundConfig = dynamicConfigResults.find(config => config.measurementId === sendToId);
|
|
250
|
+
const initializationPromise = foundConfig && initializationPromisesMap[foundConfig.appId];
|
|
251
|
+
if (initializationPromise) {
|
|
252
|
+
initializationPromisesToWaitFor.push(initializationPromise);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// Found an item in 'send_to' that is not associated
|
|
256
|
+
// directly with an FID, possibly a group. Empty this array,
|
|
257
|
+
// exit the loop early, and let it get populated below.
|
|
253
258
|
initializationPromisesToWaitFor = [];
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
// Make it an array if is isn't, so it can be dealt with the same way.
|
|
257
|
-
if (!Array.isArray(gaSendToList)) {
|
|
258
|
-
gaSendToList = [gaSendToList];
|
|
259
|
-
}
|
|
260
|
-
return [4 /*yield*/, promiseAllSettled(dynamicConfigPromisesList)];
|
|
261
|
-
case 1:
|
|
262
|
-
dynamicConfigResults = _a.sent();
|
|
263
|
-
_loop_1 = function (sendToId) {
|
|
264
|
-
// Any fetched dynamic measurement ID that matches this 'send_to' ID
|
|
265
|
-
var foundConfig = dynamicConfigResults.find(function (config) { return config.measurementId === sendToId; });
|
|
266
|
-
var initializationPromise = foundConfig && initializationPromisesMap[foundConfig.appId];
|
|
267
|
-
if (initializationPromise) {
|
|
268
|
-
initializationPromisesToWaitFor.push(initializationPromise);
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
// Found an item in 'send_to' that is not associated
|
|
272
|
-
// directly with an FID, possibly a group. Empty this array,
|
|
273
|
-
// exit the loop early, and let it get populated below.
|
|
274
|
-
initializationPromisesToWaitFor = [];
|
|
275
|
-
return "break";
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
for (_i = 0, gaSendToList_1 = gaSendToList; _i < gaSendToList_1.length; _i++) {
|
|
279
|
-
sendToId = gaSendToList_1[_i];
|
|
280
|
-
state_1 = _loop_1(sendToId);
|
|
281
|
-
if (state_1 === "break")
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
_a.label = 2;
|
|
285
|
-
case 2:
|
|
286
|
-
// This will be unpopulated if there was no 'send_to' field , or
|
|
287
|
-
// if not all entries in the 'send_to' field could be mapped to
|
|
288
|
-
// a FID. In these cases, wait on all pending initialization promises.
|
|
289
|
-
if (initializationPromisesToWaitFor.length === 0) {
|
|
290
|
-
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
|
291
|
-
initializationPromisesToWaitFor = Object.values(initializationPromisesMap);
|
|
292
|
-
}
|
|
293
|
-
// Run core gtag function with args after all relevant initialization
|
|
294
|
-
// promises have been resolved.
|
|
295
|
-
return [4 /*yield*/, Promise.all(initializationPromisesToWaitFor)];
|
|
296
|
-
case 3:
|
|
297
|
-
// Run core gtag function with args after all relevant initialization
|
|
298
|
-
// promises have been resolved.
|
|
299
|
-
_a.sent();
|
|
300
|
-
// Workaround for http://b/141370449 - third argument cannot be undefined.
|
|
301
|
-
gtagCore("event" /* GtagCommand.EVENT */, measurementId, gtagParams || {});
|
|
302
|
-
return [3 /*break*/, 5];
|
|
303
|
-
case 4:
|
|
304
|
-
e_2 = _a.sent();
|
|
305
|
-
logger.error(e_2);
|
|
306
|
-
return [3 /*break*/, 5];
|
|
307
|
-
case 5: return [2 /*return*/];
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
308
261
|
}
|
|
309
|
-
}
|
|
310
|
-
|
|
262
|
+
}
|
|
263
|
+
// This will be unpopulated if there was no 'send_to' field , or
|
|
264
|
+
// if not all entries in the 'send_to' field could be mapped to
|
|
265
|
+
// a FID. In these cases, wait on all pending initialization promises.
|
|
266
|
+
if (initializationPromisesToWaitFor.length === 0) {
|
|
267
|
+
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
|
268
|
+
initializationPromisesToWaitFor = Object.values(initializationPromisesMap);
|
|
269
|
+
}
|
|
270
|
+
// Run core gtag function with args after all relevant initialization
|
|
271
|
+
// promises have been resolved.
|
|
272
|
+
await Promise.all(initializationPromisesToWaitFor);
|
|
273
|
+
// Workaround for http://b/141370449 - third argument cannot be undefined.
|
|
274
|
+
gtagCore("event" /* GtagCommand.EVENT */, measurementId, gtagParams || {});
|
|
275
|
+
}
|
|
276
|
+
catch (e) {
|
|
277
|
+
logger.error(e);
|
|
278
|
+
}
|
|
311
279
|
}
|
|
312
280
|
/**
|
|
313
281
|
* Wraps a standard gtag function with extra code to wait for completion of
|
|
@@ -341,62 +309,40 @@ measurementIdToAppId) {
|
|
|
341
309
|
* @param idOrNameOrParams Measurement ID if command is EVENT/CONFIG, params if command is SET.
|
|
342
310
|
* @param gtagParams Params if event is EVENT/CONFIG.
|
|
343
311
|
*/
|
|
344
|
-
function gtagWrapper(command) {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
312
|
+
async function gtagWrapper(command, ...args) {
|
|
313
|
+
try {
|
|
314
|
+
// If event, check that relevant initialization promises have completed.
|
|
315
|
+
if (command === "event" /* GtagCommand.EVENT */) {
|
|
316
|
+
const [measurementId, gtagParams] = args;
|
|
317
|
+
// If EVENT, second arg must be measurementId.
|
|
318
|
+
await gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams);
|
|
319
|
+
}
|
|
320
|
+
else if (command === "config" /* GtagCommand.CONFIG */) {
|
|
321
|
+
const [measurementId, gtagParams] = args;
|
|
322
|
+
// If CONFIG, second arg must be measurementId.
|
|
323
|
+
await gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams);
|
|
324
|
+
}
|
|
325
|
+
else if (command === "consent" /* GtagCommand.CONSENT */) {
|
|
326
|
+
const [consentAction, gtagParams] = args;
|
|
327
|
+
// consentAction can be one of 'default' or 'update'.
|
|
328
|
+
gtagCore("consent" /* GtagCommand.CONSENT */, consentAction, gtagParams);
|
|
329
|
+
}
|
|
330
|
+
else if (command === "get" /* GtagCommand.GET */) {
|
|
331
|
+
const [measurementId, fieldName, callback] = args;
|
|
332
|
+
gtagCore("get" /* GtagCommand.GET */, measurementId, fieldName, callback);
|
|
333
|
+
}
|
|
334
|
+
else if (command === "set" /* GtagCommand.SET */) {
|
|
335
|
+
const [customParams] = args;
|
|
336
|
+
// If SET, second arg must be params.
|
|
337
|
+
gtagCore("set" /* GtagCommand.SET */, customParams);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
gtagCore(command, ...args);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
catch (e) {
|
|
344
|
+
logger.error(e);
|
|
348
345
|
}
|
|
349
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
350
|
-
var measurementId, gtagParams, measurementId, gtagParams, consentAction, gtagParams, measurementId, fieldName, callback, customParams, e_3;
|
|
351
|
-
return tslib.__generator(this, function (_a) {
|
|
352
|
-
switch (_a.label) {
|
|
353
|
-
case 0:
|
|
354
|
-
_a.trys.push([0, 6, , 7]);
|
|
355
|
-
if (!(command === "event" /* GtagCommand.EVENT */)) return [3 /*break*/, 2];
|
|
356
|
-
measurementId = args[0], gtagParams = args[1];
|
|
357
|
-
// If EVENT, second arg must be measurementId.
|
|
358
|
-
return [4 /*yield*/, gtagOnEvent(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementId, gtagParams)];
|
|
359
|
-
case 1:
|
|
360
|
-
// If EVENT, second arg must be measurementId.
|
|
361
|
-
_a.sent();
|
|
362
|
-
return [3 /*break*/, 5];
|
|
363
|
-
case 2:
|
|
364
|
-
if (!(command === "config" /* GtagCommand.CONFIG */)) return [3 /*break*/, 4];
|
|
365
|
-
measurementId = args[0], gtagParams = args[1];
|
|
366
|
-
// If CONFIG, second arg must be measurementId.
|
|
367
|
-
return [4 /*yield*/, gtagOnConfig(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, measurementId, gtagParams)];
|
|
368
|
-
case 3:
|
|
369
|
-
// If CONFIG, second arg must be measurementId.
|
|
370
|
-
_a.sent();
|
|
371
|
-
return [3 /*break*/, 5];
|
|
372
|
-
case 4:
|
|
373
|
-
if (command === "consent" /* GtagCommand.CONSENT */) {
|
|
374
|
-
consentAction = args[0], gtagParams = args[1];
|
|
375
|
-
// consentAction can be one of 'default' or 'update'.
|
|
376
|
-
gtagCore("consent" /* GtagCommand.CONSENT */, consentAction, gtagParams);
|
|
377
|
-
}
|
|
378
|
-
else if (command === "get" /* GtagCommand.GET */) {
|
|
379
|
-
measurementId = args[0], fieldName = args[1], callback = args[2];
|
|
380
|
-
gtagCore("get" /* GtagCommand.GET */, measurementId, fieldName, callback);
|
|
381
|
-
}
|
|
382
|
-
else if (command === "set" /* GtagCommand.SET */) {
|
|
383
|
-
customParams = args[0];
|
|
384
|
-
// If SET, second arg must be params.
|
|
385
|
-
gtagCore("set" /* GtagCommand.SET */, customParams);
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
gtagCore.apply(void 0, tslib.__spreadArray([command], args, false));
|
|
389
|
-
}
|
|
390
|
-
_a.label = 5;
|
|
391
|
-
case 5: return [3 /*break*/, 7];
|
|
392
|
-
case 6:
|
|
393
|
-
e_3 = _a.sent();
|
|
394
|
-
logger.error(e_3);
|
|
395
|
-
return [3 /*break*/, 7];
|
|
396
|
-
case 7: return [2 /*return*/];
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
});
|
|
400
346
|
}
|
|
401
347
|
return gtagWrapper;
|
|
402
348
|
}
|
|
@@ -413,7 +359,7 @@ measurementIdToAppId) {
|
|
|
413
359
|
*/
|
|
414
360
|
function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagFunctionName) {
|
|
415
361
|
// Create a basic core gtag function
|
|
416
|
-
|
|
362
|
+
let gtagCore = function (..._args) {
|
|
417
363
|
// Must push IArguments object, not an array.
|
|
418
364
|
window[dataLayerName].push(arguments);
|
|
419
365
|
};
|
|
@@ -425,7 +371,7 @@ function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList,
|
|
|
425
371
|
}
|
|
426
372
|
window[gtagFunctionName] = wrapGtag(gtagCore, initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId);
|
|
427
373
|
return {
|
|
428
|
-
gtagCore
|
|
374
|
+
gtagCore,
|
|
429
375
|
wrappedGtag: window[gtagFunctionName]
|
|
430
376
|
};
|
|
431
377
|
}
|
|
@@ -434,9 +380,8 @@ function wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList,
|
|
|
434
380
|
* and the provided data layer name.
|
|
435
381
|
*/
|
|
436
382
|
function findGtagScriptOnPage(dataLayerName) {
|
|
437
|
-
|
|
438
|
-
for (
|
|
439
|
-
var tag = _a[_i];
|
|
383
|
+
const scriptTags = window.document.getElementsByTagName('script');
|
|
384
|
+
for (const tag of Object.values(scriptTags)) {
|
|
440
385
|
if (tag.src &&
|
|
441
386
|
tag.src.includes(GTAG_URL) &&
|
|
442
387
|
tag.src.includes(dataLayerName)) {
|
|
@@ -468,33 +413,30 @@ function findGtagScriptOnPage(dataLayerName) {
|
|
|
468
413
|
* BASE_INTERVAL_MILLIS * LONG_RETRY_FACTOR ^ retryCount, so the second one
|
|
469
414
|
* will be ~30 seconds (with fuzzing).
|
|
470
415
|
*/
|
|
471
|
-
|
|
416
|
+
const LONG_RETRY_FACTOR = 30;
|
|
472
417
|
/**
|
|
473
418
|
* Base wait interval to multiplied by backoffFactor^backoffCount.
|
|
474
419
|
*/
|
|
475
|
-
|
|
420
|
+
const BASE_INTERVAL_MILLIS = 1000;
|
|
476
421
|
/**
|
|
477
422
|
* Stubbable retry data storage class.
|
|
478
423
|
*/
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (throttleMetadata === void 0) { throttleMetadata = {}; }
|
|
482
|
-
if (intervalMillis === void 0) { intervalMillis = BASE_INTERVAL_MILLIS; }
|
|
424
|
+
class RetryData {
|
|
425
|
+
constructor(throttleMetadata = {}, intervalMillis = BASE_INTERVAL_MILLIS) {
|
|
483
426
|
this.throttleMetadata = throttleMetadata;
|
|
484
427
|
this.intervalMillis = intervalMillis;
|
|
485
428
|
}
|
|
486
|
-
|
|
429
|
+
getThrottleMetadata(appId) {
|
|
487
430
|
return this.throttleMetadata[appId];
|
|
488
|
-
}
|
|
489
|
-
|
|
431
|
+
}
|
|
432
|
+
setThrottleMetadata(appId, metadata) {
|
|
490
433
|
this.throttleMetadata[appId] = metadata;
|
|
491
|
-
}
|
|
492
|
-
|
|
434
|
+
}
|
|
435
|
+
deleteThrottleMetadata(appId) {
|
|
493
436
|
delete this.throttleMetadata[appId];
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
var defaultRetryData = new RetryData();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
const defaultRetryData = new RetryData();
|
|
498
440
|
/**
|
|
499
441
|
* Set GET request headers.
|
|
500
442
|
* @param apiKey App API key.
|
|
@@ -509,86 +451,62 @@ function getHeaders(apiKey) {
|
|
|
509
451
|
* Fetches dynamic config from backend.
|
|
510
452
|
* @param app Firebase app to fetch config for.
|
|
511
453
|
*/
|
|
512
|
-
function fetchDynamicConfig(appFields) {
|
|
454
|
+
async function fetchDynamicConfig(appFields) {
|
|
513
455
|
var _a;
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (!(response.status !== 200 && response.status !== 304)) return [3 /*break*/, 6];
|
|
529
|
-
errorMessage = '';
|
|
530
|
-
_b.label = 2;
|
|
531
|
-
case 2:
|
|
532
|
-
_b.trys.push([2, 4, , 5]);
|
|
533
|
-
return [4 /*yield*/, response.json()];
|
|
534
|
-
case 3:
|
|
535
|
-
jsonResponse = (_b.sent());
|
|
536
|
-
if ((_a = jsonResponse.error) === null || _a === void 0 ? void 0 : _a.message) {
|
|
537
|
-
errorMessage = jsonResponse.error.message;
|
|
538
|
-
}
|
|
539
|
-
return [3 /*break*/, 5];
|
|
540
|
-
case 4:
|
|
541
|
-
_b.sent();
|
|
542
|
-
return [3 /*break*/, 5];
|
|
543
|
-
case 5: throw ERROR_FACTORY.create("config-fetch-failed" /* AnalyticsError.CONFIG_FETCH_FAILED */, {
|
|
544
|
-
httpStatus: response.status,
|
|
545
|
-
responseMessage: errorMessage
|
|
546
|
-
});
|
|
547
|
-
case 6: return [2 /*return*/, response.json()];
|
|
456
|
+
const { appId, apiKey } = appFields;
|
|
457
|
+
const request = {
|
|
458
|
+
method: 'GET',
|
|
459
|
+
headers: getHeaders(apiKey)
|
|
460
|
+
};
|
|
461
|
+
const appUrl = DYNAMIC_CONFIG_URL.replace('{app-id}', appId);
|
|
462
|
+
const response = await fetch(appUrl, request);
|
|
463
|
+
if (response.status !== 200 && response.status !== 304) {
|
|
464
|
+
let errorMessage = '';
|
|
465
|
+
try {
|
|
466
|
+
// Try to get any error message text from server response.
|
|
467
|
+
const jsonResponse = (await response.json());
|
|
468
|
+
if ((_a = jsonResponse.error) === null || _a === void 0 ? void 0 : _a.message) {
|
|
469
|
+
errorMessage = jsonResponse.error.message;
|
|
548
470
|
}
|
|
471
|
+
}
|
|
472
|
+
catch (_ignored) { }
|
|
473
|
+
throw ERROR_FACTORY.create("config-fetch-failed" /* AnalyticsError.CONFIG_FETCH_FAILED */, {
|
|
474
|
+
httpStatus: response.status,
|
|
475
|
+
responseMessage: errorMessage
|
|
549
476
|
});
|
|
550
|
-
}
|
|
477
|
+
}
|
|
478
|
+
return response.json();
|
|
551
479
|
}
|
|
552
480
|
/**
|
|
553
481
|
* Fetches dynamic config from backend, retrying if failed.
|
|
554
482
|
* @param app Firebase app to fetch config for.
|
|
555
483
|
*/
|
|
556
|
-
function fetchDynamicConfigWithRetry(app,
|
|
484
|
+
async function fetchDynamicConfigWithRetry(app,
|
|
557
485
|
// retryData and timeoutMillis are parameterized to allow passing a different value for testing.
|
|
558
|
-
retryData, timeoutMillis) {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
if (!apiKey) {
|
|
569
|
-
if (measurementId) {
|
|
570
|
-
return [2 /*return*/, {
|
|
571
|
-
measurementId: measurementId,
|
|
572
|
-
appId: appId
|
|
573
|
-
}];
|
|
574
|
-
}
|
|
575
|
-
throw ERROR_FACTORY.create("no-api-key" /* AnalyticsError.NO_API_KEY */);
|
|
576
|
-
}
|
|
577
|
-
throttleMetadata = retryData.getThrottleMetadata(appId) || {
|
|
578
|
-
backoffCount: 0,
|
|
579
|
-
throttleEndTimeMillis: Date.now()
|
|
486
|
+
retryData = defaultRetryData, timeoutMillis) {
|
|
487
|
+
const { appId, apiKey, measurementId } = app.options;
|
|
488
|
+
if (!appId) {
|
|
489
|
+
throw ERROR_FACTORY.create("no-app-id" /* AnalyticsError.NO_APP_ID */);
|
|
490
|
+
}
|
|
491
|
+
if (!apiKey) {
|
|
492
|
+
if (measurementId) {
|
|
493
|
+
return {
|
|
494
|
+
measurementId,
|
|
495
|
+
appId
|
|
580
496
|
};
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
497
|
+
}
|
|
498
|
+
throw ERROR_FACTORY.create("no-api-key" /* AnalyticsError.NO_API_KEY */);
|
|
499
|
+
}
|
|
500
|
+
const throttleMetadata = retryData.getThrottleMetadata(appId) || {
|
|
501
|
+
backoffCount: 0,
|
|
502
|
+
throttleEndTimeMillis: Date.now()
|
|
503
|
+
};
|
|
504
|
+
const signal = new AnalyticsAbortSignal();
|
|
505
|
+
setTimeout(async () => {
|
|
506
|
+
// Note a very low delay, eg < 10ms, can elapse before listeners are initialized.
|
|
507
|
+
signal.abort();
|
|
508
|
+
}, timeoutMillis !== undefined ? timeoutMillis : FETCH_TIMEOUT_MILLIS);
|
|
509
|
+
return attemptFetchDynamicConfigWithRetry({ appId, apiKey, measurementId }, throttleMetadata, signal, retryData);
|
|
592
510
|
}
|
|
593
511
|
/**
|
|
594
512
|
* Runs one retry attempt.
|
|
@@ -596,71 +514,58 @@ retryData, timeoutMillis) {
|
|
|
596
514
|
* @param throttleMetadata Ongoing metadata to determine throttling times.
|
|
597
515
|
* @param signal Abort signal.
|
|
598
516
|
*/
|
|
599
|
-
function attemptFetchDynamicConfigWithRetry(appFields,
|
|
517
|
+
async function attemptFetchDynamicConfigWithRetry(appFields, { throttleEndTimeMillis, backoffCount }, signal, retryData = defaultRetryData // for testing
|
|
600
518
|
) {
|
|
601
|
-
var
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
return [2 /*return*/, response];
|
|
634
|
-
case 6:
|
|
635
|
-
e_2 = _c.sent();
|
|
636
|
-
error = e_2;
|
|
637
|
-
if (!isRetriableError(error)) {
|
|
638
|
-
retryData.deleteThrottleMetadata(appId);
|
|
639
|
-
if (measurementId) {
|
|
640
|
-
logger.warn("Failed to fetch this Firebase app's measurement ID from the server." +
|
|
641
|
-
" Falling back to the measurement ID ".concat(measurementId) +
|
|
642
|
-
" provided in the \"measurementId\" field in the local Firebase config. [".concat(error === null || error === void 0 ? void 0 : error.message, "]"));
|
|
643
|
-
return [2 /*return*/, { appId: appId, measurementId: measurementId }];
|
|
644
|
-
}
|
|
645
|
-
else {
|
|
646
|
-
throw e_2;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
backoffMillis = Number((_b = error === null || error === void 0 ? void 0 : error.customData) === null || _b === void 0 ? void 0 : _b.httpStatus) === 503
|
|
650
|
-
? util.calculateBackoffMillis(backoffCount, retryData.intervalMillis, LONG_RETRY_FACTOR)
|
|
651
|
-
: util.calculateBackoffMillis(backoffCount, retryData.intervalMillis);
|
|
652
|
-
throttleMetadata = {
|
|
653
|
-
throttleEndTimeMillis: Date.now() + backoffMillis,
|
|
654
|
-
backoffCount: backoffCount + 1
|
|
655
|
-
};
|
|
656
|
-
// Persists state.
|
|
657
|
-
retryData.setThrottleMetadata(appId, throttleMetadata);
|
|
658
|
-
logger.debug("Calling attemptFetch again in ".concat(backoffMillis, " millis"));
|
|
659
|
-
return [2 /*return*/, attemptFetchDynamicConfigWithRetry(appFields, throttleMetadata, signal, retryData)];
|
|
660
|
-
case 7: return [2 /*return*/];
|
|
519
|
+
var _a;
|
|
520
|
+
const { appId, measurementId } = appFields;
|
|
521
|
+
// Starts with a (potentially zero) timeout to support resumption from stored state.
|
|
522
|
+
// Ensures the throttle end time is honored if the last attempt timed out.
|
|
523
|
+
// Note the SDK will never make a request if the fetch timeout expires at this point.
|
|
524
|
+
try {
|
|
525
|
+
await setAbortableTimeout(signal, throttleEndTimeMillis);
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
if (measurementId) {
|
|
529
|
+
logger.warn(`Timed out fetching this Firebase app's measurement ID from the server.` +
|
|
530
|
+
` Falling back to the measurement ID ${measurementId}` +
|
|
531
|
+
` provided in the "measurementId" field in the local Firebase config. [${e === null || e === void 0 ? void 0 : e.message}]`);
|
|
532
|
+
return { appId, measurementId };
|
|
533
|
+
}
|
|
534
|
+
throw e;
|
|
535
|
+
}
|
|
536
|
+
try {
|
|
537
|
+
const response = await fetchDynamicConfig(appFields);
|
|
538
|
+
// Note the SDK only clears throttle state if response is success or non-retriable.
|
|
539
|
+
retryData.deleteThrottleMetadata(appId);
|
|
540
|
+
return response;
|
|
541
|
+
}
|
|
542
|
+
catch (e) {
|
|
543
|
+
const error = e;
|
|
544
|
+
if (!isRetriableError(error)) {
|
|
545
|
+
retryData.deleteThrottleMetadata(appId);
|
|
546
|
+
if (measurementId) {
|
|
547
|
+
logger.warn(`Failed to fetch this Firebase app's measurement ID from the server.` +
|
|
548
|
+
` Falling back to the measurement ID ${measurementId}` +
|
|
549
|
+
` provided in the "measurementId" field in the local Firebase config. [${error === null || error === void 0 ? void 0 : error.message}]`);
|
|
550
|
+
return { appId, measurementId };
|
|
661
551
|
}
|
|
662
|
-
|
|
663
|
-
|
|
552
|
+
else {
|
|
553
|
+
throw e;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const backoffMillis = Number((_a = error === null || error === void 0 ? void 0 : error.customData) === null || _a === void 0 ? void 0 : _a.httpStatus) === 503
|
|
557
|
+
? util.calculateBackoffMillis(backoffCount, retryData.intervalMillis, LONG_RETRY_FACTOR)
|
|
558
|
+
: util.calculateBackoffMillis(backoffCount, retryData.intervalMillis);
|
|
559
|
+
// Increments backoff state.
|
|
560
|
+
const throttleMetadata = {
|
|
561
|
+
throttleEndTimeMillis: Date.now() + backoffMillis,
|
|
562
|
+
backoffCount: backoffCount + 1
|
|
563
|
+
};
|
|
564
|
+
// Persists state.
|
|
565
|
+
retryData.setThrottleMetadata(appId, throttleMetadata);
|
|
566
|
+
logger.debug(`Calling attemptFetch again in ${backoffMillis} millis`);
|
|
567
|
+
return attemptFetchDynamicConfigWithRetry(appFields, throttleMetadata, signal, retryData);
|
|
568
|
+
}
|
|
664
569
|
}
|
|
665
570
|
/**
|
|
666
571
|
* Supports waiting on a backoff by:
|
|
@@ -675,16 +580,16 @@ function attemptFetchDynamicConfigWithRetry(appFields, _a, signal, retryData //
|
|
|
675
580
|
* <p>Visible for testing.
|
|
676
581
|
*/
|
|
677
582
|
function setAbortableTimeout(signal, throttleEndTimeMillis) {
|
|
678
|
-
return new Promise(
|
|
583
|
+
return new Promise((resolve, reject) => {
|
|
679
584
|
// Derives backoff from given end time, normalizing negative numbers to zero.
|
|
680
|
-
|
|
681
|
-
|
|
585
|
+
const backoffMillis = Math.max(throttleEndTimeMillis - Date.now(), 0);
|
|
586
|
+
const timeout = setTimeout(resolve, backoffMillis);
|
|
682
587
|
// Adds listener, rather than sets onabort, because signal is a shared object.
|
|
683
|
-
signal.addEventListener(
|
|
588
|
+
signal.addEventListener(() => {
|
|
684
589
|
clearTimeout(timeout);
|
|
685
590
|
// If the request completes before this timeout, the rejection has no effect.
|
|
686
591
|
reject(ERROR_FACTORY.create("fetch-throttle" /* AnalyticsError.FETCH_THROTTLE */, {
|
|
687
|
-
throttleEndTimeMillis
|
|
592
|
+
throttleEndTimeMillis
|
|
688
593
|
}));
|
|
689
594
|
});
|
|
690
595
|
});
|
|
@@ -697,7 +602,7 @@ function isRetriableError(e) {
|
|
|
697
602
|
return false;
|
|
698
603
|
}
|
|
699
604
|
// Uses string index defined by ErrorData, which FirebaseError implements.
|
|
700
|
-
|
|
605
|
+
const httpStatus = Number(e.customData['httpStatus']);
|
|
701
606
|
return (httpStatus === 429 ||
|
|
702
607
|
httpStatus === 500 ||
|
|
703
608
|
httpStatus === 503 ||
|
|
@@ -711,18 +616,17 @@ function isRetriableError(e) {
|
|
|
711
616
|
* polyfill recommendation, like we do with the Fetch API, but this minimal shim can easily be
|
|
712
617
|
* swapped out if/when we do.
|
|
713
618
|
*/
|
|
714
|
-
|
|
715
|
-
|
|
619
|
+
class AnalyticsAbortSignal {
|
|
620
|
+
constructor() {
|
|
716
621
|
this.listeners = [];
|
|
717
622
|
}
|
|
718
|
-
|
|
623
|
+
addEventListener(listener) {
|
|
719
624
|
this.listeners.push(listener);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
this.listeners.forEach(
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
}());
|
|
625
|
+
}
|
|
626
|
+
abort() {
|
|
627
|
+
this.listeners.forEach(listener => listener());
|
|
628
|
+
}
|
|
629
|
+
}
|
|
726
630
|
|
|
727
631
|
/**
|
|
728
632
|
* @license
|
|
@@ -743,7 +647,7 @@ var AnalyticsAbortSignal = /** @class */ (function () {
|
|
|
743
647
|
/**
|
|
744
648
|
* Event parameters to set on 'gtag' during initialization.
|
|
745
649
|
*/
|
|
746
|
-
|
|
650
|
+
let defaultEventParametersForInit;
|
|
747
651
|
/**
|
|
748
652
|
* Logs an analytics event through the Firebase SDK.
|
|
749
653
|
*
|
|
@@ -751,25 +655,16 @@ var defaultEventParametersForInit;
|
|
|
751
655
|
* @param eventName Google Analytics event name, choose from standard list or use a custom string.
|
|
752
656
|
* @param eventParams Analytics event parameters.
|
|
753
657
|
*/
|
|
754
|
-
function logEvent$1(gtagFunction, initializationPromise, eventName, eventParams, options) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
return
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
case 2:
|
|
765
|
-
measurementId = _a.sent();
|
|
766
|
-
params = tslib.__assign(tslib.__assign({}, eventParams), { 'send_to': measurementId });
|
|
767
|
-
gtagFunction("event" /* GtagCommand.EVENT */, eventName, params);
|
|
768
|
-
_a.label = 3;
|
|
769
|
-
case 3: return [2 /*return*/];
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
});
|
|
658
|
+
async function logEvent$1(gtagFunction, initializationPromise, eventName, eventParams, options) {
|
|
659
|
+
if (options && options.global) {
|
|
660
|
+
gtagFunction("event" /* GtagCommand.EVENT */, eventName, eventParams);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
const measurementId = await initializationPromise;
|
|
665
|
+
const params = Object.assign(Object.assign({}, eventParams), { 'send_to': measurementId });
|
|
666
|
+
gtagFunction("event" /* GtagCommand.EVENT */, eventName, params);
|
|
667
|
+
}
|
|
773
668
|
}
|
|
774
669
|
/**
|
|
775
670
|
* Set screen_name parameter for this Google Analytics ID.
|
|
@@ -780,27 +675,18 @@ function logEvent$1(gtagFunction, initializationPromise, eventName, eventParams,
|
|
|
780
675
|
* @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
|
|
781
676
|
* @param screenName Screen name string to set.
|
|
782
677
|
*/
|
|
783
|
-
function setCurrentScreen$1(gtagFunction, initializationPromise, screenName, options) {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
return
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
case 2:
|
|
794
|
-
measurementId = _a.sent();
|
|
795
|
-
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
796
|
-
update: true,
|
|
797
|
-
'screen_name': screenName
|
|
798
|
-
});
|
|
799
|
-
_a.label = 3;
|
|
800
|
-
case 3: return [2 /*return*/];
|
|
801
|
-
}
|
|
678
|
+
async function setCurrentScreen$1(gtagFunction, initializationPromise, screenName, options) {
|
|
679
|
+
if (options && options.global) {
|
|
680
|
+
gtagFunction("set" /* GtagCommand.SET */, { 'screen_name': screenName });
|
|
681
|
+
return Promise.resolve();
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
const measurementId = await initializationPromise;
|
|
685
|
+
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
686
|
+
update: true,
|
|
687
|
+
'screen_name': screenName
|
|
802
688
|
});
|
|
803
|
-
}
|
|
689
|
+
}
|
|
804
690
|
}
|
|
805
691
|
/**
|
|
806
692
|
* Set user_id parameter for this Google Analytics ID.
|
|
@@ -808,27 +694,18 @@ function setCurrentScreen$1(gtagFunction, initializationPromise, screenName, opt
|
|
|
808
694
|
* @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
|
|
809
695
|
* @param id User ID string to set
|
|
810
696
|
*/
|
|
811
|
-
function setUserId$1(gtagFunction, initializationPromise, id, options) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
return
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
case 2:
|
|
822
|
-
measurementId = _a.sent();
|
|
823
|
-
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
824
|
-
update: true,
|
|
825
|
-
'user_id': id
|
|
826
|
-
});
|
|
827
|
-
_a.label = 3;
|
|
828
|
-
case 3: return [2 /*return*/];
|
|
829
|
-
}
|
|
697
|
+
async function setUserId$1(gtagFunction, initializationPromise, id, options) {
|
|
698
|
+
if (options && options.global) {
|
|
699
|
+
gtagFunction("set" /* GtagCommand.SET */, { 'user_id': id });
|
|
700
|
+
return Promise.resolve();
|
|
701
|
+
}
|
|
702
|
+
else {
|
|
703
|
+
const measurementId = await initializationPromise;
|
|
704
|
+
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
705
|
+
update: true,
|
|
706
|
+
'user_id': id
|
|
830
707
|
});
|
|
831
|
-
}
|
|
708
|
+
}
|
|
832
709
|
}
|
|
833
710
|
/**
|
|
834
711
|
* Set all other user properties other than user_id and screen_name.
|
|
@@ -836,33 +713,23 @@ function setUserId$1(gtagFunction, initializationPromise, id, options) {
|
|
|
836
713
|
* @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
|
|
837
714
|
* @param properties Map of user properties to set
|
|
838
715
|
*/
|
|
839
|
-
function setUserProperties$1(gtagFunction, initializationPromise, properties, options) {
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
case 1: return [4 /*yield*/, initializationPromise];
|
|
855
|
-
case 2:
|
|
856
|
-
measurementId = _b.sent();
|
|
857
|
-
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
858
|
-
update: true,
|
|
859
|
-
'user_properties': properties
|
|
860
|
-
});
|
|
861
|
-
_b.label = 3;
|
|
862
|
-
case 3: return [2 /*return*/];
|
|
863
|
-
}
|
|
716
|
+
async function setUserProperties$1(gtagFunction, initializationPromise, properties, options) {
|
|
717
|
+
if (options && options.global) {
|
|
718
|
+
const flatProperties = {};
|
|
719
|
+
for (const key of Object.keys(properties)) {
|
|
720
|
+
// use dot notation for merge behavior in gtag.js
|
|
721
|
+
flatProperties[`user_properties.${key}`] = properties[key];
|
|
722
|
+
}
|
|
723
|
+
gtagFunction("set" /* GtagCommand.SET */, flatProperties);
|
|
724
|
+
return Promise.resolve();
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
const measurementId = await initializationPromise;
|
|
728
|
+
gtagFunction("config" /* GtagCommand.CONFIG */, measurementId, {
|
|
729
|
+
update: true,
|
|
730
|
+
'user_properties': properties
|
|
864
731
|
});
|
|
865
|
-
}
|
|
732
|
+
}
|
|
866
733
|
}
|
|
867
734
|
/**
|
|
868
735
|
* Retrieves a unique Google Analytics identifier for the web client.
|
|
@@ -870,23 +737,14 @@ function setUserProperties$1(gtagFunction, initializationPromise, properties, op
|
|
|
870
737
|
*
|
|
871
738
|
* @param gtagFunction Wrapped gtag function that waits for fid to be set before sending an event
|
|
872
739
|
*/
|
|
873
|
-
function internalGetGoogleAnalyticsClientId(gtagFunction, initializationPromise) {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
case 1:
|
|
880
|
-
measurementId = _a.sent();
|
|
881
|
-
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
882
|
-
gtagFunction("get" /* GtagCommand.GET */, measurementId, 'client_id', function (clientId) {
|
|
883
|
-
if (!clientId) {
|
|
884
|
-
reject(ERROR_FACTORY.create("no-client-id" /* AnalyticsError.NO_CLIENT_ID */));
|
|
885
|
-
}
|
|
886
|
-
resolve(clientId);
|
|
887
|
-
});
|
|
888
|
-
})];
|
|
740
|
+
async function internalGetGoogleAnalyticsClientId(gtagFunction, initializationPromise) {
|
|
741
|
+
const measurementId = await initializationPromise;
|
|
742
|
+
return new Promise((resolve, reject) => {
|
|
743
|
+
gtagFunction("get" /* GtagCommand.GET */, measurementId, 'client_id', (clientId) => {
|
|
744
|
+
if (!clientId) {
|
|
745
|
+
reject(ERROR_FACTORY.create("no-client-id" /* AnalyticsError.NO_CLIENT_ID */));
|
|
889
746
|
}
|
|
747
|
+
resolve(clientId);
|
|
890
748
|
});
|
|
891
749
|
});
|
|
892
750
|
}
|
|
@@ -895,24 +753,14 @@ function internalGetGoogleAnalyticsClientId(gtagFunction, initializationPromise)
|
|
|
895
753
|
*
|
|
896
754
|
* @param enabled If true, collection is enabled for this ID.
|
|
897
755
|
*/
|
|
898
|
-
function setAnalyticsCollectionEnabled$1(initializationPromise, enabled) {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
return tslib.__generator(this, function (_a) {
|
|
902
|
-
switch (_a.label) {
|
|
903
|
-
case 0: return [4 /*yield*/, initializationPromise];
|
|
904
|
-
case 1:
|
|
905
|
-
measurementId = _a.sent();
|
|
906
|
-
window["ga-disable-".concat(measurementId)] = !enabled;
|
|
907
|
-
return [2 /*return*/];
|
|
908
|
-
}
|
|
909
|
-
});
|
|
910
|
-
});
|
|
756
|
+
async function setAnalyticsCollectionEnabled$1(initializationPromise, enabled) {
|
|
757
|
+
const measurementId = await initializationPromise;
|
|
758
|
+
window[`ga-disable-${measurementId}`] = !enabled;
|
|
911
759
|
}
|
|
912
760
|
/**
|
|
913
761
|
* Consent parameters to default to during 'gtag' initialization.
|
|
914
762
|
*/
|
|
915
|
-
|
|
763
|
+
let defaultConsentSettingsForInit;
|
|
916
764
|
/**
|
|
917
765
|
* Sets the variable {@link defaultConsentSettingsForInit} for use in the initialization of
|
|
918
766
|
* analytics.
|
|
@@ -948,33 +796,25 @@ function _setDefaultEventParametersForInit(customParams) {
|
|
|
948
796
|
* See the License for the specific language governing permissions and
|
|
949
797
|
* limitations under the License.
|
|
950
798
|
*/
|
|
951
|
-
function validateIndexedDB() {
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */, {
|
|
971
|
-
errorInfo: e_1 === null || e_1 === void 0 ? void 0 : e_1.toString()
|
|
972
|
-
}).message);
|
|
973
|
-
return [2 /*return*/, false];
|
|
974
|
-
case 4: return [2 /*return*/, true];
|
|
975
|
-
}
|
|
976
|
-
});
|
|
977
|
-
});
|
|
799
|
+
async function validateIndexedDB() {
|
|
800
|
+
if (!util.isIndexedDBAvailable()) {
|
|
801
|
+
logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */, {
|
|
802
|
+
errorInfo: 'IndexedDB is not available in this environment.'
|
|
803
|
+
}).message);
|
|
804
|
+
return false;
|
|
805
|
+
}
|
|
806
|
+
else {
|
|
807
|
+
try {
|
|
808
|
+
await util.validateIndexedDBOpenable();
|
|
809
|
+
}
|
|
810
|
+
catch (e) {
|
|
811
|
+
logger.warn(ERROR_FACTORY.create("indexeddb-unavailable" /* AnalyticsError.INDEXEDDB_UNAVAILABLE */, {
|
|
812
|
+
errorInfo: e === null || e === void 0 ? void 0 : e.toString()
|
|
813
|
+
}).message);
|
|
814
|
+
return false;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
return true;
|
|
978
818
|
}
|
|
979
819
|
/**
|
|
980
820
|
* Initialize the analytics instance in gtag.js by calling config command with fid.
|
|
@@ -989,80 +829,72 @@ function validateIndexedDB() {
|
|
|
989
829
|
*
|
|
990
830
|
* @returns Measurement ID.
|
|
991
831
|
*/
|
|
992
|
-
function _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCore, dataLayerName, options) {
|
|
832
|
+
async function _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCore, dataLayerName, options) {
|
|
993
833
|
var _a;
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
return installations.getId();
|
|
1019
|
-
}
|
|
1020
|
-
else {
|
|
1021
|
-
return undefined;
|
|
1022
|
-
}
|
|
1023
|
-
});
|
|
1024
|
-
return [4 /*yield*/, Promise.all([
|
|
1025
|
-
dynamicConfigPromise,
|
|
1026
|
-
fidPromise
|
|
1027
|
-
])];
|
|
1028
|
-
case 1:
|
|
1029
|
-
_b = _c.sent(), dynamicConfig = _b[0], fid = _b[1];
|
|
1030
|
-
// Detect if user has already put the gtag <script> tag on this page with the passed in
|
|
1031
|
-
// data layer name.
|
|
1032
|
-
if (!findGtagScriptOnPage(dataLayerName)) {
|
|
1033
|
-
insertScriptTag(dataLayerName, dynamicConfig.measurementId);
|
|
1034
|
-
}
|
|
1035
|
-
// Detects if there are consent settings that need to be configured.
|
|
1036
|
-
if (defaultConsentSettingsForInit) {
|
|
1037
|
-
gtagCore("consent" /* GtagCommand.CONSENT */, 'default', defaultConsentSettingsForInit);
|
|
1038
|
-
_setConsentDefaultForInit(undefined);
|
|
1039
|
-
}
|
|
1040
|
-
// This command initializes gtag.js and only needs to be called once for the entire web app,
|
|
1041
|
-
// but since it is idempotent, we can call it multiple times.
|
|
1042
|
-
// We keep it together with other initialization logic for better code structure.
|
|
1043
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1044
|
-
gtagCore('js', new Date());
|
|
1045
|
-
configProperties = (_a = options === null || options === void 0 ? void 0 : options.config) !== null && _a !== void 0 ? _a : {};
|
|
1046
|
-
// guard against developers accidentally setting properties with prefix `firebase_`
|
|
1047
|
-
configProperties[ORIGIN_KEY] = 'firebase';
|
|
1048
|
-
configProperties.update = true;
|
|
1049
|
-
if (fid != null) {
|
|
1050
|
-
configProperties[GA_FID_KEY] = fid;
|
|
1051
|
-
}
|
|
1052
|
-
// It should be the first config command called on this GA-ID
|
|
1053
|
-
// Initialize this GA-ID and set FID on it using the gtag config API.
|
|
1054
|
-
// Note: This will trigger a page_view event unless 'send_page_view' is set to false in
|
|
1055
|
-
// `configProperties`.
|
|
1056
|
-
gtagCore("config" /* GtagCommand.CONFIG */, dynamicConfig.measurementId, configProperties);
|
|
1057
|
-
// Detects if there is data that will be set on every event logged from the SDK.
|
|
1058
|
-
if (defaultEventParametersForInit) {
|
|
1059
|
-
gtagCore("set" /* GtagCommand.SET */, defaultEventParametersForInit);
|
|
1060
|
-
_setDefaultEventParametersForInit(undefined);
|
|
1061
|
-
}
|
|
1062
|
-
return [2 /*return*/, dynamicConfig.measurementId];
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
834
|
+
const dynamicConfigPromise = fetchDynamicConfigWithRetry(app);
|
|
835
|
+
// Once fetched, map measurementIds to appId, for ease of lookup in wrapped gtag function.
|
|
836
|
+
dynamicConfigPromise
|
|
837
|
+
.then(config => {
|
|
838
|
+
measurementIdToAppId[config.measurementId] = config.appId;
|
|
839
|
+
if (app.options.measurementId &&
|
|
840
|
+
config.measurementId !== app.options.measurementId) {
|
|
841
|
+
logger.warn(`The measurement ID in the local Firebase config (${app.options.measurementId})` +
|
|
842
|
+
` does not match the measurement ID fetched from the server (${config.measurementId}).` +
|
|
843
|
+
` To ensure analytics events are always sent to the correct Analytics property,` +
|
|
844
|
+
` update the` +
|
|
845
|
+
` measurement ID field in the local config or remove it from the local config.`);
|
|
846
|
+
}
|
|
847
|
+
})
|
|
848
|
+
.catch(e => logger.error(e));
|
|
849
|
+
// Add to list to track state of all dynamic config promises.
|
|
850
|
+
dynamicConfigPromisesList.push(dynamicConfigPromise);
|
|
851
|
+
const fidPromise = validateIndexedDB().then(envIsValid => {
|
|
852
|
+
if (envIsValid) {
|
|
853
|
+
return installations.getId();
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
return undefined;
|
|
857
|
+
}
|
|
1065
858
|
});
|
|
859
|
+
const [dynamicConfig, fid] = await Promise.all([
|
|
860
|
+
dynamicConfigPromise,
|
|
861
|
+
fidPromise
|
|
862
|
+
]);
|
|
863
|
+
// Detect if user has already put the gtag <script> tag on this page with the passed in
|
|
864
|
+
// data layer name.
|
|
865
|
+
if (!findGtagScriptOnPage(dataLayerName)) {
|
|
866
|
+
insertScriptTag(dataLayerName, dynamicConfig.measurementId);
|
|
867
|
+
}
|
|
868
|
+
// Detects if there are consent settings that need to be configured.
|
|
869
|
+
if (defaultConsentSettingsForInit) {
|
|
870
|
+
gtagCore("consent" /* GtagCommand.CONSENT */, 'default', defaultConsentSettingsForInit);
|
|
871
|
+
_setConsentDefaultForInit(undefined);
|
|
872
|
+
}
|
|
873
|
+
// This command initializes gtag.js and only needs to be called once for the entire web app,
|
|
874
|
+
// but since it is idempotent, we can call it multiple times.
|
|
875
|
+
// We keep it together with other initialization logic for better code structure.
|
|
876
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
877
|
+
gtagCore('js', new Date());
|
|
878
|
+
// User config added first. We don't want users to accidentally overwrite
|
|
879
|
+
// base Firebase config properties.
|
|
880
|
+
const configProperties = (_a = options === null || options === void 0 ? void 0 : options.config) !== null && _a !== void 0 ? _a : {};
|
|
881
|
+
// guard against developers accidentally setting properties with prefix `firebase_`
|
|
882
|
+
configProperties[ORIGIN_KEY] = 'firebase';
|
|
883
|
+
configProperties.update = true;
|
|
884
|
+
if (fid != null) {
|
|
885
|
+
configProperties[GA_FID_KEY] = fid;
|
|
886
|
+
}
|
|
887
|
+
// It should be the first config command called on this GA-ID
|
|
888
|
+
// Initialize this GA-ID and set FID on it using the gtag config API.
|
|
889
|
+
// Note: This will trigger a page_view event unless 'send_page_view' is set to false in
|
|
890
|
+
// `configProperties`.
|
|
891
|
+
gtagCore("config" /* GtagCommand.CONFIG */, dynamicConfig.measurementId, configProperties);
|
|
892
|
+
// Detects if there is data that will be set on every event logged from the SDK.
|
|
893
|
+
if (defaultEventParametersForInit) {
|
|
894
|
+
gtagCore("set" /* GtagCommand.SET */, defaultEventParametersForInit);
|
|
895
|
+
_setDefaultEventParametersForInit(undefined);
|
|
896
|
+
}
|
|
897
|
+
return dynamicConfig.measurementId;
|
|
1066
898
|
}
|
|
1067
899
|
|
|
1068
900
|
/**
|
|
@@ -1084,58 +916,57 @@ function _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToApp
|
|
|
1084
916
|
/**
|
|
1085
917
|
* Analytics Service class.
|
|
1086
918
|
*/
|
|
1087
|
-
|
|
1088
|
-
|
|
919
|
+
class AnalyticsService {
|
|
920
|
+
constructor(app) {
|
|
1089
921
|
this.app = app;
|
|
1090
922
|
}
|
|
1091
|
-
|
|
923
|
+
_delete() {
|
|
1092
924
|
delete initializationPromisesMap[this.app.options.appId];
|
|
1093
925
|
return Promise.resolve();
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
}());
|
|
926
|
+
}
|
|
927
|
+
}
|
|
1097
928
|
/**
|
|
1098
929
|
* Maps appId to full initialization promise. Wrapped gtag calls must wait on
|
|
1099
930
|
* all or some of these, depending on the call's `send_to` param and the status
|
|
1100
931
|
* of the dynamic config fetches (see below).
|
|
1101
932
|
*/
|
|
1102
|
-
|
|
933
|
+
let initializationPromisesMap = {};
|
|
1103
934
|
/**
|
|
1104
935
|
* List of dynamic config fetch promises. In certain cases, wrapped gtag calls
|
|
1105
936
|
* wait on all these to be complete in order to determine if it can selectively
|
|
1106
937
|
* wait for only certain initialization (FID) promises or if it must wait for all.
|
|
1107
938
|
*/
|
|
1108
|
-
|
|
939
|
+
let dynamicConfigPromisesList = [];
|
|
1109
940
|
/**
|
|
1110
941
|
* Maps fetched measurementIds to appId. Populated when the app's dynamic config
|
|
1111
942
|
* fetch completes. If already populated, gtag config calls can use this to
|
|
1112
943
|
* selectively wait for only this app's initialization promise (FID) instead of all
|
|
1113
944
|
* initialization promises.
|
|
1114
945
|
*/
|
|
1115
|
-
|
|
946
|
+
const measurementIdToAppId = {};
|
|
1116
947
|
/**
|
|
1117
948
|
* Name for window global data layer array used by GA: defaults to 'dataLayer'.
|
|
1118
949
|
*/
|
|
1119
|
-
|
|
950
|
+
let dataLayerName = 'dataLayer';
|
|
1120
951
|
/**
|
|
1121
952
|
* Name for window global gtag function used by GA: defaults to 'gtag'.
|
|
1122
953
|
*/
|
|
1123
|
-
|
|
954
|
+
let gtagName = 'gtag';
|
|
1124
955
|
/**
|
|
1125
956
|
* Reproduction of standard gtag function or reference to existing
|
|
1126
957
|
* gtag function on window object.
|
|
1127
958
|
*/
|
|
1128
|
-
|
|
959
|
+
let gtagCoreFunction;
|
|
1129
960
|
/**
|
|
1130
961
|
* Wrapper around gtag function that ensures FID is sent with all
|
|
1131
962
|
* relevant event and config calls.
|
|
1132
963
|
*/
|
|
1133
|
-
|
|
964
|
+
let wrappedGtagFunction;
|
|
1134
965
|
/**
|
|
1135
966
|
* Flag to ensure page initialization steps (creation or wrapping of
|
|
1136
967
|
* dataLayer and gtag script) are only run once per page load.
|
|
1137
968
|
*/
|
|
1138
|
-
|
|
969
|
+
let globalInitDone = false;
|
|
1139
970
|
/**
|
|
1140
971
|
* Configures Firebase Analytics to use custom `gtag` or `dataLayer` names.
|
|
1141
972
|
* Intended to be used if `gtag.js` script has been installed on
|
|
@@ -1165,7 +996,7 @@ function settings(options) {
|
|
|
1165
996
|
* error that also lists details for each mismatch found.
|
|
1166
997
|
*/
|
|
1167
998
|
function warnOnBrowserContextMismatch() {
|
|
1168
|
-
|
|
999
|
+
const mismatchedEnvMessages = [];
|
|
1169
1000
|
if (util.isBrowserExtension()) {
|
|
1170
1001
|
mismatchedEnvMessages.push('This is a browser extension environment.');
|
|
1171
1002
|
}
|
|
@@ -1173,10 +1004,10 @@ function warnOnBrowserContextMismatch() {
|
|
|
1173
1004
|
mismatchedEnvMessages.push('Cookies are not available.');
|
|
1174
1005
|
}
|
|
1175
1006
|
if (mismatchedEnvMessages.length > 0) {
|
|
1176
|
-
|
|
1177
|
-
.map(
|
|
1007
|
+
const details = mismatchedEnvMessages
|
|
1008
|
+
.map((message, index) => `(${index + 1}) ${message}`)
|
|
1178
1009
|
.join(' ');
|
|
1179
|
-
|
|
1010
|
+
const err = ERROR_FACTORY.create("invalid-analytics-context" /* AnalyticsError.INVALID_ANALYTICS_CONTEXT */, {
|
|
1180
1011
|
errorInfo: details
|
|
1181
1012
|
});
|
|
1182
1013
|
logger.warn(err.message);
|
|
@@ -1188,15 +1019,15 @@ function warnOnBrowserContextMismatch() {
|
|
|
1188
1019
|
*/
|
|
1189
1020
|
function factory(app, installations, options) {
|
|
1190
1021
|
warnOnBrowserContextMismatch();
|
|
1191
|
-
|
|
1022
|
+
const appId = app.options.appId;
|
|
1192
1023
|
if (!appId) {
|
|
1193
1024
|
throw ERROR_FACTORY.create("no-app-id" /* AnalyticsError.NO_APP_ID */);
|
|
1194
1025
|
}
|
|
1195
1026
|
if (!app.options.apiKey) {
|
|
1196
1027
|
if (app.options.measurementId) {
|
|
1197
|
-
logger.warn(
|
|
1198
|
-
|
|
1199
|
-
|
|
1028
|
+
logger.warn(`The "apiKey" field is empty in the local Firebase config. This is needed to fetch the latest` +
|
|
1029
|
+
` measurement ID for this Firebase app. Falling back to the measurement ID ${app.options.measurementId}` +
|
|
1030
|
+
` provided in the "measurementId" field in the local Firebase config.`);
|
|
1200
1031
|
}
|
|
1201
1032
|
else {
|
|
1202
1033
|
throw ERROR_FACTORY.create("no-api-key" /* AnalyticsError.NO_API_KEY */);
|
|
@@ -1211,7 +1042,7 @@ function factory(app, installations, options) {
|
|
|
1211
1042
|
// Steps here should only be done once per page: creation or wrapping
|
|
1212
1043
|
// of dataLayer and global gtag function.
|
|
1213
1044
|
getOrCreateDataLayer(dataLayerName);
|
|
1214
|
-
|
|
1045
|
+
const { wrappedGtag, gtagCore } = wrapOrCreateGtag(initializationPromisesMap, dynamicConfigPromisesList, measurementIdToAppId, dataLayerName, gtagName);
|
|
1215
1046
|
wrappedGtagFunction = wrappedGtag;
|
|
1216
1047
|
gtagCoreFunction = gtagCore;
|
|
1217
1048
|
globalInitDone = true;
|
|
@@ -1219,7 +1050,7 @@ function factory(app, installations, options) {
|
|
|
1219
1050
|
// Async but non-blocking.
|
|
1220
1051
|
// This map reflects the completion state of all promises for each appId.
|
|
1221
1052
|
initializationPromisesMap[appId] = _initializeAnalytics(app, dynamicConfigPromisesList, measurementIdToAppId, installations, gtagCoreFunction, dataLayerName, options);
|
|
1222
|
-
|
|
1053
|
+
const analyticsInstance = new AnalyticsService(app);
|
|
1223
1054
|
return analyticsInstance;
|
|
1224
1055
|
}
|
|
1225
1056
|
|
|
@@ -1231,11 +1062,10 @@ function factory(app, installations, options) {
|
|
|
1231
1062
|
*
|
|
1232
1063
|
* @param app - The {@link @firebase/app#FirebaseApp} to use.
|
|
1233
1064
|
*/
|
|
1234
|
-
function getAnalytics(app$1) {
|
|
1235
|
-
if (app$1 === void 0) { app$1 = app.getApp(); }
|
|
1065
|
+
function getAnalytics(app$1 = app.getApp()) {
|
|
1236
1066
|
app$1 = util.getModularInstance(app$1);
|
|
1237
1067
|
// Dependencies
|
|
1238
|
-
|
|
1068
|
+
const analyticsProvider = app._getProvider(app$1, ANALYTICS_TYPE);
|
|
1239
1069
|
if (analyticsProvider.isInitialized()) {
|
|
1240
1070
|
return analyticsProvider.getImmediate();
|
|
1241
1071
|
}
|
|
@@ -1248,12 +1078,11 @@ function getAnalytics(app$1) {
|
|
|
1248
1078
|
*
|
|
1249
1079
|
* @param app - The {@link @firebase/app#FirebaseApp} to use.
|
|
1250
1080
|
*/
|
|
1251
|
-
function initializeAnalytics(app$1, options) {
|
|
1252
|
-
if (options === void 0) { options = {}; }
|
|
1081
|
+
function initializeAnalytics(app$1, options = {}) {
|
|
1253
1082
|
// Dependencies
|
|
1254
|
-
|
|
1083
|
+
const analyticsProvider = app._getProvider(app$1, ANALYTICS_TYPE);
|
|
1255
1084
|
if (analyticsProvider.isInitialized()) {
|
|
1256
|
-
|
|
1085
|
+
const existingInstance = analyticsProvider.getImmediate();
|
|
1257
1086
|
if (util.deepEqual(options, analyticsProvider.getOptions())) {
|
|
1258
1087
|
return existingInstance;
|
|
1259
1088
|
}
|
|
@@ -1261,7 +1090,7 @@ function initializeAnalytics(app$1, options) {
|
|
|
1261
1090
|
throw ERROR_FACTORY.create("already-initialized" /* AnalyticsError.ALREADY_INITIALIZED */);
|
|
1262
1091
|
}
|
|
1263
1092
|
}
|
|
1264
|
-
|
|
1093
|
+
const analyticsInstance = analyticsProvider.initialize({ options });
|
|
1265
1094
|
return analyticsInstance;
|
|
1266
1095
|
}
|
|
1267
1096
|
/**
|
|
@@ -1275,35 +1104,23 @@ function initializeAnalytics(app$1, options) {
|
|
|
1275
1104
|
* @public
|
|
1276
1105
|
*
|
|
1277
1106
|
*/
|
|
1278
|
-
function isSupported() {
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
_a.trys.push([1, 3, , 4]);
|
|
1296
|
-
return [4 /*yield*/, util.validateIndexedDBOpenable()];
|
|
1297
|
-
case 2:
|
|
1298
|
-
isDBOpenable = _a.sent();
|
|
1299
|
-
return [2 /*return*/, isDBOpenable];
|
|
1300
|
-
case 3:
|
|
1301
|
-
_a.sent();
|
|
1302
|
-
return [2 /*return*/, false];
|
|
1303
|
-
case 4: return [2 /*return*/];
|
|
1304
|
-
}
|
|
1305
|
-
});
|
|
1306
|
-
});
|
|
1107
|
+
async function isSupported() {
|
|
1108
|
+
if (util.isBrowserExtension()) {
|
|
1109
|
+
return false;
|
|
1110
|
+
}
|
|
1111
|
+
if (!util.areCookiesEnabled()) {
|
|
1112
|
+
return false;
|
|
1113
|
+
}
|
|
1114
|
+
if (!util.isIndexedDBAvailable()) {
|
|
1115
|
+
return false;
|
|
1116
|
+
}
|
|
1117
|
+
try {
|
|
1118
|
+
const isDBOpenable = await util.validateIndexedDBOpenable();
|
|
1119
|
+
return isDBOpenable;
|
|
1120
|
+
}
|
|
1121
|
+
catch (error) {
|
|
1122
|
+
return false;
|
|
1123
|
+
}
|
|
1307
1124
|
}
|
|
1308
1125
|
/**
|
|
1309
1126
|
* Use gtag `config` command to set `screen_name`.
|
|
@@ -1318,7 +1135,7 @@ function isSupported() {
|
|
|
1318
1135
|
*/
|
|
1319
1136
|
function setCurrentScreen(analyticsInstance, screenName, options) {
|
|
1320
1137
|
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1321
|
-
setCurrentScreen$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], screenName, options).catch(
|
|
1138
|
+
setCurrentScreen$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], screenName, options).catch(e => logger.error(e));
|
|
1322
1139
|
}
|
|
1323
1140
|
/**
|
|
1324
1141
|
* Retrieves a unique Google Analytics identifier for the web client.
|
|
@@ -1328,13 +1145,9 @@ function setCurrentScreen(analyticsInstance, screenName, options) {
|
|
|
1328
1145
|
*
|
|
1329
1146
|
* @param app - The {@link @firebase/app#FirebaseApp} to use.
|
|
1330
1147
|
*/
|
|
1331
|
-
function getGoogleAnalyticsClientId(analyticsInstance) {
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1335
|
-
return [2 /*return*/, internalGetGoogleAnalyticsClientId(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId])];
|
|
1336
|
-
});
|
|
1337
|
-
});
|
|
1148
|
+
async function getGoogleAnalyticsClientId(analyticsInstance) {
|
|
1149
|
+
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1150
|
+
return internalGetGoogleAnalyticsClientId(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId]);
|
|
1338
1151
|
}
|
|
1339
1152
|
/**
|
|
1340
1153
|
* Use gtag `config` command to set `user_id`.
|
|
@@ -1346,7 +1159,7 @@ function getGoogleAnalyticsClientId(analyticsInstance) {
|
|
|
1346
1159
|
*/
|
|
1347
1160
|
function setUserId(analyticsInstance, id, options) {
|
|
1348
1161
|
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1349
|
-
setUserId$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], id, options).catch(
|
|
1162
|
+
setUserId$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], id, options).catch(e => logger.error(e));
|
|
1350
1163
|
}
|
|
1351
1164
|
/**
|
|
1352
1165
|
* Use gtag `config` command to set all params specified.
|
|
@@ -1355,7 +1168,7 @@ function setUserId(analyticsInstance, id, options) {
|
|
|
1355
1168
|
*/
|
|
1356
1169
|
function setUserProperties(analyticsInstance, properties, options) {
|
|
1357
1170
|
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1358
|
-
setUserProperties$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], properties, options).catch(
|
|
1171
|
+
setUserProperties$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], properties, options).catch(e => logger.error(e));
|
|
1359
1172
|
}
|
|
1360
1173
|
/**
|
|
1361
1174
|
* Sets whether Google Analytics collection is enabled for this app on this device.
|
|
@@ -1368,7 +1181,7 @@ function setUserProperties(analyticsInstance, properties, options) {
|
|
|
1368
1181
|
*/
|
|
1369
1182
|
function setAnalyticsCollectionEnabled(analyticsInstance, enabled) {
|
|
1370
1183
|
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1371
|
-
setAnalyticsCollectionEnabled$1(initializationPromisesMap[analyticsInstance.app.options.appId], enabled).catch(
|
|
1184
|
+
setAnalyticsCollectionEnabled$1(initializationPromisesMap[analyticsInstance.app.options.appId], enabled).catch(e => logger.error(e));
|
|
1372
1185
|
}
|
|
1373
1186
|
/**
|
|
1374
1187
|
* Adds data that will be set on every event logged from the SDK, including automatic ones.
|
|
@@ -1399,7 +1212,7 @@ function setDefaultEventParameters(customParams) {
|
|
|
1399
1212
|
*/
|
|
1400
1213
|
function logEvent(analyticsInstance, eventName, eventParams, options) {
|
|
1401
1214
|
analyticsInstance = util.getModularInstance(analyticsInstance);
|
|
1402
|
-
logEvent$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], eventName, eventParams, options).catch(
|
|
1215
|
+
logEvent$1(wrappedGtagFunction, initializationPromisesMap[analyticsInstance.app.options.appId], eventName, eventParams, options).catch(e => logger.error(e));
|
|
1403
1216
|
}
|
|
1404
1217
|
/**
|
|
1405
1218
|
* Sets the applicable end user consent state for this web app across all gtag references once
|
|
@@ -1420,8 +1233,8 @@ function setConsent(consentSettings) {
|
|
|
1420
1233
|
}
|
|
1421
1234
|
}
|
|
1422
1235
|
|
|
1423
|
-
|
|
1424
|
-
|
|
1236
|
+
const name = "@firebase/analytics";
|
|
1237
|
+
const version = "0.10.9-canary.a97ac88db";
|
|
1425
1238
|
|
|
1426
1239
|
/**
|
|
1427
1240
|
* The Firebase Analytics Web SDK.
|
|
@@ -1430,24 +1243,23 @@ var version = "0.10.8";
|
|
|
1430
1243
|
* @packageDocumentation
|
|
1431
1244
|
*/
|
|
1432
1245
|
function registerAnalytics() {
|
|
1433
|
-
app._registerComponent(new component.Component(ANALYTICS_TYPE,
|
|
1434
|
-
var analyticsOptions = _a.options;
|
|
1246
|
+
app._registerComponent(new component.Component(ANALYTICS_TYPE, (container, { options: analyticsOptions }) => {
|
|
1435
1247
|
// getImmediate for FirebaseApp will always succeed
|
|
1436
|
-
|
|
1437
|
-
|
|
1248
|
+
const app = container.getProvider('app').getImmediate();
|
|
1249
|
+
const installations = container
|
|
1438
1250
|
.getProvider('installations-internal')
|
|
1439
1251
|
.getImmediate();
|
|
1440
1252
|
return factory(app, installations, analyticsOptions);
|
|
1441
1253
|
}, "PUBLIC" /* ComponentType.PUBLIC */));
|
|
1442
1254
|
app._registerComponent(new component.Component('analytics-internal', internalFactory, "PRIVATE" /* ComponentType.PRIVATE */));
|
|
1443
1255
|
app.registerVersion(name, version);
|
|
1444
|
-
// BUILD_TARGET will be replaced by values like
|
|
1445
|
-
app.registerVersion(name, version, '
|
|
1256
|
+
// BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
|
|
1257
|
+
app.registerVersion(name, version, 'cjs2017');
|
|
1446
1258
|
function internalFactory(container) {
|
|
1447
1259
|
try {
|
|
1448
|
-
|
|
1260
|
+
const analytics = container.getProvider(ANALYTICS_TYPE).getImmediate();
|
|
1449
1261
|
return {
|
|
1450
|
-
logEvent:
|
|
1262
|
+
logEvent: (eventName, eventParams, options) => logEvent(analytics, eventName, eventParams, options)
|
|
1451
1263
|
};
|
|
1452
1264
|
}
|
|
1453
1265
|
catch (e) {
|