feat: implement PostHog event tracking for user interactions#3218
Conversation
OpenAPI ChangesNo changes detected Unexpected changes? Ensure your branch is up-to-date with |
0e5962e to
5f8329e
Compare
There was a problem hiding this comment.
Pull request overview
Adds PostHog analytics instrumentation for key user interactions across the Learn UI (resource cards, CTAs, AskTIM entry points, and MITxOnline product pages), supporting HQ issue tracking requirements.
Changes:
- Introduces new PostHog event names (
course_card_clicked,asktim_clicked) and captures them in several UI entry points. - Adds CTA click labeling for
cta_clickedand updates the corresponding unit test expectation. - Enables click handlers to run for
LinkAdapter“shallow” navigation (query-param pushState), so analytics can be captured for shallow links.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| frontends/ol-components/src/components/LinkAdapter/LinkAdapter.tsx | Ensures onClick runs even for shallow pushState links. |
| frontends/main/src/page-components/ResourceCarousel/ResourceCarousel.tsx | Captures course_card_clicked for carousel card interactions. |
| frontends/main/src/page-components/LearningResourceExpanded/CallToActionSection.tsx | Adds label to cta_clicked payload for drawer CTAs. |
| frontends/main/src/page-components/LearningResourceExpanded/CallToActionSection.test.tsx | Updates test to assert label is included in capture payload. |
| frontends/main/src/page-components/LearningResourceExpanded/AiChatSyllabusSlideDown.tsx | Captures asktim_clicked for syllabus-bot toggling. |
| frontends/main/src/page-components/AiChat/AskTimDrawerButton.tsx | Captures asktim_clicked for opening the homepage recommender drawer via shallow link. |
| frontends/main/src/common/constants.ts | Adds new PostHog event constants. |
| frontends/main/src/app-pages/ProductPages/ProgramPage.tsx | Passes section label into MITxOnline requirement cards for analytics context. |
| frontends/main/src/app-pages/ProductPages/ProgramEnrollmentButton.tsx | Captures cta_clicked for program enrollment button clicks. |
| frontends/main/src/app-pages/ProductPages/MitxOnlineResourceCard.tsx | Captures course_card_clicked for MITxOnline product requirement cards. |
| frontends/main/src/app-pages/ProductPages/CourseEnrollmentButton.tsx | Captures cta_clicked for course enrollment button clicks. |
| if (process.env.NEXT_PUBLIC_POSTHOG_API_KEY) { | ||
| posthog.capture(PostHogEvents.CallToActionClicked, { | ||
| program, | ||
| label: program.title, | ||
| }) | ||
| } |
There was a problem hiding this comment.
ProgramEnrollmentButton has a comprehensive test suite, but the new PostHog tracking path isn’t covered. Add a test that sets NEXT_PUBLIC_POSTHOG_API_KEY, mocks usePostHog().capture, clicks the enroll button, and asserts cta_clicked is captured with the expected properties (and that it does not fire when the env var is unset).
| if (process.env.NEXT_PUBLIC_POSTHOG_API_KEY) { | ||
| posthog.capture(PostHogEvents.CallToActionClicked, { | ||
| course, | ||
| label: course.title, | ||
| }) | ||
| } |
There was a problem hiding this comment.
CourseEnrollmentButton has an existing test suite, but the new PostHog tracking path isn’t covered. Add a test that sets NEXT_PUBLIC_POSTHOG_API_KEY, mocks usePostHog().capture, triggers a click in an authenticated scenario, and asserts cta_clicked is captured with the expected payload.
gumaerc
left a comment
There was a problem hiding this comment.
I tested this and see tracking events flowing through, but there are a few things we should address:
Firstly, there is a bit of missing test coverage I think we should add, and I had AI summarize it:
-
Home page UAI card click tracking
- File: frontends/main/src/app-pages/HomePage/HomePage.test.tsx
- Add one test in the existing UAI Announcement Card describe block:
- Enable UniversalAI flag
- Click Learn about Universal AI link
- Assert mocked capture was called with cta_clicked and payload including label plus readableId
-
Search page UAI banner click tracking
- File: frontends/main/src/app-pages/SearchPage/SearchPage.test.tsx
- Add one test in the existing UniversalAIBanner describe block:
- Enable UniversalAISearchBanner flag with matching search term
- Click Learn More link
- Assert mocked capture was called with cta_clicked and payload including label plus readableId
-
AskTIM recommendation button click tracking
- File: frontends/main/src/page-components/AiChat/AskTimDrawerButton.test.tsx
- Add one test:
- Click Ask TIM link
- Assert mocked capture called with asktim_clicked and type recommendation_bot
-
AskTIM syllabus button click tracking
- File: frontends/main/src/page-components/LearningResourceExpanded/AiChatSyllabusSlideDown.test.tsx
- Add one test:
- Render opener with a course/program resource
- Click Ask TIM about this ...
- Assert mocked capture called with asktim_clicked and syllabus payload fields
-
Carousel card click tracking
- File: frontends/main/src/page-components/ResourceCarousel/ResourceCarousel.test.tsx
- Add one test:
- Render carousel with at least one resource
- Click card
- Assert mocked capture called with course_card_clicked and key payload fields (label/resource id/readable id)
-
Product page requirement card tracking
- File: frontends/main/src/app-pages/ProductPages/ProgramPage.test.tsx
- Add one test:
- Click a requirement card rendered via MitxOnlineResourceCard
- Assert mocked capture called with course_card_clicked
-
Enrollment CTA tracking branch behavior
- Files:
- Add one authenticated click test per file:
- Assert cta_clicked is captured
- Optional but useful:
- Add one unauthenticated click test per file asserting no capture (if that is intended behavior)
| @@ -91,6 +94,14 @@ const CourseEnrollmentButton: React.FC<CourseEnrollmentButtonProps> = ({ | |||
| if (me.isLoading) { | |||
| return | |||
| } else if (me.data?.is_authenticated) { | |||
There was a problem hiding this comment.
Currently this checks if the user is authenticated before firing the tracking event. Unauthenticated clicks should be tracked as well.
| const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => { | ||
| if (enrollments.isLoading || me.isLoading) { | ||
| return | ||
| } else if (me.data?.is_authenticated) { |
There was a problem hiding this comment.
Similarly here, we need to also track unauthenticated clicks.
…d and UniversalAIBanner
5ccb9f3 to
f587709
Compare
…ssertion Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e.error Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
What are the relevant tickets?
https://github.com/mitodl/hq/issues/10916
Description (What does it do?)
Adds PostHog analytics event tracking for user interactions:
How can this be tested?
env/frontend.local.env:
Ensure you have courses and programs product setup on your local mitxonline http://mitxonline.odl.local:8013/api/v2/programs/
env/shared.local.env:
course_card_clicked
cta_clicked
asktim_clicked
Additional Context