mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-13 04:45:19 +00:00
PostHog event pass (#246)
This commit is contained in:
parent
78b8916797
commit
8e3235a56d
9 changed files with 81 additions and 38 deletions
|
|
@ -34,7 +34,7 @@ AUTH_URL="http://localhost:3000"
|
|||
# Sentry
|
||||
# SENTRY_BACKEND_DSN=""
|
||||
# NEXT_PUBLIC_SENTRY_WEBAPP_DSN=""
|
||||
SENTRY_ENVIRONMENT="dev"
|
||||
# SENTRY_ENVIRONMENT="dev"
|
||||
# NEXT_PUBLIC_SENTRY_ENVIRONMENT="dev"
|
||||
# SENTRY_AUTH_TOKEN=
|
||||
|
||||
|
|
@ -76,4 +76,6 @@ SOURCEBOT_TELEMETRY_DISABLED=true # Disables telemetry collection
|
|||
|
||||
# CONFIG_MAX_REPOS_NO_TOKEN=
|
||||
# NODE_ENV=
|
||||
# SOURCEBOT_TENANCY_MODE=single
|
||||
# SOURCEBOT_TENANCY_MODE=single
|
||||
|
||||
# NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT=
|
||||
|
|
@ -9,6 +9,7 @@ ARG SOURCEBOT_VERSION
|
|||
# @see: https://posthog.com/tutorials/api-capture-events#authenticating-with-the-project-api-key
|
||||
ARG POSTHOG_PAPIK
|
||||
ARG SENTRY_ENVIRONMENT
|
||||
ARG SOURCEBOT_CLOUD_ENVIRONMENT
|
||||
|
||||
FROM node:20-alpine3.19 AS node-alpine
|
||||
FROM golang:1.23.4-alpine3.19 AS go-alpine
|
||||
|
|
@ -52,9 +53,11 @@ ARG POSTHOG_PAPIK
|
|||
ENV NEXT_PUBLIC_POSTHOG_PAPIK=$POSTHOG_PAPIK
|
||||
ARG SENTRY_ENVIRONMENT
|
||||
ENV NEXT_PUBLIC_SENTRY_ENVIRONMENT=$SENTRY_ENVIRONMENT
|
||||
ARG SOURCEBOT_CLOUD_ENVIRONMENT
|
||||
ENV NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT=$SOURCEBOT_CLOUD_ENVIRONMENT
|
||||
# Local args
|
||||
ARG SENTRY_WEBAPP_DSN
|
||||
ENV NEXT_PUBLIC_SENTRY_WEBAPP_DSN=$SENTRY_WEBAPP_DSN
|
||||
ARG NEXT_PUBLIC_SENTRY_WEBAPP_DSN
|
||||
ENV NEXT_PUBLIC_SENTRY_WEBAPP_DSN=$NEXT_PUBLIC_SENTRY_WEBAPP_DSN
|
||||
# -----------
|
||||
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
|
@ -104,6 +107,8 @@ ARG SOURCEBOT_VERSION
|
|||
ENV SOURCEBOT_VERSION=$SOURCEBOT_VERSION
|
||||
ARG POSTHOG_PAPIK
|
||||
ENV POSTHOG_PAPIK=$POSTHOG_PAPIK
|
||||
ARG SENTRY_ENVIRONMENT
|
||||
ENV SENTRY_ENVIRONMENT=$SENTRY_ENVIRONMENT
|
||||
# Local args
|
||||
# -----------
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { useSession } from "next-auth/react";
|
|||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { signOut } from "next-auth/react"
|
||||
import { env } from "@/env.mjs";
|
||||
import posthog from "posthog-js";
|
||||
|
||||
interface SettingsDropdownProps {
|
||||
menuButtonClassName?: string;
|
||||
|
|
@ -94,7 +95,9 @@ export const SettingsDropdown = ({
|
|||
onClick={() => {
|
||||
signOut({
|
||||
redirectTo: "/login",
|
||||
});
|
||||
}).then(() => {
|
||||
posthog.reset();
|
||||
})
|
||||
}}
|
||||
>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { CodeHostType } from "@/lib/utils";
|
||||
import { getCodeHostIcon } from "@/lib/utils";
|
||||
import {
|
||||
|
|
@ -15,8 +15,6 @@ import { OnboardingSteps } from "@/lib/constants";
|
|||
import { BackButton } from "./onboardBackButton";
|
||||
import { CodeHostIconButton } from "../../components/codeHostIconButton";
|
||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||
import { useSession } from "next-auth/react";
|
||||
import posthog from "posthog-js";
|
||||
import SecurityCard from "@/app/components/securityCard";
|
||||
|
||||
interface ConnectCodeHostProps {
|
||||
|
|
@ -27,18 +25,6 @@ interface ConnectCodeHostProps {
|
|||
export const ConnectCodeHost = ({ nextStep, securityCardEnabled }: ConnectCodeHostProps) => {
|
||||
const [selectedCodeHost, setSelectedCodeHost] = useState<CodeHostType | null>(null);
|
||||
const router = useRouter();
|
||||
const { data: session } = useSession();
|
||||
|
||||
// Note: this is currently the first client side page that gets loaded after a user registers. If this changes, we need to update this.
|
||||
// @nocheckin
|
||||
useEffect(() => {
|
||||
if (session?.user) {
|
||||
posthog.identify(session.user.id, {
|
||||
email: session.user.email,
|
||||
name: session.user.name,
|
||||
});
|
||||
}
|
||||
}, [session?.user]);
|
||||
|
||||
const onCreated = useCallback(() => {
|
||||
router.push(`?step=${nextStep}`);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import { LogOutIcon } from "lucide-react";
|
||||
import { signOut } from "@/auth";
|
||||
import posthog from "posthog-js";
|
||||
|
||||
interface LogoutEscapeHatchProps {
|
||||
className?: string;
|
||||
}
|
||||
|
|
@ -14,6 +16,8 @@ export const LogoutEscapeHatch = ({
|
|||
"use server";
|
||||
await signOut({
|
||||
redirectTo: "/login",
|
||||
}).then(() => {
|
||||
posthog.reset();
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ import { SourcebotLogo } from "@/app/components/sourcebotLogo";
|
|||
import { TextSeparator } from "@/app/components/textSeparator";
|
||||
import useCaptureEvent from "@/hooks/useCaptureEvent";
|
||||
import DemoCard from "@/app/[domain]/onboard/components/demoCard";
|
||||
import Link from "next/link";
|
||||
import { env } from "@/env.mjs";
|
||||
|
||||
const TERMS_OF_SERVICE_URL = "https://sourcebot.dev/terms";
|
||||
const PRIVACY_POLICY_URL = "https://sourcebot.dev/privacy";
|
||||
|
||||
interface LoginFormProps {
|
||||
callbackUrl?: string;
|
||||
error?: string;
|
||||
|
|
@ -98,6 +104,9 @@ export const LoginForm = ({ callbackUrl, error, enabledMethods }: LoginFormProps
|
|||
]}
|
||||
/>
|
||||
</Card>
|
||||
{env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT !== undefined && (
|
||||
<p className="text-xs text-muted-foreground mt-8">By signing in, you agree to the <Link className="underline" href={TERMS_OF_SERVICE_URL} target="_blank">Terms of Service</Link> and <Link className="underline" href={PRIVACY_POLICY_URL} target="_blank">Privacy Policy</Link>.</p>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@ import { PostHogProvider as PHProvider } from 'posthog-js/react'
|
|||
import { usePathname, useSearchParams } from "next/navigation"
|
||||
import { Suspense, useEffect } from "react"
|
||||
import { env } from '@/env.mjs'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { captureEvent } from '@/hooks/useCaptureEvent'
|
||||
|
||||
// @see: https://posthog.com/docs/libraries/next-js#capturing-pageviews
|
||||
function PostHogPageView() {
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const posthog = usePostHog()
|
||||
|
||||
// Track pageviews
|
||||
useEffect(() => {
|
||||
if (pathname && posthog) {
|
||||
let url = window.origin + pathname
|
||||
|
|
@ -19,7 +21,9 @@ function PostHogPageView() {
|
|||
url = url + `?${searchParams.toString()}`
|
||||
}
|
||||
|
||||
posthog.capture('$pageview', { '$current_url': url })
|
||||
captureEvent('$pageview', {
|
||||
$current_url: url,
|
||||
});
|
||||
}
|
||||
}, [pathname, searchParams, posthog])
|
||||
|
||||
|
|
@ -32,34 +36,55 @@ interface PostHogProviderProps {
|
|||
}
|
||||
|
||||
export function PostHogProvider({ children, disabled }: PostHogProviderProps) {
|
||||
const { data: session } = useSession();
|
||||
|
||||
useEffect(() => {
|
||||
if (!disabled && env.NEXT_PUBLIC_POSTHOG_PAPIK) {
|
||||
console.debug(`PostHog telemetry enabled. Cloud environment: ${env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT}`);
|
||||
posthog.init(env.NEXT_PUBLIC_POSTHOG_PAPIK, {
|
||||
// @see next.config.mjs for path rewrites to the "/ingest" route.
|
||||
api_host: "/ingest",
|
||||
person_profiles: 'identified_only',
|
||||
capture_pageview: false,
|
||||
autocapture: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
sanitize_properties: (properties: Record<string, any>, _event: string) => {
|
||||
// https://posthog.com/docs/libraries/js#config
|
||||
if (properties['$current_url']) {
|
||||
properties['$current_url'] = null;
|
||||
}
|
||||
if (properties['$ip']) {
|
||||
properties['$ip'] = null;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
// In self-hosted mode, we don't want to capture the following
|
||||
// default properties.
|
||||
// @see: https://posthog.com/docs/data/events#default-properties
|
||||
property_denylist: env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT === undefined ? [
|
||||
'$current_url',
|
||||
'$pathname',
|
||||
'$session_entry_url',
|
||||
'$session_entry_host',
|
||||
'$session_entry_pathname',
|
||||
'$session_entry_referrer',
|
||||
'$session_entry_referring_domain',
|
||||
'$referrer',
|
||||
'$referring_domain',
|
||||
'$ip',
|
||||
] : []
|
||||
});
|
||||
} else {
|
||||
console.log("PostHog telemetry disabled");
|
||||
console.debug("PostHog telemetry disabled");
|
||||
}
|
||||
}, [disabled])
|
||||
}, [disabled]);
|
||||
|
||||
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, {
|
||||
email: session.user.email,
|
||||
name: session.user.name,
|
||||
});
|
||||
}
|
||||
}, [session]);
|
||||
|
||||
return (
|
||||
<PHProvider client={posthog}>
|
||||
{/* @see: https://github.com/vercel/next.js/issues/51581 */}
|
||||
<Suspense fallback={null}>
|
||||
<PostHogPageView />
|
||||
</Suspense>
|
||||
|
|
|
|||
|
|
@ -50,8 +50,10 @@ export const env = createEnv({
|
|||
// Misc UI flags
|
||||
SECURITY_CARD_ENABLED: booleanSchema.default('false'),
|
||||
},
|
||||
// @NOTE: Make sure you destructure all client variables in the
|
||||
// `experimental__runtimeEnv` block below.
|
||||
// @NOTE: Please make sure of the following:
|
||||
// - Make sure you destructure all client variables in
|
||||
// the `experimental__runtimeEnv` block below.
|
||||
// - Update the Dockerfile to pass these variables as build-args.
|
||||
client: {
|
||||
// PostHog
|
||||
NEXT_PUBLIC_POSTHOG_PAPIK: z.string().optional(),
|
||||
|
|
@ -59,12 +61,15 @@ export const env = createEnv({
|
|||
// Misc
|
||||
NEXT_PUBLIC_SOURCEBOT_VERSION: z.string().default('unknown'),
|
||||
NEXT_PUBLIC_POLLING_INTERVAL_MS: numberSchema.default(5000),
|
||||
|
||||
NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT: z.enum(["dev", "staging", "prod"]).optional(),
|
||||
},
|
||||
// For Next.js >= 13.4.4, you only need to destructure client variables:
|
||||
experimental__runtimeEnv: {
|
||||
NEXT_PUBLIC_POSTHOG_PAPIK: process.env.NEXT_PUBLIC_POSTHOG_PAPIK,
|
||||
NEXT_PUBLIC_SOURCEBOT_VERSION: process.env.NEXT_PUBLIC_SOURCEBOT_VERSION,
|
||||
NEXT_PUBLIC_POLLING_INTERVAL_MS: process.env.NEXT_PUBLIC_POLLING_INTERVAL_MS,
|
||||
NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT: process.env.NEXT_PUBLIC_SOURCEBOT_CLOUD_ENVIRONMENT,
|
||||
},
|
||||
skipValidation: process.env.SKIP_ENV_VALIDATION === "1",
|
||||
emptyStringAsUndefined: true,
|
||||
|
|
|
|||
|
|
@ -244,6 +244,10 @@ export type PosthogEventMap = {
|
|||
wa_demo_card_click: {},
|
||||
wa_demo_try_card_pressed: {},
|
||||
wa_share_link_created: {},
|
||||
//////////////////////////////////////////////////////////////////
|
||||
$pageview: {
|
||||
$current_url: string,
|
||||
},
|
||||
}
|
||||
|
||||
export type PosthogEvent = keyof PosthogEventMap;
|
||||
Loading…
Reference in a new issue