mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-13 12:55:19 +00:00
improvements to identify
This commit is contained in:
parent
36338dc8d2
commit
eac7ea0555
5 changed files with 68 additions and 21 deletions
|
|
@ -7,6 +7,7 @@ import { Toaster } from "@/components/ui/toaster";
|
|||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
import { env } from "@sourcebot/shared";
|
||||
import { env as clientEnv } from "@sourcebot/shared/client";
|
||||
import { PlanProvider } from "@/features/entitlements/planProvider";
|
||||
import { getEntitlements } from "@sourcebot/shared";
|
||||
|
||||
|
|
@ -42,6 +43,8 @@ export default function RootLayout({
|
|||
// @note: the posthog api key doesn't need to be kept secret,
|
||||
// so we are safe to send it to the client.
|
||||
posthogApiKey={env.POSTHOG_PAPIK}
|
||||
sourcebotVersion={clientEnv.NEXT_PUBLIC_SOURCEBOT_VERSION}
|
||||
sourcebotInstallId={env.SOURCEBOT_INSTALL_ID}
|
||||
>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
|
|
|
|||
|
|
@ -34,9 +34,17 @@ interface PostHogProviderProps {
|
|||
children: React.ReactNode
|
||||
isDisabled: boolean
|
||||
posthogApiKey: string
|
||||
sourcebotVersion: string
|
||||
sourcebotInstallId: string
|
||||
}
|
||||
|
||||
export function PostHogProvider({ children, isDisabled, posthogApiKey }: PostHogProviderProps) {
|
||||
export function PostHogProvider({
|
||||
children,
|
||||
isDisabled,
|
||||
posthogApiKey,
|
||||
sourcebotVersion,
|
||||
sourcebotInstallId,
|
||||
}: PostHogProviderProps) {
|
||||
const { data: session } = useSession();
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -61,27 +69,33 @@ export function PostHogProvider({ children, isDisabled, posthogApiKey }: PostHog
|
|||
'$referrer',
|
||||
'$referring_domain',
|
||||
'$ip',
|
||||
] : []
|
||||
] : [],
|
||||
loaded: (posthog) => {
|
||||
// Include install id & version in all events.
|
||||
posthog.register({
|
||||
sourcebot_version: sourcebotVersion,
|
||||
install_id: sourcebotInstallId,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.debug("PostHog telemetry disabled");
|
||||
}
|
||||
}, [isDisabled, posthogApiKey]);
|
||||
}, [isDisabled, posthogApiKey, sourcebotInstallId, sourcebotVersion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only identify the user if we are running in a cloud environment.
|
||||
if (env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT !== undefined) {
|
||||
posthog.identify(session.user.id, {
|
||||
posthog.identify(
|
||||
session.user.id,
|
||||
// Only include email & name when running in a cloud environment.
|
||||
env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT !== undefined ? {
|
||||
email: session.user.email,
|
||||
name: session.user.name,
|
||||
});
|
||||
} else {
|
||||
console.debug("PostHog identify skipped");
|
||||
}
|
||||
} : undefined
|
||||
);
|
||||
}, [session]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,17 +3,13 @@
|
|||
import { CaptureOptions } from "posthog-js";
|
||||
import posthog from "posthog-js";
|
||||
import { PosthogEvent, PosthogEventMap } from "../lib/posthogEvents";
|
||||
import { env } from "@sourcebot/shared/client";
|
||||
|
||||
export function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E], options?: CaptureOptions) {
|
||||
if(!options) {
|
||||
options = {};
|
||||
}
|
||||
options.send_instantly = true;
|
||||
posthog.capture(event, {
|
||||
...properties,
|
||||
sourcebot_version: env.NEXT_PUBLIC_SOURCEBOT_VERSION,
|
||||
}, options);
|
||||
posthog.capture(event, properties, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { PostHog } from 'posthog-node'
|
||||
import { env } from '@sourcebot/shared'
|
||||
import { env as clientEnv } from '@sourcebot/shared/client';
|
||||
import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { PosthogEvent, PosthogEventMap } from './posthogEvents';
|
||||
import { cookies } from 'next/headers';
|
||||
import { cookies, headers } from 'next/headers';
|
||||
import { auth } from '@/auth';
|
||||
import { getVerifiedApiObject } from '@/withAuthV2';
|
||||
|
||||
/**
|
||||
* @note: This is a subset of the properties stored in the
|
||||
|
|
@ -47,13 +50,40 @@ const getPostHogCookie = (cookieStore: Pick<RequestCookies, 'get'>): PostHogCook
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve the distinct id of the current user.
|
||||
*/
|
||||
const tryGetDistinctId = async () => {
|
||||
// First, attempt to retrieve the distinct id from the cookie.
|
||||
const cookieStore = await cookies();
|
||||
const cookie = getPostHogCookie(cookieStore);
|
||||
if (cookie) {
|
||||
return cookie.distinct_id;
|
||||
}
|
||||
|
||||
// Next, from the session.
|
||||
const session = await auth();
|
||||
if (session) {
|
||||
return session.user.id;
|
||||
}
|
||||
|
||||
// Finally, from the api key.
|
||||
const headersList = await headers();
|
||||
const apiKeyString = headersList.get("X-Sourcebot-Api-Key") ?? undefined;
|
||||
if (!apiKeyString) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const apiKey = await getVerifiedApiObject(apiKeyString);
|
||||
return apiKey?.createdById;
|
||||
}
|
||||
|
||||
export async function captureEvent<E extends PosthogEvent>(event: E, properties: PosthogEventMap[E]) {
|
||||
if (env.SOURCEBOT_TELEMETRY_DISABLED === 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
const cookieStore = await cookies();
|
||||
const cookie = getPostHogCookie(cookieStore);
|
||||
const distinctId = await tryGetDistinctId();
|
||||
|
||||
const posthog = new PostHog(env.POSTHOG_PAPIK, {
|
||||
host: 'https://us.i.posthog.com',
|
||||
|
|
@ -63,7 +93,11 @@ export async function captureEvent<E extends PosthogEvent>(event: E, properties:
|
|||
|
||||
posthog.capture({
|
||||
event,
|
||||
properties,
|
||||
distinctId: cookie?.distinct_id ?? '',
|
||||
properties: {
|
||||
...properties,
|
||||
sourcebot_version: clientEnv.NEXT_PUBLIC_SOURCEBOT_VERSION,
|
||||
install_id: env.SOURCEBOT_INSTALL_ID,
|
||||
},
|
||||
distinctId,
|
||||
});
|
||||
}
|
||||
|
|
@ -156,7 +156,7 @@ export const getAuthenticatedUser = async () => {
|
|||
/**
|
||||
* Returns a API key object if the API key string is valid, otherwise returns undefined.
|
||||
*/
|
||||
const getVerifiedApiObject = async (apiKeyString: string): Promise<ApiKey | undefined> => {
|
||||
export const getVerifiedApiObject = async (apiKeyString: string): Promise<ApiKey | undefined> => {
|
||||
const parts = apiKeyString.split("-");
|
||||
if (parts.length !== 2 || parts[0] !== "sourcebot") {
|
||||
return undefined;
|
||||
|
|
|
|||
Loading…
Reference in a new issue