Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat[mixpanel]: integration of mix panel for analytics #43

Merged
merged 5 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/app/api/v1/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ def get_user_api_key(db: Session = Depends(get_db)):

@user_router.get("/getme", status_code=200)
def get_me(db: Session = Depends(get_db)):
user_email = "[email protected]"
user = user_repository.get_user(db, user_email)
users = user_repository.get_users(db, n=1)


return {
"status": "success",
"message": "User details returned successfully!",
"data": user,
"data": users[0] if len(users) > 0 else None,
}


Expand Down
3 changes: 2 additions & 1 deletion frontend/.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
NEXT_PUBLIC_API_URL=http://localhost:3000/api/v1
NEXT_PUBLIC_STORAGE_URL=http://localhost:3000/api/assets
NEXT_PUBLIC_STORAGE_URL=http://localhost:3000/api/assets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security Risk: Remove the actual Mixpanel token from the example file

The Mixpanel token appears to be a real API token. Exposing actual tokens in version control is a security risk as they could be misused if compromised.

Replace the actual token with a placeholder value:

-NEXT_PUBLIC_MIXPANEL_TOKEN=f2e8a71ab2bde33ebf346c5abf6ba9fa
+NEXT_PUBLIC_MIXPANEL_TOKEN=your_mixpanel_token_here

Additionally, if this is a real token, please:

  1. Invalidate this token immediately
  2. Generate a new token
  3. Update the token in your deployment environments
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
NEXT_PUBLIC_MIXPANEL_TOKEN=f2e8a71ab2bde33ebf346c5abf6ba9fa
NEXT_PUBLIC_MIXPANEL_TOKEN=your_mixpanel_token_here
🧰 Tools
🪛 Gitleaks

3-3: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

NEXT_PUBLIC_MIXPANEL_TOKEN=f2e8a71ab2bde33ebf346c5abf6ba9fa
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"@react-pdf/renderer": "^4.0.0",
"@tanstack/react-query": "^5.51.1",
"@tippyjs/react": "^4.2.6",
"@types/mixpanel-browser": "^2.50.1",
"axios": "^1.7.2",
"date-fns": "^3.6.0",
"framer-motion": "^11.3.31",
"lucide-react": "^0.408.0",
"marked": "^13.0.2",
"mixpanel-browser": "^2.55.1",
"next": "14.2.4",
"openai": "^4.52.5",
"papaparse": "^5.4.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import DataTable from "@/components/DataTable";
import Papa from "papaparse";
import { BASE_API_URL } from "@/constants";
import { toast } from "react-hot-toast";
import { trackEvent } from "@/lib/mixpanelLib";

const ProcessPage = () => {
const router = useRouter();
Expand Down Expand Up @@ -55,6 +56,8 @@ const ProcessPage = () => {
},
header: true,
});

trackEvent("Table opened", { url: `process_${processId}.csv` });
} catch (error) {
console.error("Error loading CSV data:", error);
setIsLoading(false);
Expand All @@ -77,6 +80,7 @@ const ProcessPage = () => {
document.body.removeChild(a);

// Show success toast
trackEvent("Download CSV", { url: `process_${processId}.csv` });
toast.success("CSV downloaded successfully");
} catch (error) {
console.error("Error downloading CSV:", error);
Expand Down
55 changes: 55 additions & 0 deletions frontend/src/lib/mixpanelLib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { GetUserData } from "@/services/user";
import mixpanel, { Mixpanel } from "mixpanel-browser";

const MIXPANEL_TOKEN = process.env.NEXT_PUBLIC_MIXPANEL_TOKEN;

let mixpanelInstance: Mixpanel | null = null;

let isInitialized = false;

const initMixpanel = async () => {
if (typeof window !== "undefined" && MIXPANEL_TOKEN && !isInitialized) {
mixpanel.init(MIXPANEL_TOKEN, {
debug: process.env.NODE_ENV === "development",
});

const user = await GetUserData();

if (user.data.data) {
mixpanel.identify(user.data.data.email);

mixpanel.people.set({
$name: `${user.data.data.first_name} ${user.data.data.last_name}`,
$email: user.data.data.email,
});
}

mixpanelInstance = mixpanel;
isInitialized = true;
} else if (!MIXPANEL_TOKEN) {
console.warn("Mixpanel token is missing; tracking will be disabled.");
}
};

const trackEvent = async (
eventName: string,
eventProps = {}
): Promise<void> => {
if (!isInitialized) {
initMixpanel();
}
if (mixpanelInstance) {
mixpanelInstance.track(eventName, eventProps);
} else {
console.warn(
`Event "${eventName}" not tracked because Mixpanel is not initialized.`
);
}
};

// Initialize Mixpanel on the client at import
if (typeof window !== "undefined") {
initMixpanel();
}

export { trackEvent };
2 changes: 2 additions & 0 deletions frontend/src/services/processes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ProcessResumeData,
ProcessSuggestionRequest,
} from "@/interfaces/processes";
import { trackEvent } from "@/lib/mixpanelLib";

export const processApiUrl = "/processes";

Expand Down Expand Up @@ -35,6 +36,7 @@ export const StartProcess = async (data: ProcessRequest) => {
`${processApiUrl}/start`,
data
);
trackEvent("Start Process", data);
return response;
} catch (error) {
throw error;
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/services/projects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AssetData } from "@/interfaces/assets";
import { ProcessData } from "@/interfaces/processes";
import { BASE_API_URL } from "@/constants";
import { AxiosResponse } from "axios";
import { trackEvent } from "@/lib/mixpanelLib";

const projectsApiUrl = "/projects";

Expand Down Expand Up @@ -49,6 +50,8 @@ export const CreateProject = async (data: {
projectsApiUrl,
data
);

trackEvent("Project created", { data });
return response;
} catch (error) {
throw error;
Expand Down Expand Up @@ -158,7 +161,6 @@ export const DeleteAssets = async (projectId: string, assetId: string) => {
}
};

// Add this new function to update a project
export const UpdateProject = async (
projectId: string,
data: { name: string; description: string }
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/services/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { GetRequest, PostRequest, PutRequest } from "@/lib/requests";
import { APIKeyData } from "@/interfaces/user";
import { UserData } from "@/interfaces/user";
import localStorage from "@/lib/localStorage";
import { trackEvent } from "@/lib/mixpanelLib";

const userApiUrl = "/user";

Expand All @@ -11,6 +12,7 @@ export const APIKeyRequest = async (data: { email: string }) => {
`${userApiUrl}/request-api-key`,
data
);
trackEvent("API Key Request", data);
return response;
} catch (error) {
throw error;
Expand All @@ -24,6 +26,10 @@ export const SaveAPIKey = async (data: { api_key: string }) => {
data
);
localStorage.setItem("api_key", data.api_key);
trackEvent("API Key Activation", {
timestamp: new Date().toISOString(),
success: true,
});
return response;
} catch (error) {
throw error;
Expand Down
94 changes: 91 additions & 3 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,13 @@
resolved "https://registry.npmjs.org/@react-types/shared/-/shared-3.24.1.tgz"
integrity sha512-AUQeGYEm/zDTN6zLzdXolDxz3Jk5dDL7f506F07U8tBwxNNI3WRdhU84G0/AaFikOZzDXhOZDr3MhQMzyE7Ydw==

"@rrweb/types@^2.0.0-alpha.13":
version "2.0.0-alpha.17"
resolved "https://registry.yarnpkg.com/@rrweb/types/-/types-2.0.0-alpha.17.tgz#bf4af026e767022674892919692d59e766e9368e"
integrity sha512-AfDTVUuCyCaIG0lTSqYtrZqJX39ZEYzs4fYKnexhQ+id+kbZIpIJtaut5cto6dWZbB3SEe4fW0o90Po3LvTmfg==
dependencies:
rrweb-snapshot "^2.0.0-alpha.17"

"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz"
Expand Down Expand Up @@ -746,6 +753,11 @@
dependencies:
tippy.js "^6.3.1"

"@types/[email protected]":
version "0.0.7"
resolved "https://registry.yarnpkg.com/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz#2f98ede46acc0975de85c0b7b0ebe06041d24601"
integrity sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==

"@types/debug@^4.0.0":
version "4.1.12"
resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz"
Expand Down Expand Up @@ -784,6 +796,11 @@
dependencies:
"@types/unist" "*"

"@types/mixpanel-browser@^2.50.1":
version "2.50.1"
resolved "https://registry.yarnpkg.com/@types/mixpanel-browser/-/mixpanel-browser-2.50.1.tgz#e93b8754893369bd0a9eae61ce2a45f392ca4e7f"
integrity sha512-Z9QnzNIZtsyhc0tvGFeaYCo2NJTGwWi8pqLMB3z/BnGUdEpr3x2qK28KKTjVH31DMbQ0IwqjNQElwJP+XpmeMQ==

"@types/ms@*":
version "0.7.34"
resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz"
Expand Down Expand Up @@ -918,6 +935,11 @@
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==

"@xstate/fsm@^1.4.0":
version "1.6.5"
resolved "https://registry.yarnpkg.com/@xstate/fsm/-/fsm-1.6.5.tgz#f599e301997ad7e3c572a0b1ff0696898081bea5"
integrity sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==

abbrev@1:
version "1.1.1"
resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz"
Expand Down Expand Up @@ -1188,6 +1210,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==

base64-arraybuffer@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc"
integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==

base64-js@^1.1.2, base64-js@^1.3.0:
version "1.5.1"
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
Expand Down Expand Up @@ -2123,6 +2150,11 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"

fflate@^0.4.4:
version "0.4.8"
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae"
integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==

file-entry-cache@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
Expand Down Expand Up @@ -3628,6 +3660,18 @@ minizlib@^2.1.1:
minipass "^3.0.0"
yallist "^4.0.0"

mitt@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==

mixpanel-browser@^2.55.1:
version "2.55.1"
resolved "https://registry.yarnpkg.com/mixpanel-browser/-/mixpanel-browser-2.55.1.tgz#d37a8d3777abd4c58d537ea87959c9d9b9b507c8"
integrity sha512-NSEPdFSJxoR1OCKWKHbtqd3BeH1c9NjXbEt0tN5TgBEO1nSDji6niU9n4MopAXOP0POET9spjpQKxZtLZKTJwA==
dependencies:
rrweb "2.0.0-alpha.13"

mkdirp@^1.0.3:
version "1.0.4"
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
Expand Down Expand Up @@ -4050,7 +4094,7 @@ [email protected]:
picocolors "^1.0.0"
source-map-js "^1.0.2"

postcss@^8, postcss@^8.4.23:
postcss@^8, postcss@^8.4.23, postcss@^8.4.38:
version "8.4.47"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz"
integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==
Expand Down Expand Up @@ -4408,6 +4452,34 @@ rimraf@^3.0.2:
dependencies:
glob "^7.1.3"

rrdom@^2.0.0-alpha.13:
version "2.0.0-alpha.17"
resolved "https://registry.yarnpkg.com/rrdom/-/rrdom-2.0.0-alpha.17.tgz#c200f21a63bab341caea7f3f2f88d760aa045c3a"
integrity sha512-b6caDiNcFO96Opp7TGdcVd4OLGSXu5dJe+A0IDiAu8mk7OmhqZCSDlgQdTKmdO5wMf4zPsUTgb8H/aNvR3kDHA==
dependencies:
rrweb-snapshot "^2.0.0-alpha.17"

rrweb-snapshot@^2.0.0-alpha.13, rrweb-snapshot@^2.0.0-alpha.17:
version "2.0.0-alpha.17"
resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-2.0.0-alpha.17.tgz#c4667cbca62530bcb98508e6c85c20f2b320f5ca"
integrity sha512-GBg5pV8LHOTbeVmH2VHLEFR0mc2QpQMzAvcoxEGfPNWgWHc8UvKCyq7pqN1vA+fDZ+yXXbixeO0kB2pzVvFCBw==
dependencies:
postcss "^8.4.38"

[email protected]:
version "2.0.0-alpha.13"
resolved "https://registry.yarnpkg.com/rrweb/-/rrweb-2.0.0-alpha.13.tgz#37798404acd985212f72544c8823af275fdad514"
integrity sha512-a8GXOCnzWHNaVZPa7hsrLZtNZ3CGjiL+YrkpLo0TfmxGLhjNZbWY2r7pE06p+FcjFNlgUVTmFrSJbK3kO7yxvw==
dependencies:
"@rrweb/types" "^2.0.0-alpha.13"
"@types/css-font-loading-module" "0.0.7"
"@xstate/fsm" "^1.4.0"
base64-arraybuffer "^1.0.1"
fflate "^0.4.4"
mitt "^3.0.0"
rrdom "^2.0.0-alpha.13"
rrweb-snapshot "^2.0.0-alpha.13"

run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
Expand Down Expand Up @@ -4592,7 +4664,16 @@ string-argv@~0.3.2:
resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz"
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==

"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -4696,7 +4777,14 @@ stringify-entities@^4.0.0:
character-entities-html4 "^2.0.0"
character-entities-legacy "^3.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down
Loading