Adds frontend events for Google Analytics.
VAN-282)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faCaretDown, faCaretRight } from '@fortawesome/free-solid-svg-icons';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
@@ -22,8 +23,13 @@ const LoginHelpLinks = (props) => {
|
||||
setShowLoginHelpValue(!showLoginHelp);
|
||||
};
|
||||
|
||||
const handleForgotPasswordLinkClickEvent = () => {
|
||||
sendTrackEvent('edx.bi.password-reset_form.toggled', { category: 'user-engagement' });
|
||||
};
|
||||
|
||||
const forgotPasswordLink = () => (
|
||||
<a className="field-link" href={RESET_PAGE}>
|
||||
|
||||
<a className="field-link" href={RESET_PAGE} onClick={handleForgotPasswordLinkClickEvent}>
|
||||
{intl.formatMessage(messages['forgot.password.link'])}
|
||||
</a>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import Skeleton from 'react-loading-skeleton';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
import { sendPageEvent, sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import {
|
||||
Form, Hyperlink, Input, StatefulButton, ValidationFormGroup,
|
||||
} from '@edx/paragon';
|
||||
@@ -58,6 +59,8 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
handleInstitutionLogin = () => {
|
||||
sendTrackEvent('edx.bi.institution_login_form.toggled', { category: 'user-engagement' });
|
||||
sendPageEvent('login_and_registration', 'institution_login');
|
||||
this.setState(prevState => ({ institutionLogin: !prevState.institutionLogin }));
|
||||
}
|
||||
|
||||
@@ -123,6 +126,10 @@ class LoginPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
handleCreateAccountLinkClickEvent() {
|
||||
sendTrackEvent('edx.bi.register_form.toggled', { category: 'user-engagement' });
|
||||
}
|
||||
|
||||
renderThirdPartyAuth(providers, secondaryProviders, currentProvider, thirdPartyAuthApiStatus, intl) {
|
||||
let thirdPartyComponent = null;
|
||||
if ((providers.length || secondaryProviders.length) && !currentProvider) {
|
||||
@@ -162,6 +169,8 @@ class LoginPage extends React.Component {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
sendPageEvent('login_and_registration', 'login');
|
||||
return (
|
||||
<>
|
||||
<RedirectLogistration
|
||||
@@ -185,7 +194,7 @@ class LoginPage extends React.Component {
|
||||
<div className="d-flex flex-row">
|
||||
<p>
|
||||
{intl.formatMessage(messages['first.time.here'])}
|
||||
<Hyperlink className="ml-1" destination={REGISTER_PAGE}>
|
||||
<Hyperlink className="ml-1" destination={REGISTER_PAGE} onClick={this.handleCreateAccountLinkClickEvent}>
|
||||
{intl.formatMessage(messages['create.an.account'])}.
|
||||
</Hyperlink>
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import * as analytics from '@edx/frontend-platform/analytics';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import LoginHelpLinks from '../LoginHelpLinks';
|
||||
@@ -11,6 +12,9 @@ jest.mock('@edx/frontend-platform', () => ({
|
||||
getConfig: jest.fn().mockReturnValue({ LOGIN_ISSUE_SUPPORT_LINK: otherSignInIssues }),
|
||||
}));
|
||||
|
||||
jest.mock('@edx/frontend-platform/analytics');
|
||||
analytics.sendTrackEvent = jest.fn();
|
||||
|
||||
describe('LoginHelpLinks', () => {
|
||||
let props = {};
|
||||
|
||||
|
||||
@@ -6,10 +6,16 @@ import configureStore from 'redux-mock-store';
|
||||
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
|
||||
import * as analytics from '@edx/frontend-platform/analytics';
|
||||
import LoginPage from '../LoginPage';
|
||||
import { RenderInstitutionButton } from '../../common-components';
|
||||
import { PENDING_STATE } from '../../data/constants';
|
||||
|
||||
jest.mock('@edx/frontend-platform/analytics');
|
||||
|
||||
analytics.sendTrackEvent = jest.fn();
|
||||
analytics.sendPageEvent = jest.fn();
|
||||
|
||||
const IntlLoginPage = injectIntl(LoginPage);
|
||||
const mockStore = configureStore();
|
||||
|
||||
@@ -278,4 +284,34 @@ describe('LoginPage', () => {
|
||||
loginPage.find(RenderInstitutionButton).simulate('click', { institutionLogin: true });
|
||||
expect(loginPage.text().includes('Test University')).toBe(true);
|
||||
});
|
||||
|
||||
it('send tracking event when create account link is clicked', () => {
|
||||
const loginPage = mount(reduxWrapper(<IntlLoginPage {...props} />));
|
||||
|
||||
loginPage.find('a[href*="/register"]').simulate('click');
|
||||
loginPage.update();
|
||||
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.register_form.toggled', { category: 'user-engagement' });
|
||||
});
|
||||
|
||||
it('send page event when login page is rendered', () => {
|
||||
mount(reduxWrapper(<IntlLoginPage {...props} />));
|
||||
expect(analytics.sendPageEvent).toHaveBeenCalledWith('login_and_registration', 'login');
|
||||
});
|
||||
|
||||
it('send tracking and page events when institutional button is clicked', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
commonComponents: {
|
||||
...initialState.commonComponents,
|
||||
thirdPartyAuthContext: {
|
||||
...initialState.commonComponents.thirdPartyAuthContext,
|
||||
secondaryProviders: [secondaryProviders],
|
||||
},
|
||||
},
|
||||
});
|
||||
const loginPage = mount(reduxWrapper(<IntlLoginPage {...props} />));
|
||||
loginPage.find(RenderInstitutionButton).simulate('click', { institutionLogin: true });
|
||||
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.institution_login_form.toggled', { category: 'user-engagement' });
|
||||
expect(analytics.sendPageEvent).toHaveBeenCalledWith('login_and_registration', 'institution_login');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
import PropTypes from 'prop-types';
|
||||
import { sendPageEvent, sendTrackEvent } from '@edx/frontend-platform/analytics';
|
||||
import {
|
||||
Input,
|
||||
StatefulButton,
|
||||
@@ -229,6 +230,7 @@ class RegistrationPage extends React.Component {
|
||||
this.setState({
|
||||
enableOptionalField: targetValue,
|
||||
});
|
||||
sendTrackEvent('edx.bi.user.register.optional_fields_selected', {});
|
||||
}
|
||||
|
||||
handleOnClick(e) {
|
||||
@@ -244,6 +246,10 @@ class RegistrationPage extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleLoginLinkClickEvent() {
|
||||
sendTrackEvent('edx.bi.login_form.toggled', { category: 'user-engagement' });
|
||||
}
|
||||
|
||||
validateInput(inputName, value) {
|
||||
const {
|
||||
errors,
|
||||
@@ -543,6 +549,7 @@ class RegistrationPage extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
sendPageEvent('login_and_registration', 'register');
|
||||
return (
|
||||
<>
|
||||
<RedirectLogistration
|
||||
@@ -563,7 +570,7 @@ class RegistrationPage extends React.Component {
|
||||
)}
|
||||
<div className="text-left">
|
||||
<span>{intl.formatMessage(messages['already.have.an.edx.account'])}</span>
|
||||
<a href={LOGIN_PAGE}>{intl.formatMessage(messages['sign.in.hyperlink'])}</a>
|
||||
<a href={LOGIN_PAGE} onClick={this.handleLoginLinkClickEvent}>{intl.formatMessage(messages['sign.in.hyperlink'])}</a>
|
||||
</div>
|
||||
{(providers.length || secondaryProviders.length || thirdPartyAuthApiStatus === PENDING_STATE)
|
||||
&& !currentProvider ? (
|
||||
|
||||
@@ -5,12 +5,18 @@ import { mount } from 'enzyme';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { IntlProvider, injectIntl, configure } from '@edx/frontend-platform/i18n';
|
||||
import * as analytics from '@edx/frontend-platform/analytics';
|
||||
|
||||
import RegistrationPage from '../RegistrationPage';
|
||||
import { RenderInstitutionButton } from '../../common-components';
|
||||
import { PENDING_STATE } from '../../data/constants';
|
||||
import { fetchRegistrationForm, fetchRealtimeValidations, registerNewUser } from '../data/actions';
|
||||
|
||||
jest.mock('@edx/frontend-platform/analytics');
|
||||
|
||||
analytics.sendTrackEvent = jest.fn();
|
||||
analytics.sendPageEvent = jest.fn();
|
||||
|
||||
const IntlRegistrationPage = injectIntl(RegistrationPage);
|
||||
const mockStore = configureStore();
|
||||
|
||||
@@ -141,6 +147,65 @@ describe('./RegistrationPage.js', () => {
|
||||
expect(registrationPage.find('RegistrationPage').state('enableOptionalField')).toEqual(true);
|
||||
});
|
||||
|
||||
it('send tracking event on optional checkbox enabled', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
logistration: {
|
||||
...initialState.logistration,
|
||||
formData: {
|
||||
fields: [
|
||||
{
|
||||
label: 'Tell us why you\'re interested in edX',
|
||||
name: 'goals',
|
||||
type: 'textarea',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
label: 'Highest level of Education completed.',
|
||||
name: 'level_of_education',
|
||||
type: 'select',
|
||||
options: [{ value: '', name: '--' }, { value: 'p', name: 'Doctorate' }],
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
label: 'Year of birth.',
|
||||
name: 'year_of_birth',
|
||||
type: 'select',
|
||||
options: [{ value: '', name: '--' }, { value: '2021', name: '2021' }],
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
label: 'Gender.',
|
||||
name: 'gender',
|
||||
type: 'select',
|
||||
options: [{ value: '', name: '--' }, { value: 'f', name: 'Female' }],
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
|
||||
registrationPage.find('input#optional').simulate('change', { target: { checked: true } });
|
||||
registrationPage.update();
|
||||
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.user.register.optional_fields_selected', {});
|
||||
});
|
||||
|
||||
it('send tracking event when login link is clicked', () => {
|
||||
const registrationPage = mount(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
|
||||
registrationPage.find('a[href*="/login"]').simulate('click');
|
||||
registrationPage.update();
|
||||
expect(analytics.sendTrackEvent).toHaveBeenCalledWith('edx.bi.login_form.toggled', { category: 'user-engagement' });
|
||||
});
|
||||
|
||||
it('send page event when register page is rendered', () => {
|
||||
mount(reduxWrapper(<IntlRegistrationPage {...props} />));
|
||||
expect(analytics.sendPageEvent).toHaveBeenCalledWith('login_and_registration', 'register');
|
||||
});
|
||||
|
||||
it('should show optional fields section on optional check enabled', () => {
|
||||
store = mockStore({
|
||||
...initialState,
|
||||
|
||||
@@ -27,6 +27,7 @@ exports[`./RegistrationPage.js should display no password field when current pro
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
@@ -218,6 +219,7 @@ exports[`./RegistrationPage.js should match TPA provider snapshot 1`] = `
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
@@ -473,6 +475,7 @@ exports[`./RegistrationPage.js should match default section snapshot 1`] = `
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
@@ -693,6 +696,7 @@ exports[`./RegistrationPage.js should match pending button state snapshot 1`] =
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
@@ -948,6 +952,7 @@ exports[`./RegistrationPage.js should show error message on 409 1`] = `
|
||||
</span>
|
||||
<a
|
||||
href="/login"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Sign in.
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user