Skip to content
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

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

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
dwyfrequency marked this conversation as resolved.
Show resolved Hide resolved
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 one.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@egilmorez Can you review the text here? This comment here should be the only text that will end up in the reference docs.

From me:

  • one => ones
  • In "gtag's set command" the "set" should be in quotes or backticks, I think quotes because it's a string not a var

* By using gtag's set command, the values passed persist on the current page and are passed with
* all subsequent events.
*
* @param customParams Any custom params the user may pass to gtag.js.
dwyfrequency marked this conversation as resolved.
Show resolved Hide resolved
*/
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
25 changes: 24 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,25 @@ 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() adds new params correctly', async () => {
const eventParametersForInit = {
'github_user': 'dwyfrequency',
'company': 'google'
};
const additionalParams = { 'food': 'sushi' };
_setDefaultEventParametersForInit(eventParametersForInit);
_setDefaultEventParametersForInit(additionalParams);
expect(defaultEventParametersForInit).to.deep.equal({
...eventParametersForInit,
...additionalParams
});
});
});
25 changes: 25 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,22 @@ export async function setAnalyticsCollectionEnabled(
const measurementId = await initializationPromise;
window[`ga-disable-${measurementId}`] = !enabled;
}

/**
* Sets the variable {@link defaultEventParametersForInit} for use in the initialization of
dwyfrequency marked this conversation as resolved.
Show resolved Hide resolved
* analytics.
*
* @param customParams Any custom params the user may pass to gtag.js.
*/
export function _setDefaultEventParametersForInit(
customParams: CustomParams
): void {
if (defaultEventParametersForInit) {
defaultEventParametersForInit = {
dwyfrequency marked this conversation as resolved.
Show resolved Hide resolved
...defaultEventParametersForInit,
...customParams
};
} else {
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,7 @@ 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';

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

async function validateIndexedDB(): Promise<boolean> {
if (!isIndexedDBAvailable()) {
Expand Down Expand Up @@ -140,5 +141,11 @@ 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);
dwyfrequency marked this conversation as resolved.
Show resolved Hide resolved
}

return dynamicConfig.measurementId;
}