Skip to content

Commit 2cf23ad

Browse files
authored
feat: add PostHog tracking for onboarding CTA interactions (#3362)
* feat: add PostHog tracking for onboarding CTA interactions * feedback
1 parent 240511e commit 2cf23ad

2 files changed

Lines changed: 60 additions & 0 deletions

File tree

frontends/main/src/app-pages/OnboardingPage/OnboardingPage.test.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ import {
1919
type Profile,
2020
} from "api/v0"
2121
import OnboardingPage from "./OnboardingPage"
22+
import { usePostHog } from "posthog-js/react"
23+
import { PostHogEvents } from "@/common/constants"
24+
25+
jest.mock("posthog-js/react", () => ({
26+
...jest.requireActual("posthog-js/react"),
27+
usePostHog: jest.fn(),
28+
}))
29+
const mockCapture = jest.fn()
30+
jest.mocked(usePostHog).mockReturnValue(
31+
// @ts-expect-error Not mocking all of posthog
32+
{ capture: mockCapture },
33+
)
2234

2335
jest.mock("next/navigation", () =>
2436
jest.requireActual("next-router-mock/navigation"),
@@ -167,4 +179,41 @@ describe("OnboardingPage", () => {
167179

168180
expect(mockRouter.asPath).toEqual("/search?resource=184")
169181
})
182+
183+
describe("PostHog tracking", () => {
184+
beforeEach(() => {
185+
process.env.NEXT_PUBLIC_POSTHOG_API_KEY = "test-key"
186+
mockCapture.mockReset()
187+
})
188+
189+
afterEach(() => {
190+
delete process.env.NEXT_PUBLIC_POSTHOG_API_KEY
191+
})
192+
193+
it("fires cta_clicked with label 'Next' and step when Next is clicked", async () => {
194+
await setupAndProgressToStep(0)
195+
await user.click(await findNextButton())
196+
expect(mockCapture).toHaveBeenCalledWith(
197+
PostHogEvents.CallToActionClicked,
198+
{ label: "Next", step: 1, location: "onboarding" },
199+
)
200+
})
201+
202+
it("fires cta_clicked with label 'Finish' and step when Finish is clicked", async () => {
203+
await setupAndProgressToStep(STEPS_DATA.length - 1)
204+
mockCapture.mockClear()
205+
await user.click(await findFinishButton())
206+
expect(mockCapture).toHaveBeenCalledWith(
207+
PostHogEvents.CallToActionClicked,
208+
{ label: "Finish", step: STEPS_DATA.length, location: "onboarding" },
209+
)
210+
})
211+
212+
it("does not fire cta_clicked when NEXT_PUBLIC_POSTHOG_API_KEY is not set", async () => {
213+
delete process.env.NEXT_PUBLIC_POSTHOG_API_KEY
214+
await setupAndProgressToStep(0)
215+
await user.click(await findNextButton())
216+
expect(mockCapture).not.toHaveBeenCalled()
217+
})
218+
})
170219
})

frontends/main/src/app-pages/OnboardingPage/OnboardingPage.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import React, { useEffect, useId, useMemo } from "react"
44
import { useRouter } from "next-nprogress-bar"
5+
import { usePostHog } from "posthog-js/react"
56
import {
67
styled,
78
Step,
@@ -33,6 +34,7 @@ import {
3334
ProfileSchema,
3435
} from "@/common/profile"
3536
import { useSearchParams } from "next/navigation"
37+
import { PostHogEvents } from "@/common/constants"
3638

3739
const NUM_STEPS = 5
3840

@@ -155,6 +157,7 @@ const OnboardingPage: React.FC = () => {
155157
const { isLoading: userLoading, data: user } = useUserMe()
156158
const [activeStep, setActiveStep] = React.useState<number>(0)
157159
const router = useRouter()
160+
const posthog = usePostHog()
158161
const searchParams = useSearchParams()
159162
const nextUrl = searchParams.get("next")
160163

@@ -169,6 +172,14 @@ const OnboardingPage: React.FC = () => {
169172
topic_interests: values.topic_interests.map((id) => parseInt(id)),
170173
})
171174
}
175+
const label = activeStep < NUM_STEPS - 1 ? "Next" : "Finish"
176+
if (process.env.NEXT_PUBLIC_POSTHOG_API_KEY) {
177+
posthog.capture(PostHogEvents.CallToActionClicked, {
178+
label,
179+
step: activeStep + 1,
180+
location: "onboarding",
181+
})
182+
}
172183
if (activeStep < NUM_STEPS - 1) {
173184
setActiveStep((prevActiveStep) => prevActiveStep + 1)
174185
} else {

0 commit comments

Comments
 (0)