Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup features and faq analytics #270

Merged
merged 2 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/components/faqs/PlannerFaqs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import classNames from 'classnames'
import { Transition, Disclosure } from '@headlessui/react'
import { ChevronUpIcon } from '@heroicons/react/24/outline'
import { AnalyticsTracker } from '../../utils/AnalyticsTracker'

const PlannerFaqs = () => {
const data = [
Expand Down Expand Up @@ -158,7 +159,14 @@ const PlannerFaqs = () => {
as="div"
defaultOpen={faqIdx === 0}
key={`planner-faq-${faqIdx}`}
className="rounded-2xl bg-white p-3 dark:bg-dark"
className={`rounded-2xl bg-white p-3 dark:bg-dark faq-disclosure-${faqIdx}`}
onClick={() => {
const disclosure = document.querySelector(`.faq-disclosure-${faqIdx}`);
const isOpen = disclosure?.getAttribute('data-headlessui-state') !== 'open';
if (isOpen && faq.question.type === 'span') {
AnalyticsTracker.trackFaq(faq.question.props.children)
}
}}
>
{({ open }) => (
<>
Expand Down
3 changes: 3 additions & 0 deletions src/components/planner/schedule/PrintSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Button } from '../../ui/button'
import { CameraIcon } from '@heroicons/react/24/outline'
import { toPng } from 'html-to-image'
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '../../ui/tooltip'
import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker'

const PrintSchedule = ({ component }) => {
const { enabled } = useContext(ThemeContext)
Expand All @@ -24,6 +25,8 @@ const PrintSchedule = ({ component }) => {
.catch((err) => {
console.log(err)
})

AnalyticsTracker.trackFeature(Feature.SCREENSHOT)
},
[component]
)
Expand Down
6 changes: 5 additions & 1 deletion src/components/planner/schedule/ToggleScheduleGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Button } from '../../ui/button'
import { ViewColumnsIcon } from '@heroicons/react/24/outline'
import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from '../../ui/tooltip'
import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker'

const ToggleScheduleGrid = ({ showGridHook }) => {
const [showGrid, setShowGrid] = showGridHook
Expand All @@ -12,7 +13,10 @@ const ToggleScheduleGrid = ({ showGridHook }) => {
<Button
variant="icon"
className="bg-lightish text-black dark:bg-darkish dark:text-white"
onClick={() => setShowGrid(!showGrid)}
onClick={() => {
setShowGrid(!showGrid)
AnalyticsTracker.trackFeature(Feature.GRID)
}}
>
<ViewColumnsIcon className="h-5 w-5" />
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { teacherIdsFromCourseInfo, uniqueTeachersFromCourseInfo, getAllPickedSlo
import { Button } from '../../../ui/button'
import ProfessorItem from './ProfessorItem'
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from '../../../ui/dropdown-menu'
import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'
import ClassSelectorDropdownController from './ClassSelectorDropdownController'

type Props = {
Expand Down Expand Up @@ -58,6 +59,8 @@ const ClassSelector = ({ course }: Props) => {
newMultipleOptions[selectedOption].course_options = courseOptions;
setMultipleOptions(newMultipleOptions);
setLocked(!locked)

AnalyticsTracker.trackFeature(Feature.LOCK_TOGGLE);
}

useEffect(() => {
Expand Down
4 changes: 4 additions & 0 deletions src/components/planner/sidebar/OptionsController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { EllipsisHorizontalIcon } from '@heroicons/react/24/outline'
import { useContext } from 'react'
import MultipleOptionsContext from '../../../contexts/MultipleOptionsContext';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../ui/tooltip';
import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker';

/**
* Sortable list of schedule options
Expand All @@ -28,6 +29,9 @@ const OptionsController = () => {
animation={200}
delay={2}
multiDrag
onEnd={() => {
AnalyticsTracker.trackFeature(Feature.OPTION_REORDER);
}}
>
{multipleOptions.map((option: Option) => (
<OptionButton
Expand Down
8 changes: 6 additions & 2 deletions src/components/planner/sidebar/SelectedOptionController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CourseOption } from '../../../@types'
import { ThemeContext } from '../../../contexts/ThemeContext'
import { Popover, PopoverContent, PopoverTrigger } from '../../ui/popover'
import RandomFill from './selectedOptionController/RandomFill'
import { AnalyticsTracker, Feature } from '../../../utils/AnalyticsTracker'

type Props = {
currentOption: CourseOption[]
Expand Down Expand Up @@ -62,15 +63,18 @@ const SelectedOptionController = ({
)
return updatedMultipleOptions;
})
AnalyticsTracker.trackFeature(Feature.OPTION_RENAME);
}

const changeOptionIcon = (newIcon) => {
setMultipleOptions((prevMultipleOptions) => {
const updatedMultipleOptions = prevMultipleOptions.map((item) =>
item.id === multipleOptions[selectedOption].id ? { ...item, icon: newIcon } : item
item.id === multipleOptions[selectedOption].id ? { ...item, icon: newIcon.imageUrl } : item
)
return updatedMultipleOptions;
})
AnalyticsTracker.trackFeature(Feature.OPTION_EMOJI);
AnalyticsTracker.emoji(newIcon.emoji);
}

return (
Expand All @@ -92,7 +96,7 @@ const SelectedOptionController = ({
suggestedEmojisMode={SuggestionMode.RECENT}
emojiStyle={EmojiStyle.APPLE}
onEmojiClick={(emojiData, e) => {
changeOptionIcon(emojiData.imageUrl)
changeOptionIcon(emojiData)
setEmojiPickerOpen(false)
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { useToast } from '../../../ui/use-toast'
import { Buffer } from 'buffer'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../../../ui/tooltip'
import { CourseOption } from '../../../../@types'
import { plausible } from '../../../../utils'
import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'

type Props = {
currentOption: CourseOption[]
Expand Down Expand Up @@ -48,6 +50,7 @@ const CopyOption = ({ currentOption, className }: Props) => {
setTimeout(() => {
setIcon(false)
}, 1500)
AnalyticsTracker.trackFeature(Feature.COPY);
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
import { convertCourseInfoToCourseOption } from '../../../../utils'
import { Button } from '../../../ui/button'
import { useToast } from '../../../ui/use-toast'
import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'

const PasteOption = () => {
const { multipleOptions, setMultipleOptions, selectedOption } = useContext(MultipleOptionsContext)
Expand Down Expand Up @@ -97,6 +98,8 @@ const PasteOption = () => {
description: 'A opção foi colada com sucesso',
duration: 1500,
})

AnalyticsTracker.trackFeature(Feature.PASTE);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Checkbox } from '../../../ui/checkbox'
import { Separator } from '../../../ui/separator'
import CourseContext from '../../../../contexts/CourseContext'
import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'

type Props = {
className?: string
Expand Down Expand Up @@ -165,6 +166,8 @@ const RandomFill = ({ className }: Props) => {
// Choose a random permutation
const randomNumber = Math.floor(Math.random() * (newPermutations.length - 1))
applySchedule(newPermutations[randomNumber])

AnalyticsTracker.trackFeature(Feature.RANDOM_FILL);
}

const applySchedule = (classesCombinations: ClassInfo[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ArrowUpOnSquareIcon } from '@heroicons/react/24/outline'
import { useContext } from 'react'
import CourseContext from '../../../../contexts/CourseContext'
import MultipleOptionsContext from '../../../../contexts/MultipleOptionsContext'
import { AnalyticsTracker, Feature } from '../../../../utils/AnalyticsTracker'

//TODO: utils??
const csvEncode = (text: string | null | undefined) => {
Expand Down Expand Up @@ -43,6 +44,8 @@ const CsvExport = () => {
a.download = 'schedule.csv'
a.click()
URL.revokeObjectURL(url)

AnalyticsTracker.trackFeature(Feature.EXPORT_TO_CSV)
}

return (
Expand All @@ -52,7 +55,7 @@ const CsvExport = () => {
>
<ArrowUpOnSquareIcon className="h-5 w-5 text-secondary black:hover:brightness-200" />
<span className="pl-1"> Exportar Opções (CSV)</span>
</button>
</button>
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import MajorContext from '../../../../../contexts/MajorContext'
import { cn, plausible } from '../../../../../utils'
import { Button } from '../../../../ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '../../../../ui/popover'
import { AnalyticsTracker } from '../../../../../utils/AnalyticsTracker'

interface Props {
selectedMajor: Major | null
Expand Down Expand Up @@ -77,9 +78,7 @@ const MajorSearchCombobox = ({ selectedMajor, setSelectedMajor }: Props) => {
setSelectedMajor(currentMajor.id === selectedMajor?.id ? null : currentMajor)
setOpen(false)

const { trackEvent } = plausible
trackEvent('Major Selected', { props: { major: currentMajor.name } })
trackEvent('Faculty', { props: { faculty: currentMajor.faculty_id.toUpperCase() } })
AnalyticsTracker.majorSelected(currentMajor)
}}
>
{`${major.name} (${major.acronym}) - ${major.faculty_id.toUpperCase()}`}
Expand Down
50 changes: 50 additions & 0 deletions src/utils/AnalyticsTracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

import Plausible from "plausible-tracker";
import { Major } from "../@types";

const plausible = Plausible({
domain: import.meta.env.VITE_APP_PLAUSIBLE_DOMAIN,
apiHost: import.meta.env.VITE_APP_PLAUSIBLE_HOST,
trackLocalhost: !Number(import.meta.env.VITE_APP_PROD),
})

const { trackEvent } = plausible;

export enum Feature {
COPY = 'Copy Schedule',
PASTE = 'Paste Schedule',
RANDOM_FILL = 'Random Fill',

OPTION_REORDER = 'Options Order Changed',
OPTION_RENAME = 'Option Renamed',
OPTION_EMOJI = 'Schedule Emoji Changed',

SCREENSHOT = 'Screenshot',
GRID = 'Grid View Toggle',

EXPORT_TO_CSV = 'Export to CSV',

LOCK_TOGGLE = 'Class Lock Toggled',
}

export class AnalyticsTracker {
static majorSelected = (major: Major) => {
if (major) {
trackEvent('Major Selected', { props: { major: major.name } })
trackEvent('Faculty', { props: { faculty: major.faculty_id.toUpperCase() } })
}
}

static trackFeature = (feature: Feature) => {
trackEvent('Feature', { props: { feature_counter: feature } })
}

static trackFaq = (faq: string) => {
if (faq) trackEvent('FAQ', { props: { faq } })
}

static emoji = (emoji: string) => {
if (emoji) trackEvent('Emoji', { props: { emoji } })
}
}