Skip to content

Add function setDefaultEventParameters() to set data that will be logged on every analytics SDK event #6367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 24, 2022
Merged
5 changes: 5 additions & 0 deletions .changeset/silly-panthers-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@firebase/analytics': minor
---

Add function `setDefaultEventParameters()` to set data that will be logged on every Analytics SDK event
3 changes: 3 additions & 0 deletions common/api-review/analytics.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,9 @@ export function setAnalyticsCollectionEnabled(analyticsInstance: Analytics, enab
// @public @deprecated
export function setCurrentScreen(analyticsInstance: Analytics, screenName: string, options?: AnalyticsCallOptions): void;

// @public
export function setDefaultEventParameters(customParams: CustomParams): void;

// @public
export function settings(options: SettingsOptions): void;

Expand Down
31 changes: 30 additions & 1 deletion packages/analytics/src/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,22 @@ import { expect } from 'chai';
import { SinonStub, stub } from 'sinon';
import '../testing/setup';
import { getFullApp } from '../testing/get-fake-firebase-services';
import { getAnalytics, initializeAnalytics } from './api';
import {
getAnalytics,
initializeAnalytics,
setDefaultEventParameters
} from './api';
import { FirebaseApp, deleteApp } from '@firebase/app';
import { AnalyticsError } from './errors';
import * as init from './initialize-analytics';
const fakeAppParams = { appId: 'abcdefgh12345:23405', apiKey: 'AAbbCCdd12345' };
import * as factory from './factory';
import { defaultEventParametersForInit } from './functions';

describe('FirebaseAnalytics API tests', () => {
let initStub: SinonStub = stub();
let app: FirebaseApp;
const wrappedGtag: SinonStub = stub();

beforeEach(() => {
initStub = stub(init, '_initializeAnalytics').resolves(
Expand Down Expand Up @@ -94,4 +101,26 @@ describe('FirebaseAnalytics API tests', () => {
const analyticsInstance = initializeAnalytics(app);
expect(getAnalytics(app)).to.equal(analyticsInstance);
});
it('setDefaultEventParameters() updates defaultEventParametersForInit if gtag does not exist ', () => {
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
app = getFullApp(fakeAppParams);
setDefaultEventParameters(eventParametersForInit);
expect(defaultEventParametersForInit).to.deep.equal(eventParametersForInit);
});
it('setDefaultEventParameters() calls gtag set if wrappedGtagFunction exists', () => {
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
stub(factory, 'wrappedGtagFunction').get(() => wrappedGtag);
app = getFullApp(fakeAppParams);
setDefaultEventParameters(eventParametersForInit);
expect(wrappedGtag).to.have.been.calledWithExactly(
'set',
eventParametersForInit
);
});
});
22 changes: 20 additions & 2 deletions packages/analytics/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
getModularInstance,
deepEqual
} from '@firebase/util';
import { ANALYTICS_TYPE } from './constants';
import { ANALYTICS_TYPE, GtagCommand } from './constants';
import {
AnalyticsService,
initializationPromisesMap,
Expand All @@ -47,7 +47,8 @@ import {
setCurrentScreen as internalSetCurrentScreen,
setUserId as internalSetUserId,
setUserProperties as internalSetUserProperties,
setAnalyticsCollectionEnabled as internalSetAnalyticsCollectionEnabled
setAnalyticsCollectionEnabled as internalSetAnalyticsCollectionEnabled,
_setDefaultEventParametersForInit
} from './functions';
import { ERROR_FACTORY, AnalyticsError } from './errors';

Expand Down Expand Up @@ -224,6 +225,23 @@ export function setAnalyticsCollectionEnabled(
enabled
).catch(e => logger.error(e));
}

/**
* Adds data that will be set on every event logged from the SDK, including automatic ones.
* With gtag's "set" command, the values passed persist on the current page and are passed with
* all subsequent events.
* @public
* @param customParams Any custom params the user may pass to gtag.js.
*/
export function setDefaultEventParameters(customParams: CustomParams): void {
// Check if reference to existing gtag function on window object exists
if (wrappedGtagFunction) {
wrappedGtagFunction(GtagCommand.SET, customParams);
} else {
_setDefaultEventParametersForInit(customParams);
}
}

/**
* Sends a Google Analytics event with given `eventParams`. This method
* automatically associates this logged event with this Firebase web
Expand Down
24 changes: 23 additions & 1 deletion packages/analytics/src/functions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import {
logEvent,
setUserId,
setUserProperties,
setAnalyticsCollectionEnabled
setAnalyticsCollectionEnabled,
defaultEventParametersForInit,
_setDefaultEventParametersForInit
} from './functions';
import { GtagCommand } from './constants';

Expand Down Expand Up @@ -170,4 +172,24 @@ describe('FirebaseAnalytics methods', () => {
expect(window[`ga-disable-${fakeMeasurementId}`]).to.be.true;
delete window[`ga-disable-${fakeMeasurementId}`];
});
it('_setDefaultEventParametersForInit() stores individual params correctly', async () => {
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
_setDefaultEventParametersForInit(eventParametersForInit);
expect(defaultEventParametersForInit).to.deep.equal(eventParametersForInit);
});
it('_setDefaultEventParametersForInit() replaces previous params with new params', async () => {
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
const additionalParams = { 'food': 'sushi' };
_setDefaultEventParametersForInit(eventParametersForInit);
_setDefaultEventParametersForInit(additionalParams);
expect(defaultEventParametersForInit).to.deep.equal({
...additionalParams
});
});
});
18 changes: 18 additions & 0 deletions packages/analytics/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ import {
} from './public-types';
import { Gtag } from './types';
import { GtagCommand } from './constants';

/**
* Event parameters to set on 'gtag' during initialization.
*/
export let defaultEventParametersForInit: CustomParams | undefined;

/**
* Logs an analytics event through the Firebase SDK.
*
Expand Down Expand Up @@ -142,3 +148,15 @@ export async function setAnalyticsCollectionEnabled(
const measurementId = await initializationPromise;
window[`ga-disable-${measurementId}`] = !enabled;
}

/**
* Sets the variable `defaultEventParametersForInit` for use in the initialization of
* analytics.
*
* @param customParams Any custom params the user may pass to gtag.js.
*/
export function _setDefaultEventParametersForInit(
customParams?: CustomParams
): void {
defaultEventParametersForInit = customParams;
}
21 changes: 21 additions & 0 deletions packages/analytics/src/initialize-analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import { FirebaseApp } from '@firebase/app';
import { Deferred } from '@firebase/util';
import { _FirebaseInstallationsInternal } from '@firebase/installations';
import { removeGtagScript } from '../testing/gtag-script-util';
import { setDefaultEventParameters } from './api';
import { defaultEventParametersForInit } from './functions';

const fakeMeasurementId = 'abcd-efgh-ijkl';
const fakeFid = 'fid-1234-zyxw';
Expand Down Expand Up @@ -97,6 +99,25 @@ describe('initializeAnalytics()', () => {
'send_page_view': false
});
});
it('calls gtag set if there are default event parameters', async () => {
stubFetch();
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
setDefaultEventParameters(eventParametersForInit);
await _initializeAnalytics(
app,
dynamicPromisesList,
measurementIdToAppId,
fakeInstallations,
gtagStub,
'dataLayer'
);
expect(gtagStub).to.be.calledWith(GtagCommand.SET, eventParametersForInit);
// defaultEventParametersForInit is reset after initialization.
expect(defaultEventParametersForInit).to.equal(undefined);
});
it('puts dynamic fetch promise into dynamic promises list', async () => {
stubFetch();
await _initializeAnalytics(
Expand Down
11 changes: 11 additions & 0 deletions packages/analytics/src/initialize-analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ import {
import { ERROR_FACTORY, AnalyticsError } from './errors';
import { findGtagScriptOnPage, insertScriptTag } from './helpers';
import { AnalyticsSettings } from './public-types';
import {
defaultEventParametersForInit,
_setDefaultEventParametersForInit
} from './functions';

async function validateIndexedDB(): Promise<boolean> {
if (!isIndexedDBAvailable()) {
Expand Down Expand Up @@ -140,5 +144,12 @@ export async function _initializeAnalytics(
// Note: This will trigger a page_view event unless 'send_page_view' is set to false in
// `configProperties`.
gtagCore(GtagCommand.CONFIG, dynamicConfig.measurementId, configProperties);

// Detects if there is data that will be set on every event logged from the SDK.
if (defaultEventParametersForInit) {
gtagCore(GtagCommand.SET, defaultEventParametersForInit);
_setDefaultEventParametersForInit(undefined);
}

return dynamicConfig.measurementId;
}