From 5332b4e4a265ae49086f4c9d26d38e79476d4fb6 Mon Sep 17 00:00:00 2001 From: Chris Bongers Date: Fri, 14 Mar 2025 14:09:06 +0200 Subject: [PATCH 1/3] feat: analytics events for credits/awards --- .../src/components/award/AwardButton.tsx | 4 + .../comments/CommentActionButtons.tsx | 1 + .../src/components/cores/CoreOptionButton.tsx | 10 +- .../components/credit/BuyCreditsButton.tsx | 13 ++- .../components/modals/award/BuyCoresModal.tsx | 9 +- .../modals/award/GiveAwardModal.tsx | 67 ++++++++--- .../shared/src/contexts/BuyCoresContext.tsx | 6 + .../src/contexts/GiveAwardModalContext.tsx | 74 +++++++++++- packages/shared/src/lib/log.ts | 18 +++ packages/webapp/pages/earnings.tsx | 105 ++++++++++++++---- 10 files changed, 268 insertions(+), 39 deletions(-) diff --git a/packages/shared/src/components/award/AwardButton.tsx b/packages/shared/src/components/award/AwardButton.tsx index ec0bdf7d94..f9c2c76c02 100644 --- a/packages/shared/src/components/award/AwardButton.tsx +++ b/packages/shared/src/components/award/AwardButton.tsx @@ -20,12 +20,14 @@ import type { } from '../../contexts/GiveAwardModalContext'; import { useRequestProtocol } from '../../hooks/useRequestProtocol'; import { getCompanionWrapper } from '../../lib/extension'; +import type { Post } from '../../graphql/posts'; type AwardButtonProps = { appendTo?: 'parent' | Element | ((ref: Element) => Element); type: AwardTypes; className?: string; entity: AwardEntity; + post?: Post; } & Pick, 'pressed' | 'variant'>; export const AwardButton = ({ appendTo: appendToProps, @@ -34,6 +36,7 @@ export const AwardButton = ({ entity, pressed, variant = ButtonVariant.Tertiary, + post, }: AwardButtonProps): ReactElement => { const { isCompanion } = useRequestProtocol(); const { user, showLogin } = useAuthContext(); @@ -49,6 +52,7 @@ export const AwardButton = ({ props: { type, entity, + post, }, }); }; diff --git a/packages/shared/src/components/comments/CommentActionButtons.tsx b/packages/shared/src/components/comments/CommentActionButtons.tsx index da6ac355c3..d927f80620 100644 --- a/packages/shared/src/components/comments/CommentActionButtons.tsx +++ b/packages/shared/src/components/comments/CommentActionButtons.tsx @@ -365,6 +365,7 @@ export default function CommentActionButtons({ numAwards: comment.numAwards, }} pressed={!!comment.userState?.awarded} + post={post} /> {!!comment.numAwards && ( { const isMobile = useViewSize(ViewSize.MobileL); - const { selectedProduct, setSelectedProduct, openCheckout } = + const { logEvent } = useLogContext(); + const { selectedProduct, setSelectedProduct, openCheckout, origin } = useBuyCoresContext(); const onSelect = useCallback(() => { + // TODO: Amount should be deducted from selected product entity + logEvent({ + event_name: LogEvent.SelectCreditsQuantity, + extra: JSON.stringify({ origin, amount: id }), + }); setSelectedProduct(id); if (!isMobile) { openCheckout({ priceId: id }); diff --git a/packages/shared/src/components/credit/BuyCreditsButton.tsx b/packages/shared/src/components/credit/BuyCreditsButton.tsx index 67df70c144..d86d0dc531 100644 --- a/packages/shared/src/components/credit/BuyCreditsButton.tsx +++ b/packages/shared/src/components/credit/BuyCreditsButton.tsx @@ -7,6 +7,8 @@ import Link from '../utilities/Link'; import { webappUrl } from '../../lib/constants'; import { anchorDefaultRel } from '../../lib/strings'; import { isIOSNative } from '../../lib/func'; +import { LogEvent, Origin } from '../../lib/log'; +import { useLogContext } from '../../contexts/LogContext'; type BuyCreditsButtonProps = { onPlusClick: () => void; @@ -17,6 +19,15 @@ export const BuyCreditsButton = ({ hideBuyButton, }: BuyCreditsButtonProps): ReactElement => { const renderBuyButton = !isIOSNative() && !hideBuyButton; + const { logEvent } = useLogContext(); + const trackBuyCredits = () => { + logEvent({ + event_name: LogEvent.StartBuyingCredits, + extra: JSON.stringify({ origin: Origin.Award }), + }); + onPlusClick(); + }; + return (
@@ -38,7 +49,7 @@ export const BuyCreditsButton = ({ variant={ButtonVariant.Tertiary} icon={} size={ButtonSize.Small} - onClick={onPlusClick} + onClick={trackBuyCredits} /> ) : null} diff --git a/packages/shared/src/components/modals/award/BuyCoresModal.tsx b/packages/shared/src/components/modals/award/BuyCoresModal.tsx index 1f88c926bc..9283bd0edc 100644 --- a/packages/shared/src/components/modals/award/BuyCoresModal.tsx +++ b/packages/shared/src/components/modals/award/BuyCoresModal.tsx @@ -24,6 +24,7 @@ import { IconSize } from '../../Icon'; import useDebounceFn from '../../../hooks/useDebounceFn'; import { CoreOptionList } from '../../cores/CoreOptionList'; import { CoreAmountNeeded } from '../../cores/CoreAmountNeeded'; +import type { Origin } from '../../../lib/log'; const CoreOptions = () => { return ( @@ -182,14 +183,20 @@ const ModalRender = ({ ...props }: ModalProps) => { }; type BuyCoresModalProps = ModalProps & { + origin: typeof Origin; onCompletion?: () => void; }; export const BuyCoresModal = ({ + origin, onCompletion, ...props }: BuyCoresModalProps): ReactElement => { return ( - + ); diff --git a/packages/shared/src/components/modals/award/GiveAwardModal.tsx b/packages/shared/src/components/modals/award/GiveAwardModal.tsx index 4dc891169b..12a329830d 100644 --- a/packages/shared/src/components/modals/award/GiveAwardModal.tsx +++ b/packages/shared/src/components/modals/award/GiveAwardModal.tsx @@ -1,5 +1,5 @@ import type { ReactElement } from 'react'; -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import classNames from 'classnames'; import { useMutation, useQuery } from '@tanstack/react-query'; @@ -38,15 +38,22 @@ import { labels } from '../../../lib'; import type { ApiErrorResult } from '../../../graphql/common'; import { generateQueryKey, RequestKey } from '../../../lib/query'; import { useAuthContext } from '../../../contexts/AuthContext'; +import { Origin } from '../../../lib/log'; +import type { Post } from '../../../graphql/posts'; const AwardItem = ({ item }: { item: Product }) => { - const { setActiveStep } = useGiveAwardModalContext(); + const { setActiveStep, logAwardEvent } = useGiveAwardModalContext(); + + const onClick = useCallback(() => { + logAwardEvent({ awardEvent: 'PICK', extra: { award: item.value } }); + setActiveStep({ screen: 'COMMENT', product: item }); + }, [item, logAwardEvent, setActiveStep]); return ( @@ -333,11 +381,30 @@ const Earnings = (): ReactElement => {
- - - + + +
- +
From a228d93f47ec87c1b3bad464514c6c834eb542ae Mon Sep 17 00:00:00 2001 From: Chris Bongers Date: Fri, 14 Mar 2025 14:29:46 +0200 Subject: [PATCH 2/3] Update packages/shared/src/contexts/GiveAwardModalContext.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/shared/src/contexts/GiveAwardModalContext.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/shared/src/contexts/GiveAwardModalContext.tsx b/packages/shared/src/contexts/GiveAwardModalContext.tsx index a7b80205b4..520a1c1a0b 100644 --- a/packages/shared/src/contexts/GiveAwardModalContext.tsx +++ b/packages/shared/src/contexts/GiveAwardModalContext.tsx @@ -50,9 +50,9 @@ const AwardTypeToTrackingEvent: Record< AWARD: LogEvent.AwardPost, }, COMMENT: { - START: LogEvent.StartAwardPost, - PICK: LogEvent.PickAwardPost, - AWARD: LogEvent.AwardPost, + START: LogEvent.StartAwardComment, + PICK: LogEvent.PickAwardComment, + AWARD: LogEvent.AwardComment, }, }; From f7e1f5af856540ed90ec33b40614b0b03b61b0bf Mon Sep 17 00:00:00 2001 From: Chris Bongers Date: Fri, 14 Mar 2025 14:42:19 +0200 Subject: [PATCH 3/3] fix: type issues --- packages/shared/src/components/cores/CoreOptionButton.tsx | 2 +- packages/shared/src/components/modals/award/BuyCoresModal.tsx | 2 +- packages/shared/src/contexts/BuyCoresContext.tsx | 4 ++-- packages/webapp/pages/cores/index.tsx | 4 +++- packages/webapp/pages/earnings.tsx | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/shared/src/components/cores/CoreOptionButton.tsx b/packages/shared/src/components/cores/CoreOptionButton.tsx index 176b34a049..252991ba5c 100644 --- a/packages/shared/src/components/cores/CoreOptionButton.tsx +++ b/packages/shared/src/components/cores/CoreOptionButton.tsx @@ -33,7 +33,7 @@ export const CoreOptionButton = ({ if (!isMobile) { openCheckout({ priceId: id }); } - }, [id, isMobile, openCheckout, setSelectedProduct]); + }, [id, isMobile, logEvent, openCheckout, origin, setSelectedProduct]); return (