diff --git a/frontends/mit-learn/src/page-components/Dialogs/AddToListDialog.tsx b/frontends/mit-learn/src/page-components/Dialogs/AddToListDialog.tsx index 037a39031e..239b34563e 100644 --- a/frontends/mit-learn/src/page-components/Dialogs/AddToListDialog.tsx +++ b/frontends/mit-learn/src/page-components/Dialogs/AddToListDialog.tsx @@ -10,6 +10,7 @@ import { } from "ol-components" import { RiAddLine } from "@remixicon/react" +import { usePostHog } from "posthog-js/react" import * as NiceModal from "@ebay/nice-modal-react" @@ -67,6 +68,7 @@ const AddToListDialogInner: React.FC = ({ isLoading: isSavingLearningPathRelationships, mutateAsync: setLearningPathRelationships, } = useLearningResourceSetLearningPathRelationships() + const posthog = usePostHog() const isSaving = isSavingLearningPathRelationships || isSavingUserListRelationships let dialogTitle = "Add to list" @@ -93,6 +95,9 @@ const AddToListDialogInner: React.FC = ({ : null, ) .filter((value) => value !== null) + + const { POSTHOG } = APP_SETTINGS + const formik = useFormik({ enableReinitialize: true, validateOnChange: false, @@ -103,6 +108,15 @@ const AddToListDialogInner: React.FC = ({ }, onSubmit: async (values) => { if (resource) { + if (!(!POSTHOG?.api_key || POSTHOG.api_key.length < 1)) { + posthog.capture("lr_add_to_list", { + listType: listType, + resourceId: resource?.id, + readableId: resource?.readable_id, + platformCode: resource?.platform?.code, + resourceType: resource?.resource_type, + }) + } if (listType === ListType.LearningPath) { const newParents = values.learning_paths.map((id) => parseInt(id)) await setLearningPathRelationships({ diff --git a/frontends/mit-learn/src/pages/SearchPage/SearchPage.tsx b/frontends/mit-learn/src/pages/SearchPage/SearchPage.tsx index 3b8c3830cd..476945824c 100644 --- a/frontends/mit-learn/src/pages/SearchPage/SearchPage.tsx +++ b/frontends/mit-learn/src/pages/SearchPage/SearchPage.tsx @@ -20,6 +20,7 @@ import type { LearningResourceOfferor } from "api" import { useOfferorsList } from "api/hooks/learningResources" import { capitalize } from "ol-utilities" import MetaTags from "@/page-components/MetaTags/MetaTags" +import { usePostHog } from "posthog-js/react" const cssGradient = ` linear-gradient( @@ -175,6 +176,8 @@ const useFacetManifest = (resourceCategory: string | null) => { const SearchPage: React.FC = () => { const [searchParams, setSearchParams] = useSearchParams() const facetManifest = useFacetManifest(searchParams.get("resource_category")) + const posthog = usePostHog() + const { POSTHOG } = APP_SETTINGS const setPage = useCallback( (newPage: number) => { @@ -191,8 +194,11 @@ const SearchPage: React.FC = () => { [setSearchParams], ) const onFacetsChange = useCallback(() => { + if (!(!POSTHOG?.api_key || POSTHOG.api_key.length < 1)) { + posthog.capture("search_update") + } setPage(1) - }, [setPage]) + }, [setPage, posthog, POSTHOG]) const { params, diff --git a/frontends/ol-ckeditor/src/types/settings.d.ts b/frontends/ol-ckeditor/src/types/settings.d.ts index 237e6ca039..5b68d7c8b7 100644 --- a/frontends/ol-ckeditor/src/types/settings.d.ts +++ b/frontends/ol-ckeditor/src/types/settings.d.ts @@ -1,5 +1,11 @@ /* eslint-disable no-var */ +export type PostHogSettings = { + api_key: string + timeout?: int + bootstrap_flags?: Record +} + export declare global { const APP_SETTINGS: { EMBEDLY_KEY: string @@ -9,5 +15,6 @@ export declare global { PUBLIC_URL: string SITE_NAME: string CSRF_COOKIE_NAME: string + POSTHOG?: PostHogSettings } } diff --git a/frontends/ol-components/package.json b/frontends/ol-components/package.json index 8942839161..87b9df5a3c 100644 --- a/frontends/ol-components/package.json +++ b/frontends/ol-components/package.json @@ -26,6 +26,7 @@ "material-ui-popup-state": "^5.1.0", "ol-test-utilities": "0.0.0", "ol-utilities": "0.0.0", + "posthog-js": "^1.165.0", "react": "18.3.1", "react-router": "^6.22.2", "react-router-dom": "^6.22.2", diff --git a/frontends/ol-components/src/components/SearchInput/SearchInput.tsx b/frontends/ol-components/src/components/SearchInput/SearchInput.tsx index 58c6c0935a..09e711f40e 100644 --- a/frontends/ol-components/src/components/SearchInput/SearchInput.tsx +++ b/frontends/ol-components/src/components/SearchInput/SearchInput.tsx @@ -3,6 +3,7 @@ import { RiSearch2Line, RiCloseLine } from "@remixicon/react" import { Input, AdornmentButton } from "../Input/Input" import type { InputProps } from "../Input/Input" import styled from "@emotion/styled" +import { usePostHog } from "posthog-js/react" const StyledInput = styled(Input)(({ theme }) => ({ boxShadow: "0px 8px 20px 0px rgba(120, 147, 172, 0.10)", @@ -53,18 +54,32 @@ const muiInputProps = { "aria-label": "Search for" } const SearchInput: React.FC = (props) => { const { onSubmit, value } = props - const handleSubmit = useCallback(() => { - const event = { - target: { value }, - preventDefault: () => null, - } - onSubmit(event) - }, [onSubmit, value]) + const posthog = usePostHog() + const { POSTHOG } = APP_SETTINGS + + const handleSubmit = useCallback( + ( + ev: + | React.SyntheticEvent + | React.SyntheticEvent, + isEnter: boolean = false, + ) => { + const event = { + target: { value }, + preventDefault: () => null, + } + if (!(!POSTHOG?.api_key || POSTHOG.api_key.length < 1)) { + posthog.capture("search_update", { isEnter: isEnter }) + } + onSubmit(event) + }, + [onSubmit, value, posthog, POSTHOG], + ) const onInputKeyDown: React.KeyboardEventHandler = useCallback( (e) => { if (e.key !== "Enter") return - handleSubmit() + handleSubmit(e, true) }, [handleSubmit], ) diff --git a/yarn.lock b/yarn.lock index 7fa390a739..6452e2d589 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15408,6 +15408,7 @@ __metadata: material-ui-popup-state: "npm:^5.1.0" ol-test-utilities: "npm:0.0.0" ol-utilities: "npm:0.0.0" + posthog-js: "npm:^1.165.0" prop-types: "npm:^15.8.1" react: "npm:18.3.1" react-router: "npm:^6.22.2" @@ -16577,6 +16578,17 @@ __metadata: languageName: node linkType: hard +"posthog-js@npm:^1.165.0": + version: 1.165.0 + resolution: "posthog-js@npm:1.165.0" + dependencies: + fflate: "npm:^0.4.8" + preact: "npm:^10.19.3" + web-vitals: "npm:^4.0.1" + checksum: 10/4a640b90af24ffb173b4d20f27aab572437c8641b1ff48ad23e98d593fa7e94e63e660a4ce967a18eaabaf5102ecaff8a258315b47d1916e79a7f1ec7ad3bc7d + languageName: node + linkType: hard + "preact@npm:^10.19.3": version: 10.23.1 resolution: "preact@npm:10.23.1"