diff --git a/lib/analytics.js b/lib/analytics.js
deleted file mode 100644
index 6b226ec74..000000000
--- a/lib/analytics.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import * as snippet from "@segment/snippet";
-import Script from "next/script";
-
-export function track(eventName, attrs = {}) {
- if (typeof window?.analytics?.track === "function") {
- window.analytics.track(eventName, attrs);
- }
-}
-
-export function page(pageName, properties = {}) {
- if (typeof window?.analytics?.page === "function") {
- window.analytics.page(pageName, properties);
- }
-}
-
-export const SEGMENT_WRITE_KEY = process.env.NEXT_PUBLIC_ANALYTICS_WRITE_KEY;
-
-function renderSnippet() {
- const opts = {
- apiKey: SEGMENT_WRITE_KEY,
- // note: the page option only covers SSR tracking.
- // Page.js is used to track other events using `window.analytics.page()`
- page: true,
- };
-
- if (process.env.NODE_ENV === "development") {
- return snippet.max(opts);
- }
-
- return snippet.min(opts);
-}
-
-export const Snippet = () => (
-
-);
diff --git a/lib/posthog.ts b/lib/posthog.ts
new file mode 100644
index 000000000..a86cc4bb5
--- /dev/null
+++ b/lib/posthog.ts
@@ -0,0 +1,55 @@
+import posthog from "posthog-js";
+
+export const POSTHOG_KEY = process.env.NEXT_PUBLIC_POSTHOG_KEY;
+export const POSTHOG_HOST =
+ process.env.NEXT_PUBLIC_POSTHOG_HOST || "https://us.i.posthog.com";
+
+let initialized = false;
+
+export function init() {
+ if (typeof window === "undefined" || initialized || !POSTHOG_KEY) {
+ return;
+ }
+
+ posthog.init(POSTHOG_KEY, {
+ api_host: POSTHOG_HOST,
+ capture_pageview: false, // We manually capture page views on route changes
+ capture_pageleave: true,
+ loaded: (posthog) => {
+ if (process.env.NODE_ENV === "development") {
+ posthog.debug();
+ }
+ },
+ });
+
+ initialized = true;
+}
+
+export function track(eventName: string, properties: Record = {}) {
+ if (typeof window !== "undefined" && initialized) {
+ posthog.capture(eventName, properties);
+ }
+}
+
+export function page(pageName?: string, properties: Record = {}) {
+ if (typeof window !== "undefined" && initialized) {
+ posthog.capture("$pageview", {
+ ...properties,
+ ...(pageName && { page_name: pageName }),
+ });
+ }
+}
+
+export function identify(userId: string, properties: Record = {}) {
+ if (typeof window !== "undefined" && initialized) {
+ posthog.identify(userId, properties);
+ }
+}
+
+export function reset() {
+ if (typeof window !== "undefined" && initialized) {
+ posthog.reset();
+ }
+}
+
+export { posthog };
diff --git a/package.json b/package.json
index 8d10f5bfc..656b24a6d 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,6 @@
"@inkeep/cxkit-react": "^0.5.86",
"@scalar/openapi-parser": "^0.10.9",
"@scalar/openapi-types": "^0.1.9",
- "@segment/snippet": "^5.2.1",
"@tailwindcss/typography": "^0.5.4",
"@telegraph/appearance": "^0.0.12",
"@telegraph/button": "^0.0.83",
@@ -62,6 +61,7 @@
"next-mdx-remote": "^6.0.0",
"next-remote-refresh": "^0.10.1",
"next-seo": "^5.4.0",
+ "posthog-js": "^1.386.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-hotkeys-hook": "^3.4.6",
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 9d46a2806..769b898b8 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -11,7 +11,7 @@ import { InkeepModalProvider } from "../components/AiChatButton";
import { AskAiProvider } from "../components/AskAiContext";
import AskAiSidebar from "../components/AskAiSidebar";
import { ThemeProvider } from "../components/theme/ThemeProvider";
-import * as analytics from "../lib/analytics";
+import * as posthogAnalytics from "../lib/posthog";
import { initAttribution } from "../lib/attribution";
import { setClearbitPath } from "../lib/clearbit";
import * as gtag from "../lib/gtag";
@@ -31,8 +31,9 @@ function MyApp({ Component, pageProps }) {
// Refresh when content pages change
useRemoteRefresh();
- // Initialize attribution tracking on mount
+ // Initialize PostHog and attribution tracking on mount
useEffect(() => {
+ posthogAnalytics.init();
initAttribution();
}, []);
@@ -40,7 +41,7 @@ function MyApp({ Component, pageProps }) {
const handleRouteChange = (url: URL) => {
gtag.pageview(url);
setClearbitPath(url);
- analytics.page();
+ posthogAnalytics.page();
initAttribution();
};
@@ -58,7 +59,6 @@ function MyApp({ Component, pageProps }) {
- {analytics.SEGMENT_WRITE_KEY && }
diff --git a/yarn.lock b/yarn.lock
index 79eea72dd..8e438b9b7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -876,25 +876,6 @@
dependencies:
"@types/mdx" "^2.0.0"
-"@ndhoule/each@^2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@ndhoule/each/-/each-2.0.1.tgz#bbed372a603e0713a3193c706a73ddebc5b426a9"
- integrity sha512-wHuJw6x+rF6Q9Skgra++KccjBozCr9ymtna0FhxmV/8xT/hZ2ExGYR8SV8prg8x4AH/7mzDYErNGIVHuzHeybw==
- dependencies:
- "@ndhoule/keys" "^2.0.0"
-
-"@ndhoule/keys@^2.0.0":
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/@ndhoule/keys/-/keys-2.0.0.tgz#3d64ae677c65a261747bf3a457c62eb292a4e0ce"
- integrity sha512-vtCqKBC1Av6dsBA8xpAO+cgk051nfaI+PnmTZep2Px0vYrDvpUmLxv7z40COlWH5yCpu3gzNhepk+02yiQiZNw==
-
-"@ndhoule/map@^2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@ndhoule/map/-/map-2.0.1.tgz#f5ca0a47424ea67f46e2a6d499b9e9bc886aefa8"
- integrity sha512-WOEf2An9mL4DVY6NHgaRmFC82pZGrmzW4I0hpPPdczDP4Gp5+Q1Nny77x3w0qzENA8+cbgd9+Lx2ClSTLvkB0g==
- dependencies:
- "@ndhoule/each" "^2.0.1"
-
"@next/env@16.2.6":
version "16.2.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-16.2.6.tgz#93a173801cb088463070cc6a113c68e26c1838ea"
@@ -966,6 +947,18 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+"@posthog/core@^1.32.3":
+ version "1.32.3"
+ resolved "https://registry.yarnpkg.com/@posthog/core/-/core-1.32.3.tgz#4ea8177e007c17ffee74def62e41e0f6951ad343"
+ integrity sha512-vwOEMfZvGv5XxNWV7p9I52NSmvFNMhyW2IHpIoUHW5jLkgUrknzJW1H/qxVGSIrNNVQkfsoaDFzDhJdg10pgrA==
+ dependencies:
+ "@posthog/types" "1.386.3"
+
+"@posthog/types@1.386.3", "@posthog/types@^1.386.3":
+ version "1.386.3"
+ resolved "https://registry.yarnpkg.com/@posthog/types/-/types-1.386.3.tgz#2703a3b83a80c24524283c515334bdf407be9f9b"
+ integrity sha512-LqJoiQi2eyWn7rCUgnn+D+F3Efp6+04o72bjSX6kWHx0nFaYNC/nJuAIRliDTY/X7GPIUAaHAcSjbMI/9wfX1Q==
+
"@radix-ui/number@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46"
@@ -1647,13 +1640,6 @@
resolved "https://registry.yarnpkg.com/@scalar/openapi-types/-/openapi-types-0.1.9.tgz#e2c5144f7b31ab831f914b1daa0f34b50e47b106"
integrity sha512-HQQudOSQBU7ewzfnBW9LhDmBE2XOJgSfwrh5PlUB7zJup/kaRkBGNgV2wMjNz9Af/uztiU/xNrO179FysmUT+g==
-"@segment/snippet@^5.2.1":
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/@segment/snippet/-/snippet-5.2.1.tgz#1e5ebdc730a6f8a985381d96cfe3e760a61d2847"
- integrity sha512-2K0AJVWbajA91/GyizfurTnRYinWusGiFNEMqVAh6vHnbR3b4tFwb8lEMdpPMyGe07XH0Upfx+naQIpiGFnJQQ==
- dependencies:
- "@ndhoule/map" "^2.0.1"
-
"@shikijs/core@3.21.0":
version "3.21.0"
resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.21.0.tgz#9641d09865c43612b28e7931f9af68c8a62edd90"
@@ -2166,6 +2152,11 @@
dependencies:
csstype "^3.0.2"
+"@types/trusted-types@^2.0.7":
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11"
+ integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==
+
"@types/unist@*", "@types/unist@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-3.0.3.tgz#acaab0f919ce69cce629c2d4ed2eb4adc1b6c20c"
@@ -2721,6 +2712,11 @@ content-type@^1.0.5:
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+core-js@^3.38.1:
+ version "3.49.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.49.0.tgz#8b4d520ac034311fa21aa616f017ada0e0dbbddd"
+ integrity sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==
+
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -2849,6 +2845,13 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
+dompurify@^3.3.2:
+ version "3.4.10"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.4.10.tgz#96704295b4d8aeefcc8c7a90caa579b0ad69e46a"
+ integrity sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==
+ optionalDependencies:
+ "@types/trusted-types" "^2.0.7"
+
dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
@@ -3240,6 +3243,11 @@ fault@^2.0.0:
dependencies:
format "^0.2.0"
+fflate@^0.4.8:
+ version "0.4.8"
+ resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
+ integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==
+
fflate@^0.7.3:
version "0.7.4"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.7.4.tgz#61587e5d958fdabb5a9368a302c25363f4f69f50"
@@ -5234,11 +5242,30 @@ postcss@^8.4.31, postcss@^8.4.47, postcss@^8.5.3, postcss@^8.5.6:
picocolors "^1.1.1"
source-map-js "^1.2.1"
+posthog-js@^1.386.6:
+ version "1.386.6"
+ resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.386.6.tgz#9d2ef8de3f2eba9c237b8f71cb47911d7ab6339c"
+ integrity sha512-xRcbToRtU07Ojk+VaCCos6I/zD60sNKfWxdeZih0xbncgegIqLZJmBzi4HdkSkXrf14b6HhwMI/s2GxWha5ADQ==
+ dependencies:
+ "@posthog/core" "^1.32.3"
+ "@posthog/types" "^1.386.3"
+ core-js "^3.38.1"
+ dompurify "^3.3.2"
+ fflate "^0.4.8"
+ preact "^10.28.2"
+ query-selector-shadow-dom "^1.0.1"
+ web-vitals "^5.1.0"
+
preact@^10.13.2:
version "10.27.2"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.27.2.tgz#19b9009c1be801a76a0aaf0fe5ba665985a09312"
integrity sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==
+preact@^10.28.2:
+ version "10.29.2"
+ resolved "https://registry.yarnpkg.com/preact/-/preact-10.29.2.tgz#3e6069c471718b8d124d1cd67565114532e88d70"
+ integrity sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==
+
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -5298,6 +5325,11 @@ punycode@^2.1.0:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+query-selector-shadow-dom@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz#1c7b0058eff4881ac44f45d8f84ede32e9a2f349"
+ integrity sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==
+
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -6428,6 +6460,11 @@ web-streams-polyfill@4.0.0-beta.3:
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38"
integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==
+web-vitals@^5.1.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-5.3.0.tgz#a67f57f229fdf68be99eb99d3725946def284ff3"
+ integrity sha512-q6LWsLatGYZp5VGBIOvbTj6JBV2nOmC8KvWztXBmwJcfFAzhwKwbOxhUH306XY3CcaZDUlSmSuNPBsCn0bFu+g==
+
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"