AA-711: implement upsell click events (#392)

This commit is contained in:
Carla Duarte
2021-03-16 16:10:47 -04:00
committed by GitHub
parent ab98cca421
commit 45a68973b7
6 changed files with 134 additions and 5 deletions

View File

@@ -35,7 +35,7 @@ Factory.define('outlineTabData')
}))
.attrs({
access_expiration: null,
can_show_upgrade_sock: true,
can_show_upgrade_sock: false,
course_goals: {
goal_options: [],
selected_goal: null,

View File

@@ -354,7 +354,7 @@ Object {
"outline": Object {
"course-v1:edX+DemoX+Demo_Course_1": Object {
"accessExpiration": null,
"canShowUpgradeSock": true,
"canShowUpgradeSock": false,
"courseBlocks": Object {
"courses": Object {
"block-v1:edX+DemoX+Demo_Course+type@course+block@bcdabcdabcdabcdabcdabcdabcdabcd3": Object {

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { Factory } from 'rosie';
import { getConfig } from '@edx/frontend-platform';
import { sendTrackEvent, sendTrackingLogEvent } from '@edx/frontend-platform/analytics';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import MockAdapter from 'axios-mock-adapter';
import userEvent from '@testing-library/user-event';
@@ -661,4 +662,79 @@ describe('Outline Tab', () => {
expect(screen.queryByText('Onboarding profile review, including identity verification, can take 2+ business days.')).not.toBeInTheDocument();
});
});
describe('Upgrade Card', () => {
it('renders title when upgrade is available', async () => {
await fetchAndRender();
expect(screen.queryByRole('heading', { name: 'Pursue a verified certificate' })).toBeInTheDocument();
});
it('displays link to upgrade', async () => {
await fetchAndRender();
expect(screen.getByRole('link', { name: 'Upgrade ($149)' })).toBeInTheDocument();
});
it('viewing upgrade card sends analytics', async () => {
sendTrackEvent.mockClear();
sendTrackingLogEvent.mockClear();
await fetchAndRender();
expect(sendTrackEvent).toHaveBeenCalledTimes(1);
expect(sendTrackEvent).toHaveBeenCalledWith('Promotion Viewed', {
org_key: 'edX',
courserun_key: courseId,
creative: 'sidebarupsell',
name: 'In-Course Verification Prompt',
position: 'sidebar-message',
promotion_id: 'courseware_verified_certificate_upsell',
});
expect(sendTrackingLogEvent).toHaveBeenCalledTimes(1);
expect(sendTrackingLogEvent).toHaveBeenCalledWith('edx.bi.course.upgrade.sidebarupsell.displayed', {
org_key: 'edX',
courserun_key: courseId,
});
});
it('clicking upgrade link sends analytics', async () => {
sendTrackEvent.mockClear();
sendTrackingLogEvent.mockClear();
await fetchAndRender();
const upgradeButton = screen.getByRole('link', { name: 'Upgrade ($149)' });
fireEvent.click(upgradeButton);
// 3 sendTrackEvent calls are expected because 1 happens on render, and 2 happen onClick
expect(sendTrackEvent).toHaveBeenCalledTimes(3);
expect(sendTrackEvent).toHaveBeenNthCalledWith(2, 'Promotion Clicked', {
org_key: 'edX',
courserun_key: courseId,
creative: 'sidebarupsell',
name: 'In-Course Verification Prompt',
position: 'sidebar-message',
promotion_id: 'courseware_verified_certificate_upsell',
});
expect(sendTrackEvent).toHaveBeenNthCalledWith(3, 'edx.bi.ecommerce.upsell_links_clicked', {
org_key: 'edX',
courserun_key: courseId,
linkCategory: 'green_upgrade',
linkName: 'course_home_green',
linkType: 'button',
pageName: 'course_home',
});
// 3 sendTrackingLogEvent calls are expected because 1 happens on render, and 2 happen onClick
expect(sendTrackingLogEvent).toHaveBeenCalledTimes(3);
expect(sendTrackingLogEvent).toHaveBeenNthCalledWith(2, 'edx.bi.course.upgrade.sidebarupsell.clicked', {
org_key: 'edX',
courserun_key: courseId,
});
expect(sendTrackingLogEvent).toHaveBeenNthCalledWith(3, 'edx.course.enrollment.upgrade.clicked', {
org_key: 'edX',
courserun_key: courseId,
location: 'sidebar-message',
});
});
});
});

View File

@@ -37,7 +37,7 @@ function UpgradeCard({ courseId, intl, onLearnMore }) {
useEffect(() => {
sendTrackingLogEvent('edx.bi.course.upgrade.sidebarupsell.displayed', eventProperties);
sendTrackEvent('Promotion Viewed', promotionEventProperties);
});
}, []);
const logClick = () => {
sendTrackingLogEvent('edx.bi.course.upgrade.sidebarupsell.clicked', eventProperties);
@@ -46,6 +46,13 @@ function UpgradeCard({ courseId, intl, onLearnMore }) {
location: 'sidebar-message',
});
sendTrackEvent('Promotion Clicked', promotionEventProperties);
sendTrackEvent('edx.bi.ecommerce.upsell_links_clicked', {
...eventProperties,
linkCategory: 'green_upgrade',
linkName: 'course_home_green',
linkType: 'button',
pageName: 'course_home',
});
};
return (

View File

@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faLock } from '@fortawesome/free-solid-svg-icons';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import messages from './messages';
@@ -14,6 +15,7 @@ function LockPaywall({
}) {
const course = useModel('coursewareMeta', courseId);
const {
org,
verifiedMode,
} = course;
@@ -25,6 +27,21 @@ function LockPaywall({
price,
upgradeUrl,
} = verifiedMode;
const eventProperties = {
org_key: org,
courserun_key: courseId,
};
const logClick = () => {
sendTrackEvent('edx.bi.ecommerce.upsell_links_clicked', {
...eventProperties,
linkCategory: '(none)',
linkName: 'in_course_upgrade',
linkType: 'link',
pageName: 'in_course',
});
};
return (
<div className="border border-gray rounded d-flex justify-content-between mt-2 p-3">
<div>
@@ -35,7 +52,7 @@ function LockPaywall({
<p className="mb-0">
<span>{intl.formatMessage(messages['learn.lockPaywall.content'])}</span>
&nbsp;
<a className="lock_paywall_upgrade_link" href={upgradeUrl}>
<a className="lock_paywall_upgrade_link" href={upgradeUrl} onClick={logClick}>
{intl.formatMessage(messages['learn.lockPaywall.upgrade.link'], {
currencySymbol,
price,

View File

@@ -1,8 +1,14 @@
import React from 'react';
import { Factory } from 'rosie';
import { initializeTestStore, render, screen } from '../../../../setupTest';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import {
fireEvent, initializeTestStore, render, screen,
} from '../../../../setupTest';
import LockPaywall from './LockPaywall';
jest.mock('@edx/frontend-platform/analytics');
describe('Lock Paywall', () => {
let store;
const mockData = {};
@@ -33,6 +39,29 @@ describe('Lock Paywall', () => {
expect(upgradeLink).toHaveAttribute('href', `${upgradeUrl}`);
});
it('sends analytics event onClick of unlock link', () => {
sendTrackEvent.mockClear();
const {
currencySymbol,
price,
} = store.getState().models.coursewareMeta[mockData.courseId].verifiedMode;
render(<LockPaywall {...mockData} />);
const upgradeLink = screen.getByRole('link', { name: `Upgrade to unlock (${currencySymbol}${price})` });
fireEvent.click(upgradeLink);
expect(sendTrackEvent).toHaveBeenCalledTimes(1);
expect(sendTrackEvent).toHaveBeenCalledWith('edx.bi.ecommerce.upsell_links_clicked', {
org_key: 'edX',
courserun_key: mockData.courseId,
linkCategory: '(none)',
linkName: 'in_course_upgrade',
linkType: 'link',
pageName: 'in_course',
});
});
it('does not display anything if course does not have verified mode', async () => {
const courseMetadata = Factory.build('courseMetadata', { verified_mode: null });
const testStore = await initializeTestStore({ courseMetadata, excludeFetchSequence: true }, false);