From 502be14109902ccf25c8a31b615825f70f123325 Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Fri, 31 Jan 2025 22:42:25 +0600 Subject: [PATCH] feat: add course GA tracking --- src/components/Analytics/analytics.ts | 8 ++++- src/components/SQLCourse/BuyButton.tsx | 50 +++++++++++++++++++++++--- src/lib/jwt.ts | 1 + 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/components/Analytics/analytics.ts b/src/components/Analytics/analytics.ts index 520eca8df..e283e4c56 100644 --- a/src/components/Analytics/analytics.ts +++ b/src/components/Analytics/analytics.ts @@ -6,6 +6,7 @@ declare global { category: string; label?: string; value?: string; + callback?: () => void; }) => void; } } @@ -17,7 +18,7 @@ declare global { * @returns void */ window.fireEvent = (props) => { - const { action, category, label, value } = props; + const { action, category, label, value, callback } = props; if (!window.gtag) { console.warn('Missing GTAG - Analytics disabled'); return; @@ -25,11 +26,16 @@ window.fireEvent = (props) => { if (import.meta.env.DEV) { console.log('Analytics event fired', props); + callback?.(); + return; } window.gtag('event', action, { event_category: category, event_label: label, value: value, + ...(callback ? { event_callback: callback } : {}), }); }; + +export {}; diff --git a/src/components/SQLCourse/BuyButton.tsx b/src/components/SQLCourse/BuyButton.tsx index 9af3858e9..1a4f1b917 100644 --- a/src/components/SQLCourse/BuyButton.tsx +++ b/src/components/SQLCourse/BuyButton.tsx @@ -2,7 +2,11 @@ import { useMutation, useQuery } from '@tanstack/react-query'; import { ArrowRightIcon } from 'lucide-react'; import { useEffect, useState } from 'react'; import { cn } from '../../lib/classname'; -import { COURSE_PURCHASE_PARAM, isLoggedIn } from '../../lib/jwt'; +import { + COURSE_PURCHASE_PARAM, + COURSE_PURCHASE_SUCCESS_PARAM, + isLoggedIn, +} from '../../lib/jwt'; import { coursePriceOptions } from '../../queries/billing'; import { courseProgressOptions } from '../../queries/course-progress'; import { queryClient } from '../../stores/query-client'; @@ -58,7 +62,19 @@ export function BuyButton(props: BuyButtonProps) { toast.loading('Creating checkout session...'); }, onSuccess: (data) => { - window.location.href = data.checkoutUrl; + if (!window.gtag) { + window.location.href = data.checkoutUrl; + return; + } + + window?.fireEvent({ + action: `${SQL_COURSE_SLUG}_begin_checkout`, + category: 'course', + label: `${SQL_COURSE_SLUG} Course Checkout Started`, + callback: () => { + window.location.href = data.checkoutUrl; + }, + }); }, onError: (error) => { console.error(error); @@ -77,6 +93,32 @@ export function BuyButton(props: BuyButtonProps) { } }, []); + useEffect(() => { + const urlParams = getUrlParams(); + const param = urlParams?.[COURSE_PURCHASE_SUCCESS_PARAM]; + if (!param) { + return; + } + + const success = param === '1'; + + if (success) { + window?.fireEvent({ + action: `${SQL_COURSE_SLUG}_purchase_complete`, + category: 'course', + label: `${SQL_COURSE_SLUG} Course Purchase Completed`, + }); + } else { + window?.fireEvent({ + action: `${SQL_COURSE_SLUG}_purchase_canceled`, + category: 'course', + label: `${SQL_COURSE_SLUG} Course Purchase Canceled`, + }); + } + + deleteUrlParam(COURSE_PURCHASE_SUCCESS_PARAM); + }, []); + const isLoadingPricing = isLoadingCourse || !coursePricing || isLoadingCourseProgress; const isAlreadyEnrolled = !!courseProgress?.enrolledAt; @@ -88,8 +130,8 @@ export function BuyButton(props: BuyButtonProps) { createCheckoutSession({ courseId: SQL_COURSE_SLUG, - success: `/courses/sql?e=1`, - cancel: `/courses/sql`, + success: `/courses/${SQL_COURSE_SLUG}?${COURSE_PURCHASE_SUCCESS_PARAM}=1`, + cancel: `/courses/${SQL_COURSE_SLUG}?${COURSE_PURCHASE_SUCCESS_PARAM}=0`, }); } diff --git a/src/lib/jwt.ts b/src/lib/jwt.ts index c40053d82..6207be59b 100644 --- a/src/lib/jwt.ts +++ b/src/lib/jwt.ts @@ -5,6 +5,7 @@ import type { AllowedOnboardingStatus } from '../api/user'; export const TOKEN_COOKIE_NAME = '__roadmapsh_jt__'; export const FIRST_LOGIN_PARAM = 'fl' as const; export const COURSE_PURCHASE_PARAM = 't'; +export const COURSE_PURCHASE_SUCCESS_PARAM = 'success'; export type TokenPayload = { id: string;