Commit dbece389 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'feature/add-enhanced-ecommerce-checkout-to-new-subscriptions' into 'master'

Add checkout event to Google Tag Manager on new subscription form

See merge request gitlab-org/gitlab!78727
parents c2d1b36f 608727b7
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 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) =>
pushEvent('accountSubmit', { accountType, accountMethod });
......@@ -120,3 +156,35 @@ export const trackSaasTrialGetStarted = () => {
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>
import { GlIcon } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { mapGetters, mapState } from 'vuex';
import { sprintf, s__ } from '~/locale';
import { trackCheckout } from '~/google_tag_manager';
import formattingMixins from '../formatting_mixins';
import SummaryDetails from './order_summary/summary_details.vue';
......@@ -17,7 +18,9 @@ export default {
};
},
computed: {
...mapState(['numberOfUsers', 'selectedPlan']),
...mapGetters([
'selectedPlanText',
'totalAmount',
'name',
'usersPresent',
......@@ -28,6 +31,9 @@ export default {
return sprintf(this.$options.i18n.title, { name: this.name });
},
},
mounted() {
trackCheckout(this.selectedPlan, this.numberOfUsers);
},
methods: {
toggleCollapse() {
this.collapsed = !this.collapsed;
......
......@@ -5,12 +5,14 @@ import activateNextStepMutation from 'ee/vue_shared/purchase_flow/graphql/mutati
import createFlash from '~/flash';
import { redirectTo } from '~/lib/utils/url_utility';
import { sprintf, s__ } from '~/locale';
import { trackCheckout } from '~/google_tag_manager';
import defaultClient from '../graphql';
import * as types from './mutation_types';
export const updateSelectedPlan = ({ commit, getters }, selectedPlan) => {
commit(types.UPDATE_SELECTED_PLAN, selectedPlan);
commit(types.UPDATE_NUMBER_OF_USERS, getters.selectedGroupUsers);
trackCheckout(selectedPlan, getters.selectedGroupUsers);
};
export const updateSelectedGroup = ({ commit, getters }, selectedGroup) => {
......@@ -23,8 +25,9 @@ export const toggleIsSetupForCompany = ({ state, commit }) => {
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);
trackCheckout(getters.selectedPlanDetails?.value, numberOfUsers);
};
export const updateOrganizationName = ({ commit }, organizationName) => {
......
......@@ -9,6 +9,10 @@ class SubscriptionsController < ApplicationController
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
content_security_policy do |p|
......
......@@ -8,6 +8,7 @@ import {
trackSaasTrialProject,
trackSaasTrialProjectImport,
trackSaasTrialGetStarted,
trackCheckout,
} from '~/google_tag_manager';
import { setHTMLFixture } from 'helpers/fixtures';
import { logError } from '~/lib/logger';
......@@ -209,6 +210,103 @@ describe('~/google_tag_manager/index', () => {
expect(spy).toHaveBeenCalledWith({ event: 'saasTrialSubmit' });
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([
......
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