зеркало из https://github.com/mozilla/fxa.git
feat(metrics): add "deeplink" 3rd party auth Glean events
This commit is contained in:
Родитель
9d3ebf8392
Коммит
81718a0a6e
|
@ -18,6 +18,7 @@ import { accountsEvents } from './pings';
|
|||
import * as reg from './reg';
|
||||
import { oauthClientId, service } from './relyingParty';
|
||||
import { deviceType, entrypoint, flowId } from './session';
|
||||
import * as thirdPartyAuth from './thirdPartyAuth';
|
||||
import * as thirdPartyAuthSetPassword from './thirdPartyAuthSetPassword';
|
||||
import * as utm from './utm';
|
||||
|
||||
|
@ -281,6 +282,12 @@ const recordEventMetric = (eventName: string, properties: EventProperties) => {
|
|||
case 'third_party_auth_set_password_success':
|
||||
thirdPartyAuthSetPassword.success.record();
|
||||
break;
|
||||
case 'google_deeplink':
|
||||
thirdPartyAuth.googleDeeplink.record();
|
||||
break;
|
||||
case 'apple_deeplink':
|
||||
thirdPartyAuth.appleDeeplink.record();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -339,6 +346,25 @@ export const GleanMetrics = {
|
|||
Glean.setUploadEnabled(gleanEnabled);
|
||||
},
|
||||
|
||||
/**
|
||||
* The ping calls are awaited internally for ease of use and that works in
|
||||
* most cases. But in the scenario where we want to wait for the pings to
|
||||
* finish before we unload the page, we are doing so, crudely, here. Do not
|
||||
* emit more pings after calling this function.
|
||||
*/
|
||||
isDone: () =>
|
||||
new Promise((resolve) => {
|
||||
const checkForEmptyFnList = () => {
|
||||
if (lambdas.length === 0) {
|
||||
resolve(undefined);
|
||||
} else {
|
||||
setTimeout(checkForEmptyFnList, lambdas.length * 5);
|
||||
}
|
||||
};
|
||||
|
||||
checkForEmptyFnList();
|
||||
}),
|
||||
|
||||
emailFirst: {
|
||||
view: createEventFn('email_first_view'),
|
||||
appleOauthStart: createEventFn('apple_oauth_email_first_start'),
|
||||
|
@ -412,6 +438,10 @@ export const GleanMetrics = {
|
|||
submit: createEventFn('third_party_auth_set_password_submit'),
|
||||
success: createEventFn('third_party_auth_set_password_success'),
|
||||
},
|
||||
thirdPartyAuth: {
|
||||
googleDeeplink: createEventFn('google_deeplink'),
|
||||
appleDeeplink: createEventFn('apple_deeplink'),
|
||||
},
|
||||
};
|
||||
|
||||
export default GleanMetrics;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// AUTOGENERATED BY glean_parser v14.1.2. DO NOT EDIT. DO NOT COMMIT.
|
||||
|
||||
import EventMetricType from '@mozilla/glean/private/metrics/event';
|
||||
|
||||
/**
|
||||
* User sees Apple link and bypasses Mozilla Accounts email first/login
|
||||
* screens (relevant for Pocket)
|
||||
*
|
||||
* Generated from `third_party_auth.apple_deeplink`.
|
||||
*/
|
||||
export const appleDeeplink = new EventMetricType(
|
||||
{
|
||||
category: 'third_party_auth',
|
||||
name: 'apple_deeplink',
|
||||
sendInPings: ['events'],
|
||||
lifetime: 'ping',
|
||||
disabled: false,
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
/**
|
||||
* User sees Google link and bypasses Mozilla Accounts email first/login
|
||||
* screens (relevant for Pocket)
|
||||
*
|
||||
* Generated from `third_party_auth.google_deeplink`.
|
||||
*/
|
||||
export const googleDeeplink = new EventMetricType(
|
||||
{
|
||||
category: 'third_party_auth',
|
||||
name: 'google_deeplink',
|
||||
sendInPings: ['events'],
|
||||
lifetime: 'ping',
|
||||
disabled: false,
|
||||
},
|
||||
[]
|
||||
);
|
|
@ -31,14 +31,22 @@ export default {
|
|||
const params = new URLSearchParams(this.window.location.search);
|
||||
if (params.get('deeplink') === 'googleLogin') {
|
||||
this.logFlowEvent('google.deeplink');
|
||||
return new Promise(() => {
|
||||
this.googleSignIn();
|
||||
});
|
||||
GleanMetrics.thirdPartyAuth.googleDeeplink();
|
||||
return GleanMetrics.isDone().then(
|
||||
() =>
|
||||
new Promise(() => {
|
||||
this.googleSignIn();
|
||||
})
|
||||
);
|
||||
} else if (params.get('deeplink') === 'appleLogin') {
|
||||
this.logFlowEvent('apple.deeplink');
|
||||
return new Promise(() => {
|
||||
this.appleSignIn();
|
||||
});
|
||||
GleanMetrics.thirdPartyAuth.appleDeeplink();
|
||||
return GleanMetrics.isDone().then(
|
||||
() =>
|
||||
new Promise(() => {
|
||||
this.appleSignIn();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Check to see if this page is being redirected to at the end of a
|
||||
|
|
|
@ -107,12 +107,14 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('does not submit a ping on an event', async () => {
|
||||
await GleanMetrics.registration.view();
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.notCalled(submitPingStub);
|
||||
});
|
||||
|
||||
it('does not set the metrics values', async () => {
|
||||
await GleanMetrics.registration.view();
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
|
||||
sinon.assert.notCalled(setOauthClientIdStub);
|
||||
sinon.assert.notCalled(setServiceStub);
|
||||
|
@ -134,7 +136,8 @@ describe('lib/glean', () => {
|
|||
const config = { ...mockConfig, enabled: true };
|
||||
const initStub = sandbox.stub(Glean, 'initialize').throws();
|
||||
GleanMetrics.initialize(config, { metrics, relier, user, userAgent });
|
||||
await GleanMetrics.registration.view();
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(initStub);
|
||||
assert.isFalse(config.enabled);
|
||||
// does not try to set a value since internal enabled state is false
|
||||
|
@ -321,7 +324,8 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('email first', () => {
|
||||
it('submits a ping with the email_first_view event name', async () => {
|
||||
await GleanMetrics.emailFirst.view();
|
||||
GleanMetrics.emailFirst.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'email_first_view');
|
||||
});
|
||||
|
@ -329,7 +333,8 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('apple oauth email first', () => {
|
||||
it('submits a ping with the apple_oauth_email_first_start event name', async () => {
|
||||
await GleanMetrics.emailFirst.appleOauthStart();
|
||||
GleanMetrics.emailFirst.appleOauthStart();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -340,7 +345,8 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('google oauth email first', () => {
|
||||
it('submits a ping with the google_oauth_email_first_start event name', async () => {
|
||||
await GleanMetrics.emailFirst.googleOauthStart();
|
||||
GleanMetrics.emailFirst.googleOauthStart();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -351,19 +357,22 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('registration', () => {
|
||||
it('submits a ping with the reg_view event name', async () => {
|
||||
await GleanMetrics.registration.view();
|
||||
GleanMetrics.registration.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'reg_view');
|
||||
});
|
||||
|
||||
it('submits a ping with the reg_submit event name', async () => {
|
||||
await GleanMetrics.registration.submit();
|
||||
GleanMetrics.registration.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'reg_submit');
|
||||
});
|
||||
|
||||
it('submits a ping with the reg_submit_success event name', async () => {
|
||||
await GleanMetrics.registration.success();
|
||||
GleanMetrics.registration.success();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'reg_submit_success');
|
||||
});
|
||||
|
@ -371,13 +380,15 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('signup confirmation code', () => {
|
||||
it('submits a ping with the reg_signup_code_view event name', async () => {
|
||||
await GleanMetrics.signupConfirmation.view();
|
||||
GleanMetrics.signupConfirmation.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'reg_signup_code_view');
|
||||
});
|
||||
|
||||
it('submits a ping with the reg_signup_code_submit event name', async () => {
|
||||
await GleanMetrics.signupConfirmation.submit();
|
||||
GleanMetrics.signupConfirmation.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'reg_signup_code_submit');
|
||||
});
|
||||
|
@ -385,7 +396,8 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('loginConfirmation', () => {
|
||||
it('submits a ping with the login_email_confirmation_view event name', async () => {
|
||||
await GleanMetrics.loginConfirmation.view();
|
||||
GleanMetrics.loginConfirmation.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -394,7 +406,8 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('submits a ping with the reg_submit event name', async () => {
|
||||
await GleanMetrics.loginConfirmation.submit();
|
||||
GleanMetrics.loginConfirmation.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -405,19 +418,22 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('totpForm', () => {
|
||||
it('submits a ping with the login_totp_form_view event name', async () => {
|
||||
await GleanMetrics.totpForm.view();
|
||||
GleanMetrics.totpForm.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'login_totp_form_view');
|
||||
});
|
||||
|
||||
it('submits a ping with the login_totp_code_submit event name', async () => {
|
||||
await GleanMetrics.totpForm.submit();
|
||||
GleanMetrics.totpForm.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'login_totp_code_submit');
|
||||
});
|
||||
|
||||
it('submits a ping with the login_totp_code_success_view event name', async () => {
|
||||
await GleanMetrics.totpForm.success();
|
||||
GleanMetrics.totpForm.success();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -426,27 +442,47 @@ describe('lib/glean', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('thirdPartyAuth', () => {
|
||||
it('submits a ping with the google_deeplink event name', async () => {
|
||||
GleanMetrics.thirdPartyAuth.googleDeeplink();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'google_deeplink');
|
||||
});
|
||||
|
||||
it('submits a ping with the apple_deeplink event name', async () => {
|
||||
GleanMetrics.thirdPartyAuth.appleDeeplink();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'apple_deeplink');
|
||||
});
|
||||
});
|
||||
|
||||
describe('login', () => {
|
||||
it('submits a ping with the login_view event name', () => {
|
||||
it('submits a ping with the login_view event name', async () => {
|
||||
GleanMetrics.login.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'login_view');
|
||||
});
|
||||
|
||||
it('submits a ping with the login_submit event name', () => {
|
||||
it('submits a ping with the login_submit event name', async () => {
|
||||
GleanMetrics.login.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'login_submit');
|
||||
});
|
||||
|
||||
it('submits a ping with the login_submit_success event name', () => {
|
||||
it('submits a ping with the login_submit_success event name', async () => {
|
||||
GleanMetrics.login.success();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(setEventNameStub, 'login_submit_success');
|
||||
});
|
||||
|
||||
it('submits a ping with the login_submit_frontend_error event name and a reason', () => {
|
||||
it('submits a ping with the login_submit_frontend_error event name and a reason', async () => {
|
||||
GleanMetrics.login.error({ reason: 'quux' });
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -459,7 +495,8 @@ describe('lib/glean', () => {
|
|||
|
||||
describe('third_party_auth_set_password', () => {
|
||||
it('submits a ping with the third_party_auth_set_password_view event name', async () => {
|
||||
await GleanMetrics.setPasswordThirdPartyAuth.view();
|
||||
GleanMetrics.setPasswordThirdPartyAuth.view();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -468,7 +505,8 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('submits a ping with the third_party_auth_set_password_engage event name', async () => {
|
||||
await GleanMetrics.setPasswordThirdPartyAuth.engage();
|
||||
GleanMetrics.setPasswordThirdPartyAuth.engage();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -477,7 +515,8 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('submits a ping with the third_party_auth_set_password_submit event name', async () => {
|
||||
await GleanMetrics.setPasswordThirdPartyAuth.submit();
|
||||
GleanMetrics.setPasswordThirdPartyAuth.submit();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
@ -486,7 +525,8 @@ describe('lib/glean', () => {
|
|||
});
|
||||
|
||||
it('submits a ping with the third_party_auth_set_password_success event name', async () => {
|
||||
await GleanMetrics.setPasswordThirdPartyAuth.success();
|
||||
GleanMetrics.setPasswordThirdPartyAuth.success();
|
||||
await GleanMetrics.isDone();
|
||||
sinon.assert.calledOnce(setEventNameStub);
|
||||
sinon.assert.calledWith(
|
||||
setEventNameStub,
|
||||
|
|
|
@ -10,6 +10,7 @@ import sinon from 'sinon';
|
|||
import ThirdPartyAuthMixin from 'views/mixins/third-party-auth-mixin';
|
||||
import Notifier from 'lib/channels/notifier';
|
||||
import Metrics from 'lib/metrics';
|
||||
import GleanMetrics from '../../../../scripts/lib/glean';
|
||||
import SentryMetrics from 'lib/sentry';
|
||||
import WindowMock from '../../../mocks/window';
|
||||
import Storage from 'lib/storage';
|
||||
|
@ -83,9 +84,16 @@ describe('views/mixins/third-party-auth-mixin', function () {
|
|||
flowBeginTime: '456',
|
||||
deviceId: '789',
|
||||
}));
|
||||
sinon.stub(GleanMetrics.thirdPartyAuth, 'appleDeeplink');
|
||||
sinon.stub(GleanMetrics.thirdPartyAuth, 'googleDeeplink');
|
||||
await view.render();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
GleanMetrics.thirdPartyAuth.appleDeeplink.restore();
|
||||
GleanMetrics.thirdPartyAuth.googleDeeplink.restore();
|
||||
});
|
||||
|
||||
describe('beforeRender', () => {
|
||||
beforeEach(() => {
|
||||
sinon.spy(view, 'logViewEvent');
|
||||
|
@ -124,16 +132,26 @@ describe('views/mixins/third-party-auth-mixin', function () {
|
|||
|
||||
it('google login deeplink', () => {
|
||||
windowMock.location.search = '?deeplink=googleLogin';
|
||||
view.beforeRender();
|
||||
assert.isTrue(view.googleSignIn.calledOnce);
|
||||
assert.isTrue(view.logFlowEvent.calledOnceWith('google.deeplink'));
|
||||
view
|
||||
.beforeRender()
|
||||
.then(() => {
|
||||
assert.isTrue(view.googleSignIn.calledOnce);
|
||||
assert.isTrue(view.logFlowEvent.calledOnceWith('google.deeplink'));
|
||||
assert.isTrue(GleanMetrics.thirdPartyAuth.googleDeeplink.calledOnce);
|
||||
})
|
||||
.catch(() => assert.fail());
|
||||
});
|
||||
|
||||
it('apple login deeplink', () => {
|
||||
windowMock.location.search = '?deeplink=appleLogin';
|
||||
view.beforeRender();
|
||||
assert.isTrue(view.appleSignIn.calledOnce);
|
||||
assert.isTrue(view.logFlowEvent.calledOnceWith('apple.deeplink'));
|
||||
view
|
||||
.beforeRender()
|
||||
.then(() => {
|
||||
assert.isTrue(view.appleSignIn.calledOnce);
|
||||
assert.isTrue(view.logFlowEvent.calledOnceWith('apple.deeplink'));
|
||||
assert.isTrue(GleanMetrics.thirdPartyAuth.appleDeeplink.calledOnce);
|
||||
})
|
||||
.catch(() => assert.fail());
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ export const GleanMetrics: Pick<
|
|||
if (lambdas.length === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(checkForEmptyFnList, 100);
|
||||
setTimeout(checkForEmptyFnList, lambdas.length * 5);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1519,7 +1519,45 @@ cad:
|
|||
expires: never
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
|
||||
third_party_auth:
|
||||
apple_deeplink:
|
||||
type: event
|
||||
description: |
|
||||
User clicked Apple Signin link from an RP hosted site and is taken
|
||||
directly to Apple authentication flow, bypassing Mozilla Accounts email
|
||||
first page.
|
||||
send_in_pings:
|
||||
- events
|
||||
notification_emails:
|
||||
- vzare@mozilla.com
|
||||
- fxa-staff@mozilla.com
|
||||
bugs:
|
||||
- https://mozilla-hub.atlassian.net/browse/FXA-9116
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1830504
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1844121
|
||||
expires: never
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
google_deeplink:
|
||||
type: event
|
||||
description: |
|
||||
User clicked Google Signin link from an RP hosted site and is taken
|
||||
directly to Google authentication flow, bypassing Mozilla Accounts email
|
||||
first page.
|
||||
send_in_pings:
|
||||
- events
|
||||
notification_emails:
|
||||
- vzare@mozilla.com
|
||||
- fxa-staff@mozilla.com
|
||||
bugs:
|
||||
- https://mozilla-hub.atlassian.net/browse/FXA-9116
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1830504
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1844121
|
||||
expires: never
|
||||
data_sensitivity:
|
||||
- interaction
|
||||
third_party_auth_set_password:
|
||||
view:
|
||||
type: event
|
||||
|
|
Загрузка…
Ссылка в новой задаче