Skip to content

Commit

Permalink
VPN-5547: Implement subscription management telemetry (#8838)
Browse files Browse the repository at this point in the history
  • Loading branch information
MattLichtenstein authored Dec 21, 2023
1 parent 2e38e8d commit eef4311
Show file tree
Hide file tree
Showing 13 changed files with 469 additions and 52 deletions.
1 change: 0 additions & 1 deletion nebula/ui/components/MZUserProfile.qml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ MZClickableRow {

Rectangle {
id: iconButton
objectName: _objNameBase + "-manageAccountButton"
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.preferredHeight: MZTheme.theme.rowHeight
Layout.preferredWidth: MZTheme.theme.rowHeight
Expand Down
51 changes: 51 additions & 0 deletions src/frontend/navigator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,62 @@ void Navigator::computeComponent() {
void Navigator::requestScreenFromBottomBar(
int requestedScreen, Navigator::LoadingFlags loadingFlags) {
// Exists so we can add glean metric for screen changes only from bottom bar
// "bar_button" extra key denotes destination screen
mozilla::glean::sample::bottom_navigation_bar_click.record(
mozilla::glean::sample::BottomNavigationBarClickExtra{
._barButton = QVariant::fromValue(
static_cast<MozillaVPN::CustomScreen>(requestedScreen))});

// Record navbar button interaction telemetry with "screen" extra key which
// denotes the source view
// This is done by finding the screen we are currently on, and getting the
// "telemetryScreenId" QML property of the top (layers.last()) layer of this
// screens stack view, which would be the view currently being displayed
for (ScreenData& screen : s_screens) {
if (screen.m_screen == m_currentScreen) {
auto layers = screen.m_layers;

QString telemetryScreenId =
layers.last().m_layer->property("telemetryScreenId").toString();

// Make sure the screen has a view (and it has been added to the layers
// via Navigator::addView(), and that view has a non-empty
// "telemetryScreenId" property
// TODO in VPN-6039 - support screens as well (not just views on top of
// screens)
if (layers.length() < 1 || telemetryScreenId.isEmpty()) {
break;
}

// Record telemetry based on which screen was requested (aka which navbar
// button pressed)
switch (requestedScreen) {
case MozillaVPN::ScreenHome:
mozilla::glean::interaction::home_selected.record(
mozilla::glean::interaction::HomeSelectedExtra{
._screen = telemetryScreenId,
});
break;
case MozillaVPN::ScreenMessaging:
mozilla::glean::interaction::messages_selected.record(
mozilla::glean::interaction::MessagesSelectedExtra{
._screen = telemetryScreenId,
});
break;
case MozillaVPN::ScreenSettings:
mozilla::glean::interaction::settings_selected.record(
mozilla::glean::interaction::SettingsSelectedExtra{
._screen = telemetryScreenId,
});
break;
default:
logger.warning() << "Requested screen" << requestedScreen
<< "is not a screen from the navbar";
break;
}
}
}

requestScreen(requestedScreen, loadingFlags);
}

Expand Down
20 changes: 19 additions & 1 deletion src/telemetry/impression_metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -511,4 +511,22 @@ impression:
- [email protected]
- [email protected]
expires: never
extra_keys: *impression_extra_keys
extra_keys: *impression_extra_keys
account_screen:
type: event
lifetime: ping
send_in_pings:
- main
description: |
The user has viewed the subscription management screen
bugs:
- https://mozilla-hub.atlassian.net/browse/VPN-5547
data_reviews:
- https://github.com/mozilla-mobile/mozilla-vpn-client/pull/8838#pullrequestreview-1789303235
data_sensitivity:
- interaction
notification_emails:
- [email protected]
- [email protected]
expires: never
extra_keys: *impression_extra_keys
56 changes: 55 additions & 1 deletion src/telemetry/interaction_metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1086,4 +1086,58 @@ interaction:
- [email protected]
- [email protected]
expires: never
extra_keys: *interaction_extra_keys
extra_keys: *interaction_extra_keys
edit_selected:
type: event
lifetime: ping
send_in_pings:
- main
description: |
The user has clicked the "edit account" button
bugs:
- https://mozilla-hub.atlassian.net/browse/VPN-5547
data_reviews:
- https://github.com/mozilla-mobile/mozilla-vpn-client/pull/8838#pullrequestreview-1789303235
data_sensitivity:
- interaction
notification_emails:
- [email protected]
- [email protected]
expires: never
extra_keys: *interaction_extra_keys
manage_subscription_selected:
type: event
lifetime: ping
send_in_pings:
- main
description: |
The user has clicked the “manage subscription” button from the subscription management view
bugs:
- https://mozilla-hub.atlassian.net/browse/VPN-5547
data_reviews:
- https://github.com/mozilla-mobile/mozilla-vpn-client/pull/8838#pullrequestreview-1789303235
data_sensitivity:
- interaction
notification_emails:
- [email protected]
- [email protected]
expires: never
extra_keys: *interaction_extra_keys
change_plan_selected:
type: event
lifetime: ping
send_in_pings:
- main
description: |
The user has clicked the “change plan” button from the subscription management view (monthly web plan)
bugs:
- https://mozilla-hub.atlassian.net/browse/VPN-5547
data_reviews:
- https://github.com/mozilla-mobile/mozilla-vpn-client/pull/8838#pullrequestreview-1789303235
data_sensitivity:
- interaction
notification_emails:
- [email protected]
- [email protected]
expires: never
extra_keys: *interaction_extra_keys
19 changes: 0 additions & 19 deletions src/telemetry/metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1336,25 +1336,6 @@ sample:
`profileflow.h`.
type: string

manage_subscription_clicked:
type: event
lifetime: ping
send_in_pings:
- main
description: |
The user has clicked the “manage subscription” button from the
profile view.
bugs:
- https://github.com/mozilla-mobile/mozilla-vpn-client/issues/3627
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1774568
data_sensitivity:
- interaction
notification_emails:
- [email protected]
- [email protected]
expires: never

delete_account_requested:
type: event
lifetime: ping
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ColumnLayout {
id: root
objectName: _objectName + "-parent"

property string telemetryScreenId

spacing: 0

states: [
Expand Down Expand Up @@ -178,7 +180,12 @@ ColumnLayout {
MZButton {
objectName: _objectName + "-upgradeToAnnualSub-upgradeButton"

onClicked: MZUrlOpener.openUrlLabel("upgradeToAnnualUrl");
onClicked: {
Glean.interaction.changePlanSelected.record({
screen: root.telemetryScreenId,
});
MZUrlOpener.openUrlLabel("upgradeToAnnualUrl");
}
text: MZI18n.SubscriptionManagementUpgradeToAnnualButton// "Change plan"
fontSize: MZTheme.theme.fontSizeSmall
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ MZViewBase {
id: vpnFlickable
objectName: "subscriptionManagmentView"

property string telemetryScreenId: isAnnualUpgradeAvailable() && VPNSubscriptionData.type === VPNSubscriptionData.SubscriptionWeb ? "account_with_change_plan" : "account"

Component.onDestruction: () => VPNProfileFlow.reset()

_menuTitle: MZI18n.SubscriptionManagementMenuTitle
Expand All @@ -34,12 +36,13 @@ MZViewBase {
Layout.leftMargin: MZTheme.theme.windowMargin / 2
Layout.rightMargin: MZTheme.theme.windowMargin / 2

objectName: "subscriptionUserProfile"
_objNameBase: "subscriptionUserProfile"

_iconSource: "qrc:/nebula/resources/open-in-new.svg"
_buttonOnClicked: () => {
Glean.sample.manageAccountClicked.record();
Glean.interaction.editSelected.record({
screen: vpnFlickable.telemetryScreenId,
});
MZUrlOpener.openUrlLabel("account");
}
}
Expand Down Expand Up @@ -70,7 +73,9 @@ MZViewBase {
delegate: Loader {
objectName: _objectName
Layout.fillWidth: true
source: "qrc:/ui/screens/settings/ViewSubscriptionManagement/SubscriptionManagementItem.qml"
sourceComponent: SubscriptionManagementItem {
telemetryScreenId: vpnFlickable.telemetryScreenId
}
}
}

Expand Down Expand Up @@ -138,7 +143,9 @@ MZViewBase {
MZUrlOpener.openUrlLabel("account");
}

Glean.sample.manageSubscriptionClicked.record();
Glean.interaction.manageSubscriptionSelected.record({
screen: vpnFlickable.telemetryScreenId,
});
}

function isAnnualUpgradeAvailable() {
Expand Down Expand Up @@ -299,5 +306,9 @@ MZViewBase {

Component.onCompleted: {
populateListModels();
MZNavigator.addView(VPN.ScreenSettings, vpnFlickable)
Glean.impression.accountScreen.record({
screen: telemetryScreenId,
});
}
}
12 changes: 5 additions & 7 deletions tests/functional/queries.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,15 +270,12 @@ const screenSettings = {
APP_PREFERENCES: new QmlQueryComposer('//settingsPreferences'),
TIPS_AND_TRICKS: new QmlQueryComposer('//settingsTipsAndTricks'),
USER_PROFILE:
new QmlQueryComposer('//settingsUserProfile-manageAccountButton'),
new QmlQueryComposer('//settingsUserProfile'),
USER_PROFILE_DISPLAY_NAME:
new QmlQueryComposer('//settingsUserProfile-displayName'),
USER_PROFILE_EMAIL_ADDRESS:
new QmlQueryComposer('//settingsUserProfile-emailAddress'),

SUBSCRIPTION_MANAGMENT_VIEW:
new QmlQueryComposer('//subscriptionManagmentView'),

privacyView: {
BLOCK_ADS: new QmlQueryComposer('//blockAds'),
BLOCK_ADS_CHECKBOX: new QmlQueryComposer('//blockAds//checkbox'),
Expand Down Expand Up @@ -379,8 +376,11 @@ const screenSettings = {
ACCOUNT_DELETION: new QmlQueryComposer('//accountDeletionButton'),
ANNUAL_UPGRADE: new QmlQueryComposer(
'//subscriptionItem/subscriptionItem-plan/subscriptionItem-plan-parent/subscriptionItem-plan-upgradeToAnnualSub-layout'),
ANNUAL_UPGRADE_BUTTON: new QmlQueryComposer(
'//subscriptionItem/subscriptionItem-plan/subscriptionItem-plan-parent/subscriptionItem-plan-upgradeToAnnualSub-layout/subscriptionItem-plan-upgradeToAnnualSub-upgradeButton'),
PLAN: new QmlQueryComposer('//subscriptionItem-plan-valueText'),
SCREEN: new QmlQueryComposer('//subscriptionManagmentView-flickable'),
SCREEN: new QmlQueryComposer('//subscriptionManagmentView'),
FLICKABLE: new QmlQueryComposer('//subscriptionManagmentView-flickable'),
STATUS_PILL: new QmlQueryComposer('//subscriptionItem-status-pill'),

ACTIVATED: new QmlQueryComposer(
Expand All @@ -398,8 +398,6 @@ const screenSettings = {
PAYMENT_METHOD_LABEL: new QmlQueryComposer(
'//subscriptionItem/subscriptionItem-payment/subscriptionItem-payment-parent/subscriptionItem-payment-container/subscriptionItem-payment-paymentMethod/paymentLabel'),

SUBSCRIPTION_USER_PROFILE:
new QmlQueryComposer('//subscriptionUserProfile'),
SUBSCRIPTION_USER_PROFILE_DISPLAY_NAME:
new QmlQueryComposer('//subscriptionUserProfile-displayName'),
SUBSCRIPTION_USER_PROFILE_EMAIL_ADDRESS:
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/testAddons.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ describe('Addons', function() {
await vpn.waitForQuery(queries.screenSettings.STACKVIEW.ready());

await vpn.waitForQuery(
queries.screenSettings.SUBSCRIPTION_MANAGMENT_VIEW.visible());
queries.screenSettings.subscriptionView.SCREEN.visible());

// TODO: Uncomment the assertion below once we re-enable
// "Subscription expiring" message
Expand Down Expand Up @@ -368,7 +368,7 @@ describe('Addons', function() {
afterEach(() => setNextSubscriptionStarted(this.ctx));

testCases.forEach(([createdAtTimestamp, expectedTimeFormat, shouldBeAvailable, testCase]) => {
it.only(`message display is correct when subscription started at ${testCase}`, async () => {
it(`message display is correct when subscription started at ${testCase}`, async () => {
await vpn.resetAddons('prod');

//Load messages
Expand Down
Loading

0 comments on commit eef4311

Please sign in to comment.