diff --git a/apps/website/app/PostHogPageView.tsx b/apps/website/app/PostHogPageView.tsx new file mode 100644 index 000000000..4b144ea43 --- /dev/null +++ b/apps/website/app/PostHogPageView.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { usePathname, useSearchParams } from "next/navigation"; +import { useEffect, Suspense } from "react"; +import { usePostHog } from "posthog-js/react"; + +function PostHogPageView() { + const pathname = usePathname(); + const searchParams = useSearchParams(); + const posthog = usePostHog(); + + useEffect(() => { + if (pathname && posthog) { + let url = window.origin + pathname; + if (searchParams.toString()) { + url = url + `?${searchParams.toString()}`; + } + posthog.capture("$pageview", { + $current_url: url, + }); + } + }, [pathname, searchParams, posthog]); + + return null; +} + +export default function SuspendedPostHogPageView() { + return ( + + + + ); +} diff --git a/apps/website/app/layout.tsx b/apps/website/app/layout.tsx index 7bf7648e9..cf9900bad 100644 --- a/apps/website/app/layout.tsx +++ b/apps/website/app/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import "./globals.css"; +import { PostHogProvider } from "./providers"; export const metadata: Metadata = { title: "Discourse Graphs | A Tool for Collaborative Knowledge Synthesis", @@ -24,7 +25,9 @@ export default function RootLayout({ }>) { return ( - {children} + + {children} + ); } diff --git a/apps/website/app/providers.tsx b/apps/website/app/providers.tsx new file mode 100644 index 000000000..d58bca655 --- /dev/null +++ b/apps/website/app/providers.tsx @@ -0,0 +1,29 @@ +"use client"; + +import posthog from "posthog-js"; +import { PostHogProvider as PHProvider } from "posthog-js/react"; +import { useEffect } from "react"; +import PostHogPageView from "./PostHogPageView"; + +if ( + !process.env.NEXT_PUBLIC_POSTHOG_KEY || + !process.env.NEXT_PUBLIC_POSTHOG_HOST +) { + throw new Error("PostHog environment variables are not set"); +} + +export function PostHogProvider({ children }: { children: React.ReactNode }) { + useEffect(() => { + posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, { + api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST!, + capture_pageview: false, + }); + }, []); + + return ( + + + {children} + + ); +} diff --git a/package-lock.json b/package-lock.json index 226b4cf72..2ca0b9180 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "apps/*", "packages/*" ], + "dependencies": { + "posthog-js": "^1.203.1" + }, "devDependencies": { "prettier": "^3.4.2", "prettier-plugin-tailwindcss": "^0.6.9", @@ -3933,15 +3936,6 @@ "license": "MIT", "peer": true }, - "apps/roam/node_modules/core-js": { - "version": "3.30.1", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "apps/roam/node_modules/core-util-is": { "version": "1.0.3", "license": "MIT", @@ -9884,6 +9878,17 @@ "dev": true, "license": "MIT" }, + "node_modules/core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-pure": { "version": "3.39.0", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.39.0.tgz", @@ -11689,6 +11694,12 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==", + "license": "MIT" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -14722,6 +14733,28 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/posthog-js": { + "version": "1.203.1", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.203.1.tgz", + "integrity": "sha512-r/WiSyz6VNbIKEV/30+aD5gdrYkFtmZwvqNa6h9frl8hG638v098FrXaq3EYzMcCdkQf3phaZTDIAFKegpiTjw==", + "license": "MIT", + "dependencies": { + "core-js": "^3.38.1", + "fflate": "^0.4.8", + "preact": "^10.19.3", + "web-vitals": "^4.2.0" + } + }, + "node_modules/preact": { + "version": "10.25.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.25.3.tgz", + "integrity": "sha512-dzQmIFtM970z+fP9ziQ3yG4e3ULIbwZzJ734vaMVUTaKQ2+Ru1Ou/gjshOYVHCcd1rpAelC6ngjvjDXph98unQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -16849,6 +16882,12 @@ "defaults": "^1.0.3" } }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", + "license": "Apache-2.0" + }, "node_modules/website": { "resolved": "apps/website", "link": true diff --git a/package.json b/package.json index ef93564f9..b862f8ee6 100644 --- a/package.json +++ b/package.json @@ -27,5 +27,8 @@ "prettier-plugin-tailwindcss" ], "tailwindConfig": "./packages/tailwind-config/tailwind.config.ts" + }, + "dependencies": { + "posthog-js": "^1.203.1" } }