Commit 608727b7 authored by Tyler Williams's avatar Tyler Williams Committed by Paul Slaughter

Add checkout event to Google Tag Manager on new subscription form

This commit adds the checkout event to Google Tag Manager on
the new subscription form.

It also adds some Jest specs to test it out, with permutations
of the provided product text and number of users.

Related to https://gitlab.com/gitlab-com/marketing/digital-experience/buyer-experience/-/issues/269
parent 5401c260
import { logError } from '~/lib/logger'; import { logError } from '~/lib/logger';
const SKU_PREMIUM = '2c92a00d76f0d5060176f2fb0a5029ff';
const SKU_ULTIMATE = '2c92a0ff76f0d5250176f2f8c86f305a';
const PRODUCT_INFO = {
[SKU_PREMIUM]: {
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Premium',
id: '0002',
price: 228,
variant: 'SaaS',
},
[SKU_ULTIMATE]: {
// eslint-disable-next-line @gitlab/require-i18n-strings
name: 'Ultimate',
id: '0001',
price: 1188,
variant: 'SaaS',
},
};
const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer; const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer;
const pushEvent = (event, args = {}) => { const pushEvent = (event, args = {}) => {
...@@ -17,6 +36,23 @@ const pushEvent = (event, args = {}) => { ...@@ -17,6 +36,23 @@ const pushEvent = (event, args = {}) => {
} }
}; };
const pushEnhancedEcommerceEvent = (event, currencyCode, args = {}) => {
if (!window.dataLayer) {
return;
}
try {
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
event,
currencyCode,
...args,
});
} catch (e) {
logError('Unexpected error while pushing to dataLayer', e);
}
};
const pushAccountSubmit = (accountType, accountMethod) => const pushAccountSubmit = (accountType, accountMethod) =>
pushEvent('accountSubmit', { accountType, accountMethod }); pushEvent('accountSubmit', { accountType, accountMethod });
...@@ -120,3 +156,35 @@ export const trackSaasTrialGetStarted = () => { ...@@ -120,3 +156,35 @@ export const trackSaasTrialGetStarted = () => {
pushEvent('saasTrialGetStarted'); pushEvent('saasTrialGetStarted');
}); });
}; };
export const trackCheckout = (selectedPlan, quantity) => {
if (!isSupported()) {
return;
}
const product = PRODUCT_INFO[selectedPlan];
if (!product) {
logError('Unexpected product sku provided to trackCheckout');
return;
}
const selectedProductData = {
...product,
brand: 'GitLab',
category: 'DevOps',
quantity,
};
const eventData = {
ecommerce: {
checkout: {
actionField: { step: 1 },
products: [selectedProductData],
},
},
};
// eslint-disable-next-line @gitlab/require-i18n-strings
pushEnhancedEcommerceEvent('EECCheckout', 'USD', eventData);
};
<script> <script>
import { GlIcon } from '@gitlab/ui'; import { GlIcon } from '@gitlab/ui';
import { mapGetters } from 'vuex'; import { mapGetters, mapState } from 'vuex';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import { trackCheckout } from '~/google_tag_manager';
import formattingMixins from '../formatting_mixins'; import formattingMixins from '../formatting_mixins';
import SummaryDetails from './order_summary/summary_details.vue'; import SummaryDetails from './order_summary/summary_details.vue';
...@@ -17,7 +18,9 @@ export default { ...@@ -17,7 +18,9 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['numberOfUsers', 'selectedPlan']),
...mapGetters([ ...mapGetters([
'selectedPlanText',
'totalAmount', 'totalAmount',
'name', 'name',
'usersPresent', 'usersPresent',
...@@ -28,6 +31,9 @@ export default { ...@@ -28,6 +31,9 @@ export default {
return sprintf(this.$options.i18n.title, { name: this.name }); return sprintf(this.$options.i18n.title, { name: this.name });
}, },
}, },
mounted() {
trackCheckout(this.selectedPlan, this.numberOfUsers);
},
methods: { methods: {
toggleCollapse() { toggleCollapse() {
this.collapsed = !this.collapsed; this.collapsed = !this.collapsed;
......
...@@ -5,12 +5,14 @@ import activateNextStepMutation from 'ee/vue_shared/purchase_flow/graphql/mutati ...@@ -5,12 +5,14 @@ import activateNextStepMutation from 'ee/vue_shared/purchase_flow/graphql/mutati
import createFlash from '~/flash'; import createFlash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility'; import { redirectTo } from '~/lib/utils/url_utility';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import { trackCheckout } from '~/google_tag_manager';
import defaultClient from '../graphql'; import defaultClient from '../graphql';
import * as types from './mutation_types'; import * as types from './mutation_types';
export const updateSelectedPlan = ({ commit, getters }, selectedPlan) => { export const updateSelectedPlan = ({ commit, getters }, selectedPlan) => {
commit(types.UPDATE_SELECTED_PLAN, selectedPlan); commit(types.UPDATE_SELECTED_PLAN, selectedPlan);
commit(types.UPDATE_NUMBER_OF_USERS, getters.selectedGroupUsers); commit(types.UPDATE_NUMBER_OF_USERS, getters.selectedGroupUsers);
trackCheckout(selectedPlan, getters.selectedGroupUsers);
}; };
export const updateSelectedGroup = ({ commit, getters }, selectedGroup) => { export const updateSelectedGroup = ({ commit, getters }, selectedGroup) => {
...@@ -23,8 +25,9 @@ export const toggleIsSetupForCompany = ({ state, commit }) => { ...@@ -23,8 +25,9 @@ export const toggleIsSetupForCompany = ({ state, commit }) => {
commit(types.UPDATE_IS_SETUP_FOR_COMPANY, !state.isSetupForCompany); commit(types.UPDATE_IS_SETUP_FOR_COMPANY, !state.isSetupForCompany);
}; };
export const updateNumberOfUsers = ({ commit }, numberOfUsers) => { export const updateNumberOfUsers = ({ commit, getters }, numberOfUsers) => {
commit(types.UPDATE_NUMBER_OF_USERS, numberOfUsers || 0); commit(types.UPDATE_NUMBER_OF_USERS, numberOfUsers || 0);
trackCheckout(getters.selectedPlanDetails?.value, numberOfUsers);
}; };
export const updateOrganizationName = ({ commit }, organizationName) => { export const updateOrganizationName = ({ commit }, organizationName) => {
......
...@@ -9,6 +9,10 @@ class SubscriptionsController < ApplicationController ...@@ -9,6 +9,10 @@ class SubscriptionsController < ApplicationController
before_action :load_eligible_groups, only: :new before_action :load_eligible_groups, only: :new
before_action only: [:new] do
push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)
end
feature_category :purchase feature_category :purchase
content_security_policy do |p| content_security_policy do |p|
......
...@@ -8,6 +8,7 @@ import { ...@@ -8,6 +8,7 @@ import {
trackSaasTrialProject, trackSaasTrialProject,
trackSaasTrialProjectImport, trackSaasTrialProjectImport,
trackSaasTrialGetStarted, trackSaasTrialGetStarted,
trackCheckout,
} from '~/google_tag_manager'; } from '~/google_tag_manager';
import { setHTMLFixture } from 'helpers/fixtures'; import { setHTMLFixture } from 'helpers/fixtures';
import { logError } from '~/lib/logger'; import { logError } from '~/lib/logger';
...@@ -209,6 +210,103 @@ describe('~/google_tag_manager/index', () => { ...@@ -209,6 +210,103 @@ describe('~/google_tag_manager/index', () => {
expect(spy).toHaveBeenCalledWith({ event: 'saasTrialSubmit' }); expect(spy).toHaveBeenCalledWith({ event: 'saasTrialSubmit' });
expect(logError).not.toHaveBeenCalled(); expect(logError).not.toHaveBeenCalled();
}); });
describe('when trackCheckout is invoked', () => {
it('with selectedPlan: 2c92a00d76f0d5060176f2fb0a5029ff', () => {
expect(spy).not.toHaveBeenCalled();
trackCheckout('2c92a00d76f0d5060176f2fb0a5029ff', 1);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith({ ecommerce: null });
expect(spy).toHaveBeenCalledWith({
event: 'EECCheckout',
currencyCode: 'USD',
ecommerce: {
checkout: {
actionField: { step: 1 },
products: [
{
brand: 'GitLab',
category: 'DevOps',
id: '0002',
name: 'Premium',
price: 228,
quantity: 1,
variant: 'SaaS',
},
],
},
},
});
});
it('with selectedPlan: 2c92a0ff76f0d5250176f2f8c86f305a', () => {
expect(spy).not.toHaveBeenCalled();
trackCheckout('2c92a0ff76f0d5250176f2f8c86f305a', 1);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith({ ecommerce: null });
expect(spy).toHaveBeenCalledWith({
event: 'EECCheckout',
currencyCode: 'USD',
ecommerce: {
checkout: {
actionField: { step: 1 },
products: [
{
brand: 'GitLab',
category: 'DevOps',
id: '0001',
name: 'Ultimate',
price: 1188,
quantity: 1,
variant: 'SaaS',
},
],
},
},
});
});
it('with selectedPlan: Something else', () => {
expect(spy).not.toHaveBeenCalled();
trackCheckout('Something else', 1);
expect(spy).not.toHaveBeenCalled();
});
it('with a different number of users', () => {
expect(spy).not.toHaveBeenCalled();
trackCheckout('2c92a0ff76f0d5250176f2f8c86f305a', 5);
expect(spy).toHaveBeenCalledTimes(2);
expect(spy).toHaveBeenCalledWith({ ecommerce: null });
expect(spy).toHaveBeenCalledWith({
event: 'EECCheckout',
currencyCode: 'USD',
ecommerce: {
checkout: {
actionField: { step: 1 },
products: [
{
brand: 'GitLab',
category: 'DevOps',
id: '0001',
name: 'Ultimate',
price: 1188,
quantity: 5,
variant: 'SaaS',
},
],
},
},
});
});
});
}); });
describe.each([ describe.each([
......
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