Skip to content

Commit 5b2de60

Browse files
authored
Append UTM query params (#2430)
1 parent 69d1922 commit 5b2de60

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

frontends/main/src/page-components/LearningResourceExpanded/CallToActionSection.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
import type { User } from "api/hooks/user"
3030
import { PostHogEvents } from "@/common/constants"
3131
import VideoFrame from "./VideoFrame"
32+
import { kebabCase } from "lodash"
3233

3334
const showChatClass = "show-chat"
3435
const showChatSelector = `.${showChatClass} &`
@@ -262,6 +263,23 @@ const getCallToActionText = (resource: LearningResource): string => {
262263
}
263264
}
264265

266+
const buildCtaUrl = (url?: string | null, resourceTitle?: string) => {
267+
if (!url) return "#"
268+
try {
269+
const parsedUrl = new URL(url)
270+
parsedUrl.searchParams.set("utm_source", "mit-learn")
271+
parsedUrl.searchParams.set("utm_medium", "referral")
272+
if (resourceTitle) {
273+
parsedUrl.searchParams.set("utm_content", kebabCase(resourceTitle))
274+
}
275+
return parsedUrl.toString()
276+
} catch {
277+
const separator = url.includes("?") ? "&" : "?"
278+
const utm = `utm_source=mit-learn&utm_medium=referral${resourceTitle ? `&utm_content=${kebabCase(resourceTitle)}` : ""}`
279+
return `${url}${separator}${utm}`
280+
}
281+
}
282+
265283
const CallToActionSection = ({
266284
imgConfig,
267285
resource,
@@ -322,7 +340,7 @@ const CallToActionSection = ({
322340
target="_blank"
323341
size="medium"
324342
endIcon={<RiExternalLinkLine />}
325-
href={resource.url || ""}
343+
href={buildCtaUrl(resource.url, resource.title)}
326344
onClick={() => {
327345
if (process.env.NEXT_PUBLIC_POSTHOG_API_KEY) {
328346
posthog.capture(PostHogEvents.CallToActionClicked, { resource })

frontends/main/src/page-components/LearningResourceExpanded/LearningResourceExpanded.test.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { PLATFORM_LOGOS } from "ol-components"
1010
import user from "@testing-library/user-event"
1111
import { renderWithProviders } from "@/test-utils"
1212
import { useFeatureFlagEnabled } from "posthog-js/react"
13+
import { kebabCase } from "lodash"
1314

1415
jest.mock("posthog-js/react")
1516
const mockedUseFeatureFlagEnabled = jest
@@ -95,7 +96,9 @@ describe("Learning Resource Expanded", () => {
9596
name: linkName,
9697
}) as HTMLAnchorElement
9798
expect(link.target).toBe("_blank")
98-
expect(link.href).toMatch(new RegExp(`^${resource.url}/?$`))
99+
expect(link.href).toBe(
100+
`${resource.url?.replace(/\/$/, "")}/?utm_source=mit-learn&utm_medium=referral&utm_content=${kebabCase(resource.title)}`,
101+
)
99102
}
100103
},
101104
)
@@ -134,9 +137,10 @@ describe("Learning Resource Expanded", () => {
134137
})
135138

136139
test.each([ResourceTypeEnum.Program, ResourceTypeEnum.LearningPath])(
137-
'Renders CTA button for resource type "%s"',
140+
'Renders CTA button for resource type "%s" with UTM params',
138141
(resourceType) => {
139142
const resource = factories.learningResources.resource({
143+
title: "Test Resource",
140144
resource_type: resourceType,
141145
})
142146

@@ -148,7 +152,9 @@ describe("Learning Resource Expanded", () => {
148152
name: linkName,
149153
}) as HTMLAnchorElement
150154

151-
expect(link.href).toMatch(new RegExp(`^${resource.url}/?$`))
155+
expect(link.href).toBe(
156+
`${resource.url?.replace(/\/$/, "")}/?utm_source=mit-learn&utm_medium=referral&utm_content=test-resource`,
157+
)
152158
expect(link.getAttribute("data-ph-action")).toBe("click-cta")
153159
}
154160
},

0 commit comments

Comments
 (0)