Skip to content

Commit

Permalink
feat: add optimizely event for xpert upgrade (#81)
Browse files Browse the repository at this point in the history
* feat: add optimizely event for xpert upgrade

* fix: update for lint errors
  • Loading branch information
alangsto authored Jan 31, 2025
1 parent 95be27c commit 2a667bf
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/components/Sidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
IconButton,
} from '@openedx/paragon';
import { Close } from '@openedx/paragon/icons';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';

import showSurvey from '../../utils/surveyMonkey';

Expand All @@ -17,6 +18,7 @@ import MessageForm from '../MessageForm';
import UpgradePanel from '../UpgradePanel';
import { useCourseUpgrade, useTrackEvent } from '../../hooks';
import { ReactComponent as XpertLogo } from '../../assets/xpert-logo.svg';
import { trackUpgradeButtonClickedOptimizely } from '../../utils/optimizelyExperiment';
import './Sidebar.scss';

const Sidebar = ({
Expand Down Expand Up @@ -50,7 +52,16 @@ const Sidebar = ({
);

const handleUpgradeLinkClick = () => {
const { userId } = getAuthenticatedUser();
trackUpgradeButtonClickedOptimizely(userId.toString());

track('edx.ui.lms.learning_assistant.days_remaining_banner_upgrade_click');
track('edx.bi.ecommerce.upsell_links_clicked', {
linkCategory: 'xpert_learning_assistant',
linkName: 'xpert_days_remaining_banner',
linkType: 'button',
pageName: 'in_course',
});
};

const getUpgradeLink = () => (
Expand Down
16 changes: 16 additions & 0 deletions src/components/Sidebar/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { render as renderComponent } from '../../utils/utils.test';
import { initialState } from '../../data/slice';
import showSurvey from '../../utils/surveyMonkey';
import { trackUpgradeButtonClickedOptimizely } from '../../utils/optimizelyExperiment';

import Sidebar from '.';

Expand All @@ -18,6 +19,10 @@ jest.mock('../../hooks', () => ({

jest.mock('../../utils/surveyMonkey', () => jest.fn());

jest.mock('../../utils/optimizelyExperiment', () => ({
trackUpgradeButtonClickedOptimizely: jest.fn(),
}));

jest.mock('@edx/frontend-platform/analytics', () => ({
sendTrackEvent: jest.fn(),
}));
Expand Down Expand Up @@ -130,7 +135,18 @@ describe('<Sidebar />', () => {
const upgradeLink = screen.queryByTestId('days_remaining_banner_upgrade_link');
expect(mockedTrackEvent).not.toHaveBeenCalled();
fireEvent.click(upgradeLink);

expect(trackUpgradeButtonClickedOptimizely).toHaveBeenCalled();
expect(mockedTrackEvent).toHaveBeenCalledWith('edx.ui.lms.learning_assistant.days_remaining_banner_upgrade_click');
expect(mockedTrackEvent).toHaveBeenCalledWith(
'edx.bi.ecommerce.upsell_links_clicked',
{
linkCategory: 'xpert_learning_assistant',
linkName: 'xpert_days_remaining_banner',
linkType: 'button',
pageName: 'in_course',
},
);
});

it('If auditTrialDaysRemaining < 1, do not show either of those', () => {
Expand Down
16 changes: 15 additions & 1 deletion src/components/UpgradeButton/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,29 @@ import React from 'react';

import { Button, Icon } from '@openedx/paragon';
import { LockOpen } from '@openedx/paragon/icons';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';

import { useCourseUpgrade, useTrackEvent } from '../../hooks';
import { trackUpgradeButtonClickedOptimizely } from '../../utils/optimizelyExperiment';

import './UpgradeButton.scss';

const UpgradeButton = ({ includeLockIcon, trackingEventName }) => {
const { upgradeUrl } = useCourseUpgrade();
const { track } = useTrackEvent();

const handleClick = () => track(trackingEventName);
const handleClick = () => {
const { userId } = getAuthenticatedUser();
trackUpgradeButtonClickedOptimizely(userId.toString());

track(trackingEventName);
track('edx.bi.ecommerce.upsell_links_clicked', {
linkCategory: 'xpert_learning_assistant',
linkName: 'xpert_upgrade_panel',
linkType: 'button',
pageName: 'in_course',
});
};

return (
<Button
Expand Down
21 changes: 21 additions & 0 deletions src/components/UpgradeButton/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { render } from '../../utils/utils.test';
import { useCourseUpgrade, useTrackEvent } from '../../hooks';
import { trackUpgradeButtonClickedOptimizely } from '../../utils/optimizelyExperiment';

import UpgradeButton from '.';

Expand All @@ -10,6 +11,15 @@ jest.mock('../../hooks', () => ({
useTrackEvent: jest.fn(),
}));

jest.mock('../../utils/optimizelyExperiment', () => ({
trackUpgradeButtonClickedOptimizely: jest.fn(),
}));

const mockedAuthenticatedUser = { userId: 1 };
jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedUser: () => mockedAuthenticatedUser,
}));

describe('UpgradeButton', () => {
beforeEach(() => {
useCourseUpgrade.mockReturnValue({ upgradeUrl: 'www.test.com' });
Expand All @@ -32,7 +42,18 @@ describe('UpgradeButton', () => {
const upgradeCta = screen.queryByTestId('upgrade-cta');
expect(mockedTrackEvent).not.toHaveBeenCalled();
fireEvent.click(upgradeCta);

expect(trackUpgradeButtonClickedOptimizely).toHaveBeenCalled();
expect(mockedTrackEvent).toHaveBeenCalledWith('test.tracking');
expect(mockedTrackEvent).toHaveBeenCalledWith(
'edx.bi.ecommerce.upsell_links_clicked',
{
linkCategory: 'xpert_learning_assistant',
linkName: 'xpert_upgrade_panel',
linkType: 'button',
pageName: 'in_course',
},
);
});

it('should render lock icon', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/data/thunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';

import { camelCaseObject } from '@edx/frontend-platform';
import trackChatBotMessageOptimizely from '../utils/optimizelyExperiment';
import { trackChatBotMessageOptimizely } from '../utils/optimizelyExperiment';
import {
fetchChatResponse,
fetchLearningAssistantChatSummary,
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/use-track-event.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useContext } from 'react';
import { useModel } from '@src/generic/model-store'; // eslint-disable-line import/no-unresolved
import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { CourseInfoContext } from '../context';
Expand All @@ -16,11 +17,13 @@ import { CourseInfoContext } from '../context';
*/
export default function useTrackEvent() {
const { courseId, moduleId } = useContext(CourseInfoContext);
const { org } = useModel('courseHomeMeta', courseId);
const { userId } = getAuthenticatedUser();

const track = (event, details) => {
sendTrackEvent(event, {
course_id: courseId,
org_key: org,
user_id: userId,
module_id: moduleId,
...details,
Expand Down
5 changes: 5 additions & 0 deletions src/hooks/use-track-event.test.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { renderHook as rtlRenderHook } from '@testing-library/react-hooks';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { useModel } from '@src/generic/model-store'; // eslint-disable-line import/no-unresolved
import { CourseInfoProvider } from '../context';

import useTrackEvent from './use-track-event';

const mockedUserId = 123;
const mockedCourseId = 'some-course-id';
const mockedModuleId = 'some-module-id';
const mockedOrg = 'org';

jest.mock('@edx/frontend-platform/analytics', () => ({
sendTrackEvent: jest.fn(),
Expand All @@ -17,6 +19,8 @@ jest.mock('@edx/frontend-platform/auth', () => ({
getAuthenticatedUser: () => mockedAuthenticatedUser,
}));

useModel.mockImplementation(() => ({ org: mockedOrg }));

const contextWrapper = ({ courseInfo }) => function Wrapper({ children }) { // eslint-disable-line react/prop-types
return (
<CourseInfoProvider value={courseInfo}>
Expand Down Expand Up @@ -47,6 +51,7 @@ describe('useTrackEvent()', () => {
expect(sendTrackEvent).toHaveBeenCalledWith(eventLabel, {
course_id: mockedCourseId,
user_id: mockedUserId,
org_key: mockedOrg,
module_id: mockedModuleId,
some_extra_prop: 42,
});
Expand Down
15 changes: 14 additions & 1 deletion src/utils/optimizelyExperiment.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,17 @@ const trackChatBotMessageOptimizely = (userId, userAttributes = {}) => {
});
};

export default trackChatBotMessageOptimizely;
const trackUpgradeButtonClickedOptimizely = (userId, userAttributes = {}) => {
const optimizelyInstance = getOptimizely();

if (!optimizelyInstance || Object.keys(optimizelyInstance).length === 0) { return; }

optimizelyInstance.onReady().then(() => {
optimizelyInstance.track('upgrade_button_click', userId, userAttributes);
});
};

export {
trackChatBotMessageOptimizely,
trackUpgradeButtonClickedOptimizely,
};

0 comments on commit 2a667bf

Please sign in to comment.