mirror of
https://github.com/docmost/docmost.git
synced 2025-11-10 13:02:05 +10:00
posthog integration (cloud) (#1304)
This commit is contained in:
@ -41,6 +41,7 @@
|
|||||||
"lowlight": "^3.3.0",
|
"lowlight": "^3.3.0",
|
||||||
"mermaid": "^11.6.0",
|
"mermaid": "^11.6.0",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
|
"posthog-js": "^1.255.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-arborist": "3.4.0",
|
"react-arborist": "3.4.0",
|
||||||
"react-clear-modal": "^2.0.15",
|
"react-clear-modal": "^2.0.15",
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { UserProvider } from "@/features/user/user-provider.tsx";
|
import { UserProvider } from "@/features/user/user-provider.tsx";
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
import GlobalAppShell from "@/components/layouts/global/global-app-shell.tsx";
|
import GlobalAppShell from "@/components/layouts/global/global-app-shell.tsx";
|
||||||
|
import { PosthogUser } from "@/ee/components/posthog-user.tsx";
|
||||||
|
import { isCloud } from "@/lib/config.ts";
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
return (
|
return (
|
||||||
@ -8,6 +10,7 @@ export default function Layout() {
|
|||||||
<GlobalAppShell>
|
<GlobalAppShell>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</GlobalAppShell>
|
</GlobalAppShell>
|
||||||
|
{isCloud() && <PosthogUser />}
|
||||||
</UserProvider>
|
</UserProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
41
apps/client/src/ee/components/posthog-user.tsx
Normal file
41
apps/client/src/ee/components/posthog-user.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { usePostHog } from "posthog-js/react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useAtom } from "jotai";
|
||||||
|
import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
|
||||||
|
|
||||||
|
export function PosthogUser() {
|
||||||
|
const posthog = usePostHog();
|
||||||
|
const [currentUser] = useAtom(currentUserAtom);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentUser) {
|
||||||
|
const user = currentUser?.user;
|
||||||
|
const workspace = currentUser?.workspace;
|
||||||
|
if (!user || !workspace) return;
|
||||||
|
|
||||||
|
posthog?.identify(user.id, {
|
||||||
|
name: user.name,
|
||||||
|
email: user.email,
|
||||||
|
workspaceId: user.workspaceId,
|
||||||
|
workspaceHostname: workspace.hostname,
|
||||||
|
lastActiveAt: new Date().toISOString(),
|
||||||
|
createdAt: user.createdAt,
|
||||||
|
source: "docmost-app",
|
||||||
|
});
|
||||||
|
posthog?.group("workspace", workspace.id, {
|
||||||
|
name: workspace.name,
|
||||||
|
hostname: workspace.hostname,
|
||||||
|
plan: workspace?.plan,
|
||||||
|
status: workspace.status,
|
||||||
|
isOnTrial: !!workspace.trialEndAt,
|
||||||
|
hasStripeCustomerId: !!workspace.stripeCustomerId,
|
||||||
|
memberCount: workspace.memberCount,
|
||||||
|
lastActiveAt: new Date().toISOString(),
|
||||||
|
createdAt: workspace.createdAt,
|
||||||
|
source: "docmost-app",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [posthog, currentUser]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ export interface IWorkspace {
|
|||||||
settings: any;
|
settings: any;
|
||||||
status: string;
|
status: string;
|
||||||
enforceSso: boolean;
|
enforceSso: boolean;
|
||||||
|
stripeCustomerId: string;
|
||||||
billingEmail: string;
|
billingEmail: string;
|
||||||
trialEndAt: Date;
|
trialEndAt: Date;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|||||||
@ -83,6 +83,18 @@ export function getBillingTrialDays() {
|
|||||||
return getConfigValue("BILLING_TRIAL_DAYS");
|
return getConfigValue("BILLING_TRIAL_DAYS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPostHogHost() {
|
||||||
|
return getConfigValue("POSTHOG_HOST");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isPostHogEnabled(): boolean {
|
||||||
|
return Boolean(getPostHogHost() && getPostHogKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPostHogKey() {
|
||||||
|
return getConfigValue("POSTHOG_KEY");
|
||||||
|
}
|
||||||
|
|
||||||
function getConfigValue(key: string, defaultValue: string = undefined): string {
|
function getConfigValue(key: string, defaultValue: string = undefined): string {
|
||||||
const rawValue = import.meta.env.DEV
|
const rawValue = import.meta.env.DEV
|
||||||
? process?.env?.[key]
|
? process?.env?.[key]
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import "@mantine/spotlight/styles.css";
|
|||||||
import "@mantine/notifications/styles.css";
|
import "@mantine/notifications/styles.css";
|
||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import App from "./App.tsx";
|
import App from "./App.tsx";
|
||||||
import { mantineCssResolver, theme } from '@/theme';
|
import { mantineCssResolver, theme } from "@/theme";
|
||||||
import { MantineProvider } from "@mantine/core";
|
import { MantineProvider } from "@mantine/core";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import { ModalsProvider } from "@mantine/modals";
|
import { ModalsProvider } from "@mantine/modals";
|
||||||
@ -11,6 +11,14 @@ import { Notifications } from "@mantine/notifications";
|
|||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { HelmetProvider } from "react-helmet-async";
|
import { HelmetProvider } from "react-helmet-async";
|
||||||
import "./i18n";
|
import "./i18n";
|
||||||
|
import { PostHogProvider } from "posthog-js/react";
|
||||||
|
import {
|
||||||
|
getPostHogHost,
|
||||||
|
getPostHogKey,
|
||||||
|
isCloud,
|
||||||
|
isPostHogEnabled,
|
||||||
|
} from "@/lib/config.ts";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
export const queryClient = new QueryClient({
|
export const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
@ -23,9 +31,16 @@ export const queryClient = new QueryClient({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (isCloud() && isPostHogEnabled) {
|
||||||
|
posthog.init(getPostHogKey(), {
|
||||||
|
api_host: getPostHogHost(),
|
||||||
|
defaults: "2025-05-24",
|
||||||
|
disable_session_recording: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById("root") as HTMLElement
|
document.getElementById("root") as HTMLElement,
|
||||||
);
|
);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
@ -35,10 +50,12 @@ root.render(
|
|||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<Notifications position="bottom-center" limit={3} />
|
<Notifications position="bottom-center" limit={3} />
|
||||||
<HelmetProvider>
|
<HelmetProvider>
|
||||||
<App />
|
<PostHogProvider client={posthog}>
|
||||||
|
<App />
|
||||||
|
</PostHogProvider>
|
||||||
</HelmetProvider>
|
</HelmetProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</ModalsProvider>
|
</ModalsProvider>
|
||||||
</MantineProvider>
|
</MantineProvider>
|
||||||
</BrowserRouter>
|
</BrowserRouter>,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,8 @@ export default defineConfig(({ mode }) => {
|
|||||||
SUBDOMAIN_HOST,
|
SUBDOMAIN_HOST,
|
||||||
COLLAB_URL,
|
COLLAB_URL,
|
||||||
BILLING_TRIAL_DAYS,
|
BILLING_TRIAL_DAYS,
|
||||||
|
POSTHOG_HOST,
|
||||||
|
POSTHOG_KEY,
|
||||||
} = loadEnv(mode, envPath, "");
|
} = loadEnv(mode, envPath, "");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -27,6 +29,8 @@ export default defineConfig(({ mode }) => {
|
|||||||
SUBDOMAIN_HOST,
|
SUBDOMAIN_HOST,
|
||||||
COLLAB_URL,
|
COLLAB_URL,
|
||||||
BILLING_TRIAL_DAYS,
|
BILLING_TRIAL_DAYS,
|
||||||
|
POSTHOG_HOST,
|
||||||
|
POSTHOG_KEY,
|
||||||
},
|
},
|
||||||
APP_VERSION: JSON.stringify(process.env.npm_package_version),
|
APP_VERSION: JSON.stringify(process.env.npm_package_version),
|
||||||
},
|
},
|
||||||
|
|||||||
@ -205,4 +205,12 @@ export class EnvironmentService {
|
|||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
return disable === 'true';
|
return disable === 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPostHogHost(): string {
|
||||||
|
return this.configService.get<string>('POSTHOG_HOST');
|
||||||
|
}
|
||||||
|
|
||||||
|
getPostHogKey(): string {
|
||||||
|
return this.configService.get<string>('POSTHOG_KEY');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,8 @@ export class StaticModule implements OnModuleInit {
|
|||||||
BILLING_TRIAL_DAYS: this.environmentService.isCloud()
|
BILLING_TRIAL_DAYS: this.environmentService.isCloud()
|
||||||
? this.environmentService.getBillingTrialDays()
|
? this.environmentService.getBillingTrialDays()
|
||||||
: undefined,
|
: undefined,
|
||||||
|
POSTHOG_HOST: this.environmentService.getPostHogHost(),
|
||||||
|
POSTHOG_KEY: this.environmentService.getPostHogKey(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const windowScriptContent = `<script>window.CONFIG=${JSON.stringify(configString)};</script>`;
|
const windowScriptContent = `<script>window.CONFIG=${JSON.stringify(configString)};</script>`;
|
||||||
|
|||||||
41
pnpm-lock.yaml
generated
41
pnpm-lock.yaml
generated
@ -296,6 +296,9 @@ importers:
|
|||||||
mitt:
|
mitt:
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
|
posthog-js:
|
||||||
|
specifier: ^1.255.1
|
||||||
|
version: 1.255.1
|
||||||
react:
|
react:
|
||||||
specifier: ^18.3.1
|
specifier: ^18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
@ -5213,6 +5216,9 @@ packages:
|
|||||||
core-js-compat@3.35.0:
|
core-js-compat@3.35.0:
|
||||||
resolution: {integrity: sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==}
|
resolution: {integrity: sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==}
|
||||||
|
|
||||||
|
core-js@3.43.0:
|
||||||
|
resolution: {integrity: sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==}
|
||||||
|
|
||||||
core-util-is@1.0.3:
|
core-util-is@1.0.3:
|
||||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||||
|
|
||||||
@ -5988,6 +5994,9 @@ packages:
|
|||||||
picomatch:
|
picomatch:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
fflate@0.4.8:
|
||||||
|
resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
|
||||||
|
|
||||||
fflate@0.8.2:
|
fflate@0.8.2:
|
||||||
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
|
||||||
|
|
||||||
@ -7955,9 +7964,23 @@ packages:
|
|||||||
postgres-range@1.1.4:
|
postgres-range@1.1.4:
|
||||||
resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
|
resolution: {integrity: sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==}
|
||||||
|
|
||||||
|
posthog-js@1.255.1:
|
||||||
|
resolution: {integrity: sha512-KMh0o9MhORhEZVjXpktXB5rJ8PfDk+poqBoTSoLzWgNjhJf6D8jcyB9jUMA6vVPfn4YeepVX5NuclDRqOwr5Mw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@rrweb/types': 2.0.0-alpha.17
|
||||||
|
rrweb-snapshot: 2.0.0-alpha.17
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@rrweb/types':
|
||||||
|
optional: true
|
||||||
|
rrweb-snapshot:
|
||||||
|
optional: true
|
||||||
|
|
||||||
postmark@4.0.5:
|
postmark@4.0.5:
|
||||||
resolution: {integrity: sha512-nerZdd3TwOH4CgGboZnlUM/q7oZk0EqpZgJL+Y3Nup8kHeaukxouQ6JcFF3EJEijc4QbuNv1TefGhboAKtf/SQ==}
|
resolution: {integrity: sha512-nerZdd3TwOH4CgGboZnlUM/q7oZk0EqpZgJL+Y3Nup8kHeaukxouQ6JcFF3EJEijc4QbuNv1TefGhboAKtf/SQ==}
|
||||||
|
|
||||||
|
preact@10.26.9:
|
||||||
|
resolution: {integrity: sha512-SSjF9vcnF27mJK1XyFMNJzFd5u3pQiATFqoaDy03XuN00u4ziveVVEGt5RKJrDR8MHE/wJo9Nnad56RLzS2RMA==}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@ -9297,6 +9320,9 @@ packages:
|
|||||||
wcwidth@1.0.1:
|
wcwidth@1.0.1:
|
||||||
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
|
||||||
|
|
||||||
|
web-vitals@4.2.4:
|
||||||
|
resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
|
||||||
|
|
||||||
web-worker@1.5.0:
|
web-worker@1.5.0:
|
||||||
resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==}
|
resolution: {integrity: sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==}
|
||||||
|
|
||||||
@ -15194,6 +15220,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
browserslist: 4.24.2
|
browserslist: 4.24.2
|
||||||
|
|
||||||
|
core-js@3.43.0: {}
|
||||||
|
|
||||||
core-util-is@1.0.3: {}
|
core-util-is@1.0.3: {}
|
||||||
|
|
||||||
cors@2.8.5:
|
cors@2.8.5:
|
||||||
@ -16181,6 +16209,8 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
picomatch: 4.0.2
|
picomatch: 4.0.2
|
||||||
|
|
||||||
|
fflate@0.4.8: {}
|
||||||
|
|
||||||
fflate@0.8.2: {}
|
fflate@0.8.2: {}
|
||||||
|
|
||||||
figures@3.2.0:
|
figures@3.2.0:
|
||||||
@ -18482,12 +18512,21 @@ snapshots:
|
|||||||
|
|
||||||
postgres-range@1.1.4: {}
|
postgres-range@1.1.4: {}
|
||||||
|
|
||||||
|
posthog-js@1.255.1:
|
||||||
|
dependencies:
|
||||||
|
core-js: 3.43.0
|
||||||
|
fflate: 0.4.8
|
||||||
|
preact: 10.26.9
|
||||||
|
web-vitals: 4.2.4
|
||||||
|
|
||||||
postmark@4.0.5:
|
postmark@4.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
axios: 1.9.0
|
axios: 1.9.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
|
|
||||||
|
preact@10.26.9: {}
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
prettier@3.4.1: {}
|
prettier@3.4.1: {}
|
||||||
@ -19911,6 +19950,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
defaults: 1.0.4
|
defaults: 1.0.4
|
||||||
|
|
||||||
|
web-vitals@4.2.4: {}
|
||||||
|
|
||||||
web-worker@1.5.0: {}
|
web-worker@1.5.0: {}
|
||||||
|
|
||||||
webidl-conversions@3.0.1: {}
|
webidl-conversions@3.0.1: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user