diff --git a/app/assets/javascripts/tracking/tracking.js b/app/assets/javascripts/tracking/tracking.js index f4c8781ae20a0ccd4726157ac75d9e8286a9cb44..88553afeb5006ce2c6691071b8e25434a93f1076 100644 --- a/app/assets/javascripts/tracking/tracking.js +++ b/app/assets/javascripts/tracking/tracking.js @@ -19,11 +19,12 @@ const Tracking = Object.assign(Tracker, { return localCategory || opts.category; }, trackingOptions() { - const options = addExperimentContext(opts); // TODO: refactor to remove potentially undefined property // https://gitlab.com/gitlab-org/gitlab/-/issues/432995 const tracking = 'tracking' in this ? this.tracking : {}; - return { ...options, ...tracking }; + const options = addExperimentContext({ ...opts, ...tracking }); + + return options; }, }, methods: { diff --git a/ee/app/assets/javascripts/contextual_sidebar/components/trial_status_popover.vue b/ee/app/assets/javascripts/contextual_sidebar/components/trial_status_popover.vue index 3d6d076f34028a318807073bf6f0b842db4fefc6..e51e6b7df478867a2510276242e6c0663395d0e6 100644 --- a/ee/app/assets/javascripts/contextual_sidebar/components/trial_status_popover.vue +++ b/ee/app/assets/javascripts/contextual_sidebar/components/trial_status_popover.vue @@ -35,8 +35,6 @@ export default { targetId: {}, createHandRaiseLeadPath: {}, trialEndDate: {}, - trackAction: {}, - trackLabel: {}, user: {}, trialDiscoverPagePath: {}, }, @@ -89,6 +87,19 @@ export default { return classList; }, + trialPopoverCategory() { + return this.isTrialActive + ? trackingEvents.activeTrialCategory + : trackingEvents.trialEndedCategory; + }, + handRaiseLeadBtnTracking() { + const { action, label } = trackingEvents.contactSalesBtnClick; + return { + category: this.trialPopoverCategory, + action, + label, + }; + }, }, created() { this.debouncedResize = debounce(() => this.updateDisabledState(), resizeEventDebounceMS); @@ -103,9 +114,7 @@ export default { methods: { trackPageAction(eventName) { const { action, ...options } = trackingEvents[eventName]; - const category = this.isTrialActive - ? trackingEvents.activeTrialCategory - : trackingEvents.trialEndedCategory; + const category = this.trialPopoverCategory; this.track(action, { category, ...options }); }, @@ -163,22 +172,21 @@ export default { <span class="gl-font-sm">{{ $options.i18n.compareAllButtonTitle }}</span> </gl-button> - <div data-testid="contact-sales-btn" @click="trackPageAction('contactSalesBtnClick')"> - <div - class="js-hand-raise-lead-button" - data-testid="contact-sales-block" - :data-create-hand-raise-lead-path="createHandRaiseLeadPath" - :data-button-attributes="JSON.stringify($options.handRaiseLeadAttributes)" - :data-namespace-id="user.namespaceId" - :data-user-name="user.userName" - :data-first-name="user.firstName" - :data-last-name="user.lastName" - :data-company-name="user.companyName" - :data-glm-content="user.glmContent" - :data-track-action="trackAction" - :data-track-label="trackLabel" - ></div> - </div> + <div + class="js-hand-raise-lead-button" + data-testid="contact-sales-btn" + :data-create-hand-raise-lead-path="createHandRaiseLeadPath" + :data-button-attributes="JSON.stringify($options.handRaiseLeadAttributes)" + :data-namespace-id="user.namespaceId" + :data-user-name="user.userName" + :data-first-name="user.firstName" + :data-last-name="user.lastName" + :data-company-name="user.companyName" + :data-glm-content="user.glmContent" + :data-track-category="handRaiseLeadBtnTracking.category" + :data-track-action="handRaiseLeadBtnTracking.action" + :data-track-label="handRaiseLeadBtnTracking.label" + ></div> <gitlab-experiment name="trial_discover_page"> <template #candidate> diff --git a/ee/app/assets/javascripts/contextual_sidebar/init_trial_status_widget_and_popover.js b/ee/app/assets/javascripts/contextual_sidebar/init_trial_status_widget_and_popover.js index 16dc67910e6438adff51709ea86739f03e6ba366..3a8d1a7f4440883fa0505d398e1b3bf8bc2f2edb 100644 --- a/ee/app/assets/javascripts/contextual_sidebar/init_trial_status_widget_and_popover.js +++ b/ee/app/assets/javascripts/contextual_sidebar/init_trial_status_widget_and_popover.js @@ -53,8 +53,6 @@ export const initTrialStatusPopover = () => { companyName, glmContent, createHandRaiseLeadPath, - trackAction, - trackLabel, trialDiscoverPagePath, } = el.dataset; @@ -68,8 +66,6 @@ export const initTrialStatusPopover = () => { targetId, createHandRaiseLeadPath, trialEndDate: new Date(trialEndDate), - trackAction, - trackLabel, trialDiscoverPagePath, user: { namespaceId, diff --git a/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue b/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue index f6c78cf687919a964674169c6f23b6161772c0e8..4da25ffb4d98d694a94d96bbc7c8eb482d9b8f54 100644 --- a/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue +++ b/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/components/hand_raise_lead_button.vue @@ -136,6 +136,7 @@ export default { tracking() { return { label: 'hand_raise_lead_form', + experiment: this.ctaTracking.experiment, }; }, companySizeOptionsWithDefault() { @@ -208,6 +209,12 @@ export default { this.state = state; this.stateRequired = stateRequired; }, + trackBtnClick() { + const { action, ...options } = this.ctaTracking; + if (action) { + this.track(action, options); + } + }, }, i18n: { firstNameLabel: LEADS_FIRST_NAME_LABEL, @@ -239,11 +246,7 @@ export default { v-gl-modal.hand-raise-lead v-bind="buttonAttributes" :loading="isLoading" - :data-track-action="ctaTracking.action" - :data-track-label="ctaTracking.label" - :data-track-property="ctaTracking.property" - :data-track-value="ctaTracking.value" - :data-track-experiment="ctaTracking.experiment" + @click="trackBtnClick" > {{ buttonText }} </gl-button> diff --git a/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/init_hand_raise_lead_button.js b/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/init_hand_raise_lead_button.js index 6d142297863c79cef86e911931b2bb9e81cf097b..37cb1503e1ff7272d8d39818b60e74ef9c9e08f4 100644 --- a/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/init_hand_raise_lead_button.js +++ b/ee/app/assets/javascripts/hand_raise_leads/hand_raise_lead/init_hand_raise_lead_button.js @@ -12,6 +12,7 @@ export const initHandRaiseLeadButton = (el) => { companyName, glmContent, productInteraction, + trackCategory, trackAction, trackLabel, trackProperty, @@ -41,6 +42,7 @@ export const initHandRaiseLeadButton = (el) => { productInteraction, }, ctaTracking: { + category: trackCategory, action: trackAction, label: trackLabel, property: trackProperty, diff --git a/ee/app/helpers/trial_status_widget_helper.rb b/ee/app/helpers/trial_status_widget_helper.rb index d496d3f8e3da9d9749965afcdf1f61345c36e6b3..1451970f13e39432a925b88d615536134dc5f624 100644 --- a/ee/app/helpers/trial_status_widget_helper.rb +++ b/ee/app/helpers/trial_status_widget_helper.rb @@ -12,8 +12,6 @@ def trial_status_popover_data_attrs(group, trial_status) ) base_attrs.merge( - track_action: 'click_button', - track_label: 'trial_status_popover_hand_raise_lead_form', days_remaining: trial_status.days_remaining, target_id: base_attrs[:container_id], trial_end_date: trial_status.ends_on diff --git a/ee/spec/frontend/contextual_sidebar/trial_status_popover_spec.js b/ee/spec/frontend/contextual_sidebar/trial_status_popover_spec.js index 26352e18423b108fe083b482541bbbd138e4d0e6..8d2c1a8e04a01c725c5f811f187972d1e8c9b893 100644 --- a/ee/spec/frontend/contextual_sidebar/trial_status_popover_spec.js +++ b/ee/spec/frontend/contextual_sidebar/trial_status_popover_spec.js @@ -38,8 +38,6 @@ describe('TrialStatusPopover component', () => { targetId: 'target-element-identifier', createHandRaiseLeadPath: '/-/subscriptions/hand_raise_leads', trialEndDate: new Date('2021-02-21'), - trackAction: trackingEvents.contactSalesBtnClick.action, - trackLabel: trackingEvents.contactSalesBtnClick.label, user: { namespaceId: 'namespaceId', userName: 'userName', @@ -118,8 +116,8 @@ describe('TrialStatusPopover component', () => { }); }); - it('tracks when the contact sales button is clicked', async () => { - expect(wrapper.findByTestId('contact-sales-block').attributes()).toMatchObject({ + it('sets correct attributes to the contact sales button', () => { + expect(wrapper.findByTestId('contact-sales-btn').attributes()).toMatchObject({ 'data-create-hand-raise-lead-path': '/-/subscriptions/hand_raise_leads', 'data-namespace-id': 'namespaceId', 'data-user-name': 'userName', @@ -127,13 +125,10 @@ describe('TrialStatusPopover component', () => { 'data-last-name': 'lastName', 'data-company-name': 'companyName', 'data-glm-content': 'glmContent', + 'data-track-category': trackingEvents.activeTrialCategory, 'data-track-action': trackingEvents.contactSalesBtnClick.action, 'data-track-label': trackingEvents.contactSalesBtnClick.label, }); - - await wrapper.findByTestId('contact-sales-btn').trigger('click'); - - expectTracking(trackingEvents.activeTrialCategory, trackingEvents.contactSalesBtnClick); }); it('tracks when the compare button is clicked', () => { @@ -147,10 +142,19 @@ describe('TrialStatusPopover component', () => { wrapper = createComponent({ providers: { daysRemaining: -5 } }); }); - it('tracks when the contact sales button is clicked', async () => { - await wrapper.findByTestId('contact-sales-btn').trigger('click'); - - expectTracking(trackingEvents.trialEndedCategory, trackingEvents.contactSalesBtnClick); + it('sets correct attributes to the contact sales button', () => { + expect(wrapper.findByTestId('contact-sales-btn').attributes()).toMatchObject({ + 'data-create-hand-raise-lead-path': '/-/subscriptions/hand_raise_leads', + 'data-namespace-id': 'namespaceId', + 'data-user-name': 'userName', + 'data-first-name': 'firstName', + 'data-last-name': 'lastName', + 'data-company-name': 'companyName', + 'data-glm-content': 'glmContent', + 'data-track-category': trackingEvents.trialEndedCategory, + 'data-track-action': trackingEvents.contactSalesBtnClick.action, + 'data-track-label': trackingEvents.contactSalesBtnClick.label, + }); }); it('tracks when the compare button is clicked', () => { diff --git a/ee/spec/frontend/hand_raise_leads/components/hand_raise_lead_button_spec.js b/ee/spec/frontend/hand_raise_leads/components/hand_raise_lead_button_spec.js index 8c0cc4583555db07240bb623d0747437403a1c6e..e77310cc19f3d8983db6be2187bdf84a8a730ae8 100644 --- a/ee/spec/frontend/hand_raise_leads/components/hand_raise_lead_button_spec.js +++ b/ee/spec/frontend/hand_raise_leads/components/hand_raise_lead_button_spec.js @@ -170,6 +170,7 @@ describe('HandRaiseLeadButton', () => { }); describe('when provided with CTA tracking options', () => { + const category = 'category'; const action = 'click_button'; const label = 'contact sales'; const experiment = 'some_experiment'; @@ -180,48 +181,40 @@ describe('HandRaiseLeadButton', () => { beforeEach(() => { wrapper = createComponent({ - ctaTracking: { action, label, property, value, experiment }, + ctaTracking: { category, action, label, property, value, experiment }, }); - trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + trackingSpy = mockTracking(category, wrapper.element, jest.spyOn); }); it('sets up tracking on the CTA button', () => { const button = findButton(); - expect(button.attributes()).toMatchObject({ - 'data-track-action': action, - 'data-track-label': label, - 'data-track-property': property, - 'data-track-value': value, - 'data-track-experiment': experiment, - }); - - button.trigger('click'); + button.vm.$emit('click'); - expect(trackingSpy).toHaveBeenCalledWith('_category_', action, { label, property, value }); + expect(trackingSpy).toHaveBeenCalledWith(category, action, { + category, + label, + property, + value, + experiment, + }); }); }); describe('when provided with some of the CTA tracking options', () => { beforeEach(() => { wrapper = createComponent({ - ctaTracking: { action, label, experiment }, + ctaTracking: { category, action, label, experiment }, }); - trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + trackingSpy = mockTracking(category, wrapper.element, jest.spyOn); }); it('sets up tracking on the CTA button', () => { const button = findButton(); - expect(button.attributes()).toMatchObject({ - 'data-track-action': action, - 'data-track-label': label, - 'data-track-experiment': experiment, - }); - - button.trigger('click'); + button.vm.$emit('click'); - expect(trackingSpy).toHaveBeenCalledWith('_category_', action, { label }); + expect(trackingSpy).toHaveBeenCalledWith(category, action, { label, experiment, category }); }); }); @@ -230,15 +223,13 @@ describe('HandRaiseLeadButton', () => { wrapper = createComponent({ ctaTracking: { label }, }); - trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + trackingSpy = mockTracking(category, wrapper.element, jest.spyOn); }); it('does not track when action is missing', () => { const button = findButton(); - expect(button.attributes()).toMatchObject({ 'data-track-label': label }); - - button.trigger('click'); + button.vm.$emit('click'); expect(trackingSpy).not.toHaveBeenCalled(); }); diff --git a/ee/spec/helpers/sidebars_helper_spec.rb b/ee/spec/helpers/sidebars_helper_spec.rb index dfd4ddec078339d29de8e579f0ad8e7b8f87e228..6c92a71d313f5b987989d43a69b8506ceacf5dd0 100644 --- a/ee/spec/helpers/sidebars_helper_spec.rb +++ b/ee/spec/helpers/sidebars_helper_spec.rb @@ -103,8 +103,6 @@ company_name: "", container_id: "trial-status-sidebar-widget", create_hand_raise_lead_path: "/-/subscriptions/hand_raise_leads", - track_action: 'click_button', - track_label: 'trial_status_popover_hand_raise_lead_form', days_remaining: 15, first_name: user.first_name, glm_content: "trial-status-show-group", diff --git a/ee/spec/helpers/trial_status_widget_helper_spec.rb b/ee/spec/helpers/trial_status_widget_helper_spec.rb index 60c60571e8495f43797afda843aa2aa661a1017e..cb0706cd1fd593fc129b020e5d64659839e0b9bb 100644 --- a/ee/spec/helpers/trial_status_widget_helper_spec.rb +++ b/ee/spec/helpers/trial_status_widget_helper_spec.rb @@ -57,8 +57,6 @@ glm_content: 'trial-status-show-group', product_interaction: 'Hand Raise PQL', create_hand_raise_lead_path: '/-/subscriptions/hand_raise_leads', - track_action: 'click_button', - track_label: 'trial_status_popover_hand_raise_lead_form', target_id: expected_attrs[:container_id], trial_end_date: trial_end_date ) diff --git a/spec/frontend/tracking/tracking_spec.js b/spec/frontend/tracking/tracking_spec.js index 55ce8039399e1023b30a1ea66831662a67dc4d9f..6ac4f5fae5166dfd423b7902b6afcb2b1468685d 100644 --- a/spec/frontend/tracking/tracking_spec.js +++ b/spec/frontend/tracking/tracking_spec.js @@ -612,20 +612,35 @@ describe('Tracking', () => { expect(mixin.computed.trackingOptions()).toEqual({ foo: 'baz', baz: 'bar' }); }); - it('includes experiment data if linked to an experiment', () => { + describe('experiment', () => { const mockExperimentData = { variant: 'candidate', experiment: 'darkMode', }; - getExperimentData.mockReturnValue(mockExperimentData); - const mixin = Tracking.mixin({ foo: 'bar', experiment: 'darkMode' }); - expect(mixin.computed.trackingOptions()).toEqual({ + const expectedOptions = { foo: 'bar', context: { schema: TRACKING_CONTEXT_SCHEMA, data: mockExperimentData, }, + }; + + beforeEach(() => { + getExperimentData.mockReturnValue(mockExperimentData); + }); + + it('includes experiment data if linked to an experiment', () => { + const mixin = Tracking.mixin({ foo: 'bar', experiment: 'darkMode' }); + + expect(mixin.computed.trackingOptions()).toEqual(expectedOptions); + }); + + it('includes experiment data if local tracking value provides experiment name', () => { + const mixin = Tracking.mixin({ foo: 'bar' }); + mixin.computed.tracking = { experiment: 'darkMode' }; + + expect(mixin.computed.trackingOptions()).toEqual(expectedOptions); }); });