[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:
Mamadou DICKO 2023-06-26 11:36:15 +02:00 committed by GitHub
parent 5fc837b250
commit 97d2c9de10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1075 additions and 17 deletions

View File

@ -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>

View File

@ -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");
}

View File

@ -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>

View File

@ -0,0 +1,8 @@
"use client";
import { usePageTracking } from "@/services/analytics/usePageTracking";
export const TrackingWrapper = (): JSX.Element => {
usePageTracking();
return <></>;
};

View File

@ -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",

View 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,
};
};

View 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;
};

View 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