import { v4 as uuidv4 } from 'uuid'; 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 EMPTY_NAMESPACE_ID_VALUE = 'not available'; const generateProductInfo = (sku, quantity) => { const product = PRODUCT_INFO[sku]; if (!product) { logError('Unexpected product sku provided to generateProductInfo'); return {}; } const productInfo = { ...product, brand: 'GitLab', category: 'DevOps', quantity, }; return productInfo; }; const isSupported = () => Boolean(window.dataLayer) && gon.features?.gitlabGtmDatalayer; // gon.features.gitlabGtmDatalayer is set by writing // `push_frontend_feature_flag(:gitlab_gtm_datalayer, type: :ops)` // to the appropriate controller // window.dataLayer is set by adding partials to the appropriate view found in // views/layouts/_google_tag_manager_body.html.haml and _google_tag_manager_head.html.haml const pushEvent = (event, args = {}) => { if (!window.dataLayer) { return; } try { window.dataLayer.push({ event, ...args, }); } catch (e) { logError('Unexpected error while pushing to dataLayer', e); } }; const pushEnhancedEcommerceEvent = (event, args = {}) => { if (!window.dataLayer) { return; } try { window.dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object window.dataLayer.push({ event, ...args, }); } catch (e) { logError('Unexpected error while pushing to dataLayer', e); } }; const pushAccountSubmit = (accountType, accountMethod) => pushEvent('accountSubmit', { accountType, accountMethod }); const trackFormSubmission = (accountType) => { const form = document.getElementById('new_new_user'); form.addEventListener('submit', () => { pushAccountSubmit(accountType, 'form'); }); }; const trackOmniAuthSubmission = (accountType) => { const links = document.querySelectorAll('.js-oauth-login'); links.forEach((link) => { const { provider } = link.dataset; link.addEventListener('click', () => { pushAccountSubmit(accountType, provider); }); }); }; export const trackFreeTrialAccountSubmissions = () => { if (!isSupported()) { return; } trackFormSubmission('freeThirtyDayTrial'); trackOmniAuthSubmission('freeThirtyDayTrial'); }; export const trackNewRegistrations = () => { if (!isSupported()) { return; } trackFormSubmission('standardSignUp'); trackOmniAuthSubmission('standardSignUp'); }; export const trackSaasTrialSubmit = () => { if (!isSupported()) { return; } pushEvent('saasTrialSubmit'); }; export const trackSaasTrialSkip = () => { if (!isSupported()) { return; } const skipLink = document.querySelector('.js-skip-trial'); skipLink.addEventListener('click', () => { pushEvent('saasTrialSkip'); }); }; export const trackSaasTrialGroup = () => { if (!isSupported()) { return; } const form = document.querySelector('.js-saas-trial-group'); form.addEventListener('submit', () => { pushEvent('saasTrialGroup'); }); }; export const trackProjectImport = () => { if (!isSupported()) { return; } const importButtons = document.querySelectorAll('.js-import-project-btn'); importButtons.forEach((button) => { button.addEventListener('click', () => { const { platform } = button.dataset; pushEvent('projectImport', { platform }); }); }); }; export const trackSaasTrialGetStarted = () => { if (!isSupported()) { return; } const getStartedButton = document.querySelector('.js-get-started-btn'); getStartedButton.addEventListener('click', () => { pushEvent('saasTrialGetStarted'); }); }; export const trackTrialAcceptTerms = () => { if (!isSupported()) { return; } pushEvent('saasTrialAcceptTerms'); }; export const trackCheckout = (selectedPlan, quantity) => { if (!isSupported()) { return; } const product = generateProductInfo(selectedPlan, quantity); if (Object.keys(product).length === 0) { return; } const eventData = { ecommerce: { currencyCode: 'USD', checkout: { actionField: { step: 1 }, products: [product], }, }, }; // eslint-disable-next-line @gitlab/require-i18n-strings pushEnhancedEcommerceEvent('EECCheckout', eventData); }; export const getNamespaceId = () => { return window.gl.snowplowStandardContext?.data?.namespace_id || EMPTY_NAMESPACE_ID_VALUE; }; export const trackTransaction = (transactionDetails) => { if (!isSupported()) { return; } const transactionId = uuidv4(); const { paymentOption, revenue, tax, selectedPlan, quantity } = transactionDetails; const product = generateProductInfo(selectedPlan, quantity); const namespaceId = getNamespaceId(); if (Object.keys(product).length === 0) { return; } const eventData = { ecommerce: { currencyCode: 'USD', purchase: { actionField: { id: transactionId, affiliation: 'GitLab', option: paymentOption, revenue: revenue.toString(), tax: tax.toString(), }, products: [{ ...product, dimension36: namespaceId }], }, }, }; pushEnhancedEcommerceEvent('EECtransactionSuccess', eventData); }; export const pushEECproductAddToCartEvent = () => { if (!isSupported()) { return; } window.dataLayer.push({ event: 'EECproductAddToCart', ecommerce: { currencyCode: 'USD', add: { products: [ { name: 'CI/CD Minutes', id: '0003', price: '10', brand: 'GitLab', category: 'DevOps', variant: 'add-on', quantity: 1, }, ], }, }, }); }; export const trackAddToCartUsageTab = () => { const getStartedButton = document.querySelector('.js-buy-additional-minutes'); if (!getStartedButton) { return; } getStartedButton.addEventListener('click', pushEECproductAddToCartEvent); }; export const trackCombinedGroupProjectForm = () => { if (!isSupported()) { return; } const form = document.querySelector('.js-groups-projects-form'); form.addEventListener('submit', () => { pushEvent('combinedGroupProjectFormSubmit'); }); }; export const trackCompanyForm = (aboutYourCompanyType) => { if (!isSupported()) { return; } pushEvent('aboutYourCompanyFormSubmit', { aboutYourCompanyType }); }; export const saasTrialWelcome = () => { if (!isSupported()) { return; } const saasTrialWelcomeButton = document.querySelector('.js-trial-welcome-btn'); saasTrialWelcomeButton?.addEventListener('click', () => { pushEvent('saasTrialWelcome'); }); }; export const saasTrialContinuousOnboarding = () => { if (!isSupported()) { return; } const getStartedButton = document.querySelector('.js-get-started-btn'); getStartedButton?.addEventListener('click', () => { pushEvent('saasTrialContinuousOnboarding'); }); };