diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4749858..9d855ad 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -370,6 +370,9 @@ importers:
postgres:
specifier: ^3.4.3
version: 3.4.4
+ posthog-js:
+ specifier: ^1.130.0
+ version: 1.130.0
react:
specifier: 18.2.0
version: 18.2.0
@@ -6202,6 +6205,10 @@ packages:
dependencies:
reusify: 1.0.4
+ /fflate@0.4.8:
+ resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
+ dev: false
+
/file-entry-cache@6.0.1:
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
engines: {node: ^10.12.0 || >=12.0.0}
@@ -8652,6 +8659,13 @@ packages:
engines: {node: '>=12'}
dev: false
+ /posthog-js@1.130.0:
+ resolution: {integrity: sha512-bCrw5HunoXLybO20Q1bYEg68i5WCZWKxhStYJK4OR/9jrm7GwZ53GDrN78p8apFi0EH5ay4YZGbLFSkg+SsZWQ==}
+ dependencies:
+ fflate: 0.4.8
+ preact: 10.19.3
+ dev: false
+
/preact-render-to-string@5.2.3(preact@10.11.3):
resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==}
peerDependencies:
diff --git a/starterkits/saas/.env.example b/starterkits/saas/.env.example
index 575c006..1b5df5f 100644
--- a/starterkits/saas/.env.example
+++ b/starterkits/saas/.env.example
@@ -39,3 +39,7 @@ UPLOADTHING_ID=""
LEMONSQUEEZY_API_KEY=""
LEMONSQUEEZY_STORE_ID=""
LEMONSQUEEZY_WEBHOOK_SECRET=""
+
+# Posthog
+NEXT_PUBLIC_POSTHOG_KEY=""
+NEXT_PUBLIC_POSTHOG_HOST=""
\ No newline at end of file
diff --git a/starterkits/saas/package.json b/starterkits/saas/package.json
index 56fd1ef..efd0d87 100644
--- a/starterkits/saas/package.json
+++ b/starterkits/saas/package.json
@@ -53,6 +53,7 @@
"next-themes": "^0.3.0",
"nodemailer": "^6.9.13",
"postgres": "^3.4.3",
+ "posthog-js": "^1.130.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.51.3",
diff --git a/starterkits/saas/src/components/posthog-provider.tsx b/starterkits/saas/src/components/posthog-provider.tsx
new file mode 100644
index 0000000..a2fd2fb
--- /dev/null
+++ b/starterkits/saas/src/components/posthog-provider.tsx
@@ -0,0 +1,42 @@
+"use client";
+
+import { env } from "@/env";
+import { useSession } from "next-auth/react";
+import posthog from "posthog-js";
+import { PostHogProvider as CSPostHogProvider } from "posthog-js/react";
+import { useEffect } from "react";
+
+if (typeof window !== "undefined") {
+ posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, {
+ api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
+ });
+}
+
+type PostHogProviderProps = {
+ children: React.ReactNode;
+};
+
+export function PosthogProvider({ children }: PostHogProviderProps) {
+ return (
+
+ {children}
+
+ );
+}
+
+function PosthogAuthWrapper({ children }: PostHogProviderProps) {
+ const { data: session, status } = useSession();
+
+ useEffect(() => {
+ if (status === "authenticated") {
+ posthog.identify(session.user.id, {
+ email: session.user.email,
+ name: session.user.name,
+ });
+ } else if (status === "unauthenticated") {
+ posthog.reset();
+ }
+ }, [session, status]);
+
+ return children;
+}
diff --git a/starterkits/saas/src/components/providers.tsx b/starterkits/saas/src/components/providers.tsx
index f0d4745..44fd314 100644
--- a/starterkits/saas/src/components/providers.tsx
+++ b/starterkits/saas/src/components/providers.tsx
@@ -2,6 +2,8 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ThemeProvider } from "@/components/theme-provider";
+import { PosthogProvider } from "@/components/posthog-provider";
+import { SessionProvider } from "next-auth/react";
type ProvidersProps = {
children: React.ReactNode;
@@ -11,8 +13,12 @@ export function Providers({ children }: ProvidersProps) {
const queryClient = new QueryClient();
return (
-
- {children}
-
+
+
+
+ {children}
+
+
+
);
}
diff --git a/starterkits/saas/src/env.js b/starterkits/saas/src/env.js
index 8700e9c..dbff56d 100644
--- a/starterkits/saas/src/env.js
+++ b/starterkits/saas/src/env.js
@@ -41,6 +41,8 @@ export const env = createEnv({
*/
client: {
// NEXT_PUBLIC_CLIENTVAR: z.string(),
+ NEXT_PUBLIC_POSTHOG_KEY: z.string(),
+ NEXT_PUBLIC_POSTHOG_HOST: z.string().url(),
},
/**
@@ -62,6 +64,8 @@ export const env = createEnv({
LEMONSQUEEZY_API_KEY: process.env.LEMONSQUEEZY_API_KEY,
LEMONSQUEEZY_STORE_ID: process.env.LEMONSQUEEZY_STORE_ID,
LEMONSQUEEZY_WEBHOOK_SECRET: process.env.LEMONSQUEEZY_WEBHOOK_SECRET,
+ NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
+ NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially