Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40860c3eff | ||
|
|
92b89f26af |
+102
-4
@@ -1,9 +1,14 @@
|
||||
import { emptyAnalytics, jitsuAnalytics } from "@jitsu/js";
|
||||
import { PostHog } from "posthog-node";
|
||||
import { posthog } from "posthog-js";
|
||||
|
||||
import { getPostHogConfig } from "@/lib/posthog";
|
||||
import { AnalyticsEvents } from "@/lib/types";
|
||||
|
||||
// =============================================================================
|
||||
// Client-side Analytics (PostHog via posthog-js)
|
||||
// =============================================================================
|
||||
|
||||
export function useAnalytics() {
|
||||
const isPostHogEnabled = getPostHogConfig();
|
||||
|
||||
@@ -38,8 +43,11 @@ export function useAnalytics() {
|
||||
};
|
||||
}
|
||||
|
||||
// For server-side tracking
|
||||
const analytics =
|
||||
// =============================================================================
|
||||
// Server-side Analytics (Jitsu)
|
||||
// =============================================================================
|
||||
|
||||
const jitsu =
|
||||
process.env.JITSU_HOST && process.env.JITSU_WRITE_KEY
|
||||
? jitsuAnalytics({
|
||||
host: process.env.JITSU_HOST,
|
||||
@@ -47,5 +55,95 @@ const analytics =
|
||||
})
|
||||
: emptyAnalytics;
|
||||
|
||||
export const identifyUser = (userId: string) => analytics.identify(userId);
|
||||
export const trackAnalytics = (args: AnalyticsEvents) => analytics.track(args);
|
||||
export const identifyUser = (userId: string) => jitsu.identify(userId);
|
||||
export const trackAnalytics = (args: AnalyticsEvents) => jitsu.track(args);
|
||||
|
||||
// =============================================================================
|
||||
// Server-side Analytics (PostHog via posthog-node)
|
||||
// =============================================================================
|
||||
|
||||
let posthogServerClient: PostHog | null = null;
|
||||
|
||||
function getPostHogServerClient(): PostHog | null {
|
||||
const postHogKey = process.env.NEXT_PUBLIC_POSTHOG_KEY;
|
||||
|
||||
if (!postHogKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!posthogServerClient) {
|
||||
posthogServerClient = new PostHog(postHogKey, {
|
||||
host: "https://eu.i.posthog.com",
|
||||
// Flush events immediately in serverless environments
|
||||
flushAt: 1,
|
||||
flushInterval: 0,
|
||||
});
|
||||
}
|
||||
|
||||
return posthogServerClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side analytics helper for PostHog.
|
||||
* Similar pattern to the client-side useAnalytics hook.
|
||||
*/
|
||||
export const analytics = {
|
||||
/**
|
||||
* Capture an analytic event server-side.
|
||||
*
|
||||
* @param distinctId The user's unique identifier (typically email or userId).
|
||||
* @param event The event name.
|
||||
* @param properties Properties to attach to the event.
|
||||
*/
|
||||
capture: async ({
|
||||
distinctId,
|
||||
event,
|
||||
properties,
|
||||
}: {
|
||||
distinctId: string;
|
||||
event: string;
|
||||
properties?: Record<string, unknown>;
|
||||
}): Promise<void> => {
|
||||
const client = getPostHogServerClient();
|
||||
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
client.capture({
|
||||
distinctId,
|
||||
event,
|
||||
properties,
|
||||
});
|
||||
|
||||
// Flush immediately to ensure event is sent before response
|
||||
await client.flush();
|
||||
},
|
||||
|
||||
/**
|
||||
* Identify a user server-side.
|
||||
*
|
||||
* @param distinctId The user's unique identifier (typically email or userId).
|
||||
* @param properties User properties to set.
|
||||
*/
|
||||
identify: async ({
|
||||
distinctId,
|
||||
properties,
|
||||
}: {
|
||||
distinctId: string;
|
||||
properties?: Record<string, unknown>;
|
||||
}): Promise<void> => {
|
||||
const client = getPostHogServerClient();
|
||||
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
client.identify({
|
||||
distinctId,
|
||||
properties,
|
||||
});
|
||||
|
||||
await client.flush();
|
||||
},
|
||||
};
|
||||
|
||||
Generated
+22
@@ -113,6 +113,7 @@
|
||||
"pdf-lib": "^1.17.1",
|
||||
"postcss": "^8.5.6",
|
||||
"posthog-js": "^1.336.1",
|
||||
"posthog-node": "^5.21.2",
|
||||
"react": "^18.3.1",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-day-picker": "^8.10.1",
|
||||
@@ -17590,6 +17591,27 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/posthog-node": {
|
||||
"version": "5.21.2",
|
||||
"resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.21.2.tgz",
|
||||
"integrity": "sha512-Jehlu0KguL1LLyUczCt86OtA5INmeStK3zcgbv1BSyMcNxs0HP3GQogBrYhwhqHsk6JopiFFVpJyZEoXOUMhGw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@posthog/core": "1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/posthog-node/node_modules/@posthog/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-Xk3JQ+cdychsvftrV3G9ZrN9W329lbyFW0pGJXFGKFQf8qr4upw2SgNg9BVorjSrfhoXZRnJGt/uNF4nGFBL5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.28.2",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.28.2.tgz",
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
"pdf-lib": "^1.17.1",
|
||||
"postcss": "^8.5.6",
|
||||
"posthog-js": "^1.336.1",
|
||||
"posthog-node": "^5.21.2",
|
||||
"react": "^18.3.1",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-day-picker": "^8.10.1",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
||||
import { getServerSession } from "next-auth";
|
||||
|
||||
import { identifyUser, trackAnalytics } from "@/lib/analytics";
|
||||
import { analytics, identifyUser, trackAnalytics } from "@/lib/analytics";
|
||||
import { errorhandler } from "@/lib/errorHandler";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { CustomUser } from "@/lib/types";
|
||||
@@ -120,6 +120,16 @@ export default async function handle(
|
||||
teamId: teamId,
|
||||
});
|
||||
|
||||
// Track in PostHog
|
||||
await analytics.capture({
|
||||
distinctId: invitation.email,
|
||||
event: "Team Member Invitation Accepted",
|
||||
properties: {
|
||||
teamId: teamId,
|
||||
userId: userId,
|
||||
},
|
||||
});
|
||||
|
||||
// delete the invitation record after user is successfully added to the team
|
||||
await prisma.invitation.delete({
|
||||
where: {
|
||||
|
||||
Reference in New Issue
Block a user