mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-25 04:12:44 +03:00
[Analytics]: Add tracking (#375)
* feat: add june tracking config * feat(tracking): add page view tracking * feat(tracking): add event tracking
This commit is contained in:
parent
5fc837b250
commit
97d2c9de10
@ -4,3 +4,4 @@ NEXT_PUBLIC_SUPABASE_URL=XXXX
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=XXX
|
||||
NEXT_PUBLIC_GROWTHBOOK_URL=https://cdn.growthbook.io/api/features/sdk-AjVqDdrxa4ETFCoD
|
||||
NEXT_PUBLIC_GROWTHBOOK_API_KEY = "sdk-AjVqDdrxa4ETFCoD"
|
||||
NEXT_PUBLIC_JUNE_API_KEY=<change-me>
|
@ -12,6 +12,7 @@ import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
|
||||
import { useEventTracking } from "@/services/analytics/useEventTracking";
|
||||
import { GoogleLoginButton } from "./components/GoogleLogin";
|
||||
import { MagicLinkLogin } from "./components/MagicLinkLogin";
|
||||
|
||||
@ -20,8 +21,8 @@ export default function Login() {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
|
||||
const { publish } = useToast();
|
||||
const { track } = useEventTracking();
|
||||
|
||||
const handleLogin = async () => {
|
||||
setIsPending(true);
|
||||
@ -45,6 +46,7 @@ export default function Login() {
|
||||
};
|
||||
|
||||
if (session?.user !== undefined) {
|
||||
track("SIGNED_IN");
|
||||
redirect("/upload");
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,11 @@ import { cookies, headers } from "next/headers";
|
||||
|
||||
import Footer from "@/lib/components/Footer";
|
||||
import { NavBar } from "@/lib/components/NavBar";
|
||||
import { TrackingWrapper } from "@/lib/components/TrackingWrapper";
|
||||
import { ToastProvider } from "@/lib/components/ui/Toast";
|
||||
import { BrainProvider, FeatureFlagsProvider } from "@/lib/context";
|
||||
import { BrainConfigProvider } from "@/lib/context/BrainConfigProvider/brain-config-provider";
|
||||
import { SupabaseProvider } from "@/lib/context/SupabaseProvider";
|
||||
|
||||
import "./globals.css";
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] });
|
||||
@ -40,17 +40,18 @@ const RootLayout = async ({
|
||||
className={`bg-white text-black min-h-screen flex flex-col dark:bg-black dark:text-white w-full ${inter.className}`}
|
||||
>
|
||||
<FeatureFlagsProvider>
|
||||
<ToastProvider>
|
||||
<SupabaseProvider session={session}>
|
||||
<BrainConfigProvider>
|
||||
<BrainProvider>
|
||||
<NavBar />
|
||||
<div className="flex-1">{children}</div>
|
||||
<Footer />
|
||||
</BrainProvider>
|
||||
</BrainConfigProvider>
|
||||
</SupabaseProvider>
|
||||
</ToastProvider>
|
||||
<ToastProvider>
|
||||
<SupabaseProvider session={session}>
|
||||
<BrainConfigProvider>
|
||||
<BrainProvider>
|
||||
<TrackingWrapper />
|
||||
<NavBar />
|
||||
<div className="flex-1">{children}</div>
|
||||
<Footer />
|
||||
</BrainProvider>
|
||||
</BrainConfigProvider>
|
||||
</SupabaseProvider>
|
||||
</ToastProvider>
|
||||
<Analytics />
|
||||
</FeatureFlagsProvider>
|
||||
</body>
|
||||
|
8
frontend/lib/components/TrackingWrapper.tsx
Normal file
8
frontend/lib/components/TrackingWrapper.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
"use client";
|
||||
import { usePageTracking } from "@/services/analytics/usePageTracking";
|
||||
|
||||
export const TrackingWrapper = (): JSX.Element => {
|
||||
usePageTracking();
|
||||
|
||||
return <></>;
|
||||
};
|
@ -18,6 +18,7 @@
|
||||
"@emotion/react": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@growthbook/growthbook-react": "^0.17.0",
|
||||
"@june-so/analytics-next": "^2.0.0",
|
||||
"@radix-ui/react-dialog": "^1.0.3",
|
||||
"@radix-ui/react-toast": "^1.1.3",
|
||||
"@radix-ui/react-tooltip": "^1.0.6",
|
||||
|
22
frontend/services/analytics/useEventTracking.ts
Normal file
22
frontend/services/analytics/useEventTracking.ts
Normal file
@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
|
||||
import { useJune } from "./useJune";
|
||||
|
||||
type TrackedEvent = "SIGNED_IN";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const useEventTracking = () => {
|
||||
const analytics = useJune();
|
||||
const { session } = useSupabase();
|
||||
|
||||
const track = async (event: TrackedEvent): Promise<void> => {
|
||||
await analytics?.identify(session?.user.id);
|
||||
await analytics?.track(event);
|
||||
};
|
||||
|
||||
return {
|
||||
track,
|
||||
};
|
||||
};
|
25
frontend/services/analytics/useJune.ts
Normal file
25
frontend/services/analytics/useJune.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { AnalyticsBrowser } from "@june-so/analytics-next";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
const juneApiKey = process.env.NEXT_PUBLIC_JUNE_API_KEY;
|
||||
|
||||
export const useJune = (): AnalyticsBrowser | undefined => {
|
||||
const [analytics, setAnalytics] = useState<AnalyticsBrowser | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const loadAnalytics = () => {
|
||||
if (juneApiKey === undefined) {
|
||||
return;
|
||||
}
|
||||
const response = AnalyticsBrowser.load({
|
||||
writeKey: juneApiKey,
|
||||
});
|
||||
setAnalytics(response);
|
||||
};
|
||||
loadAnalytics();
|
||||
}, []);
|
||||
|
||||
return analytics;
|
||||
};
|
25
frontend/services/analytics/usePageTracking.ts
Normal file
25
frontend/services/analytics/usePageTracking.ts
Normal file
@ -0,0 +1,25 @@
|
||||
"use client";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
|
||||
import { useJune } from "./useJune";
|
||||
|
||||
export const usePageTracking = (): void => {
|
||||
const analytics = useJune();
|
||||
const pathname = usePathname();
|
||||
const { session } = useSupabase();
|
||||
|
||||
useEffect(() => {
|
||||
if (pathname !== null) {
|
||||
const handleRouteChange = async () => {
|
||||
await analytics?.identify(session?.user.id);
|
||||
await analytics?.page(pathname);
|
||||
};
|
||||
|
||||
void handleRouteChange();
|
||||
}
|
||||
}, [analytics, pathname, session?.user.id]);
|
||||
};
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user