Commit 4bcf1323 authored by Illya Klymov's avatar Illya Klymov

Merge branch '225858-homepage-banner-tracking' into 'master'

Add tracking to homepage customization banner

Closes #225858

See merge request gitlab-org/gitlab!39752
parents a411fce7 29b78062
...@@ -2,11 +2,15 @@ ...@@ -2,11 +2,15 @@
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
export default { export default {
components: { components: {
GlBanner, GlBanner,
}, },
mixins: [trackingMixin],
inject: { inject: {
svgPath: { svgPath: {
default: '', default: '',
...@@ -20,6 +24,9 @@ export default { ...@@ -20,6 +24,9 @@ export default {
calloutsFeatureId: { calloutsFeatureId: {
default: '', default: '',
}, },
trackLabel: {
default: '',
},
}, },
i18n: { i18n: {
title: s__('CustomizeHomepageBanner|Do you want to customize this page?'), title: s__('CustomizeHomepageBanner|Do you want to customize this page?'),
...@@ -31,8 +38,19 @@ export default { ...@@ -31,8 +38,19 @@ export default {
data() { data() {
return { return {
visible: true, visible: true,
tracking: {
label: this.trackLabel,
},
}; };
}, },
created() {
this.$nextTick(() => {
this.addTrackingAttributesToButton();
});
},
mounted() {
this.trackOnShow();
},
methods: { methods: {
handleClose() { handleClose() {
axios axios
...@@ -45,6 +63,23 @@ export default { ...@@ -45,6 +63,23 @@ export default {
}); });
this.visible = false; this.visible = false;
this.track('click_dismiss');
},
trackOnShow() {
if (this.visible) this.track('show_home_page_banner');
},
addTrackingAttributesToButton() {
// we can't directly add these on the button like we need to due to
// button not being modifiable currently
// https://gitlab.com/gitlab-org/gitlab-ui/-/blob/9209ec424e5cca14bc8a1b5c9fa12636d8c83dad/src/components/base/banner/banner.vue#L60
const button = this.$refs.banner.$el.querySelector(
`[href='${this.preferencesBehaviorPath}']`,
);
if (button) {
button.setAttribute('data-track-event', 'click_go_to_preferences');
button.setAttribute('data-track-label', this.trackLabel);
}
}, },
}, },
}; };
...@@ -53,6 +88,7 @@ export default { ...@@ -53,6 +88,7 @@ export default {
<template> <template>
<gl-banner <gl-banner
v-if="visible" v-if="visible"
ref="banner"
:title="$options.i18n.title" :title="$options.i18n.title"
:button-text="$options.i18n.button_text" :button-text="$options.i18n.button_text"
:button-link="preferencesBehaviorPath" :button-link="preferencesBehaviorPath"
......
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
.js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'), .js-customize-homepage-banner{ data: { svg_path: image_path('illustrations/monitoring/getting_started.svg'),
preferences_behavior_path: profile_preferences_path(anchor: 'behavior'), preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
callouts_path: user_callouts_path, callouts_path: user_callouts_path,
callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE } } callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE,
track_label: 'home_page' } }
= render_dashboard_gold_trial(current_user) = render_dashboard_gold_trial(current_user)
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { GlBanner } from '@gitlab/ui'; import { GlBanner } from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue'; import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
...@@ -10,18 +11,22 @@ const provide = { ...@@ -10,18 +11,22 @@ const provide = {
preferencesBehaviorPath: 'some/behavior/path', preferencesBehaviorPath: 'some/behavior/path',
calloutsPath: 'call/out/path', calloutsPath: 'call/out/path',
calloutsFeatureId: 'some-feature-id', calloutsFeatureId: 'some-feature-id',
trackLabel: 'home_page',
}; };
const createComponent = () => { const createComponent = () => {
return shallowMount(CustomizeHomepageBanner, { provide }); return shallowMount(CustomizeHomepageBanner, { provide, stubs: { GlBanner } });
}; };
describe('CustomizeHomepageBanner', () => { describe('CustomizeHomepageBanner', () => {
let trackingSpy;
let mockAxios; let mockAxios;
let wrapper; let wrapper;
beforeEach(() => { beforeEach(() => {
mockAxios = new MockAdapter(axios); mockAxios = new MockAdapter(axios);
document.body.dataset.page = 'some:page';
trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
wrapper = createComponent(); wrapper = createComponent();
}); });
...@@ -29,6 +34,7 @@ describe('CustomizeHomepageBanner', () => { ...@@ -29,6 +34,7 @@ describe('CustomizeHomepageBanner', () => {
wrapper.destroy(); wrapper.destroy();
wrapper = null; wrapper = null;
mockAxios.restore(); mockAxios.restore();
unmockTracking();
}); });
it('should render the banner when not dismissed', () => { it('should render the banner when not dismissed', () => {
...@@ -47,4 +53,56 @@ describe('CustomizeHomepageBanner', () => { ...@@ -47,4 +53,56 @@ describe('CustomizeHomepageBanner', () => {
it('includes the body text from options', () => { it('includes the body text from options', () => {
expect(wrapper.html()).toContain(wrapper.vm.$options.i18n.body); expect(wrapper.html()).toContain(wrapper.vm.$options.i18n.body);
}); });
describe('tracking', () => {
const preferencesTrackingEvent = 'click_go_to_preferences';
const mockTrackingOnWrapper = () => {
unmockTracking();
trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
};
it('sets the needed data attributes for tracking button', async () => {
await wrapper.vm.$nextTick();
const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
expect(button.attributes('data-track-event')).toEqual(preferencesTrackingEvent);
expect(button.attributes('data-track-label')).toEqual(provide.trackLabel);
});
it('sends a tracking event when the banner is shown', () => {
const trackCategory = undefined;
const trackEvent = 'show_home_page_banner';
expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
label: provide.trackLabel,
});
});
it('sends a tracking event when the banner is dismissed', async () => {
mockTrackingOnWrapper();
mockAxios.onPost(provide.calloutsPath).replyOnce(200);
const trackCategory = undefined;
const trackEvent = 'click_dismiss';
wrapper.find(GlBanner).vm.$emit('close');
await wrapper.vm.$nextTick();
expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
label: provide.trackLabel,
});
});
it('sends a tracking event when the button is clicked', async () => {
mockTrackingOnWrapper();
mockAxios.onPost(provide.calloutsPath).replyOnce(200);
const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
triggerEvent(button.element);
await wrapper.vm.$nextTick();
expect(trackingSpy).toHaveBeenCalledWith('_category_', preferencesTrackingEvent, {
label: provide.trackLabel,
});
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment