Openstatus
www.openstatus.dev
1import { OpenPanel, type PostEventPayload } from "@openpanel/sdk";
2import { env } from "../env";
3import type { EventProps } from "./events";
4
5const op = new OpenPanel({
6 clientId: env.NEXT_PUBLIC_OPENPANEL_CLIENT_ID,
7 clientSecret: env.OPENPANEL_CLIENT_SECRET,
8});
9
10op.setGlobalProperties({
11 env: process.env.VERCEL_ENV || process.env.NODE_ENV || "localhost",
12 // app_version
13});
14
15export type IdentifyProps = {
16 userId?: string;
17 fullName?: string | null;
18 email?: string;
19 workspaceId?: string;
20 plan?: "free" | "starter" | "team";
21 // headers from the request
22 location?: string;
23 userAgent?: string;
24};
25
26export async function setupAnalytics(props: IdentifyProps) {
27 if (process.env.NODE_ENV !== "production") {
28 return noop();
29 }
30
31 if (props.location) {
32 op.api.addHeader("x-client-ip", props.location);
33 }
34
35 if (props.userAgent) {
36 op.api.addHeader("user-agent", props.userAgent);
37 }
38
39 if (props.userId) {
40 const [firstName, lastName] = props.fullName?.split(" ") || [];
41 await op.identify({
42 profileId: props.userId,
43 email: props.email,
44 firstName: firstName,
45 lastName: lastName,
46 properties: {
47 workspaceId: props.workspaceId,
48 plan: props.plan,
49 },
50 });
51 }
52
53 return {
54 track: (opts: EventProps & PostEventPayload["properties"]) => {
55 const { name, ...rest } = opts;
56 return op.track(name, rest);
57 },
58 };
59}
60
61/**
62 * Noop analytics for development environment
63 */
64async function noop() {
65 return {
66 track: (
67 opts: EventProps & PostEventPayload["properties"],
68 ): Promise<unknown> => {
69 return new Promise((resolve) => {
70 console.log(`>>> Track Noop Event: ${opts.name}`);
71 resolve(null);
72 });
73 },
74 };
75}