Skip to content
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
2 changes: 2 additions & 0 deletions app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useEffect } from "react";
import Link from "next/link";
import { captureException } from "@/lib/posthog/helpers";

export default function ErrorPage({
error,
Expand All @@ -12,6 +13,7 @@ export default function ErrorPage({
}) {
useEffect(() => {
console.error(error);
captureException(error, { digest: error.digest });
}, [error]);

return (
Expand Down
12 changes: 3 additions & 9 deletions app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,8 @@ import { useEffect, Suspense } from "react";
import { usePathname, useSearchParams } from "next/navigation";
import posthog from "posthog-js";
import { PostHogProvider as PHProvider } from "posthog-js/react";

if (typeof window !== "undefined") {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
person_profiles: "identified_only",
capture_pageview: false,
});
}
import { captureEvent } from "@/lib/posthog/helpers";
import { POSTHOG_EVENTS } from "@/lib/posthog/events";

function PostHogPageTracker() {
const pathname = usePathname();
Expand All @@ -23,7 +17,7 @@ function PostHogPageTracker() {
if (searchParams.toString()) {
url += `?${searchParams.toString()}`;
}
posthog.capture("$pageview", { $current_url: url });
captureEvent(POSTHOG_EVENTS.PAGE_VIEW, { $current_url: url });
}
}, [pathname, searchParams]);

Expand Down
11 changes: 5 additions & 6 deletions components/BookEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import { useState } from "react";
import { createBooking } from "@/lib/actions/booking.actions";
import posthog from "posthog-js";
import { captureEvent } from "@/lib/posthog/helpers";
import { POSTHOG_EVENTS } from "@/lib/posthog/events";

const BookEvent = ({ eventId, slug }: { eventId: string; slug: string }) => {
const [email, setEmail] = useState('');
Expand All @@ -27,10 +28,10 @@ const BookEvent = ({ eventId, slug }: { eventId: string; slug: string }) => {
if (response.success) {
setSubmitted(true);
// Do not send raw email (PII) to analytics.
posthog.capture('event_booked', { eventId, slug });
captureEvent(POSTHOG_EVENTS.EVENT_BOOKED, { eventId, slug });
} else {
setError(response.error || "An unexpected error occurred. Please try again.");
posthog.captureException('Booking creation failed');
captureEvent(POSTHOG_EVENTS.BOOKING_FAILED, { eventId, slug, email });
Comment thread
SatyamPandey-07 marked this conversation as resolved.
}
} catch {
setError("A network error occurred. Please try again.");
Expand All @@ -54,13 +55,11 @@ const BookEvent = ({ eventId, slug }: { eventId: string; slug: string }) => {
id="email"
placeholder="Enter your email address"
required
disabled={isSubmitting} // 1. Freeze input when submitting
disabled={isSubmitting}
/>
{/* 2. Show the red error message under the input if an error occurs */}
{error && <p className="text-red-500 text-xs mt-1">{error}</p>}
</div>

{/* 3. Disable the button and change text dynamically */}
<button type="submit" className="button-submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
Expand Down
13 changes: 13 additions & 0 deletions components/CreateNewEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "sonner";
import { createEvent } from "@/lib/actions/create-event.actions";
import { captureEvent, captureException } from "@/lib/posthog/helpers";
import { POSTHOG_EVENTS } from "@/lib/posthog/events";

const eventSchema = z.object({
title: z.string().min(3, "Title must be at least 3 characters"),
Expand Down Expand Up @@ -63,12 +65,22 @@ const CreateEventForm = () => {
if (result.success) {

toast.success("Event created successfully!");
captureEvent(POSTHOG_EVENTS.EVENT_CREATED, {
type: data.type,
mode: data.mode,
location: data.location,
});

reset();

} else {

toast.error(result.error || "Failed to create event");
captureEvent(POSTHOG_EVENTS.EVENT_CREATION_FAILED, {
reason: result.error || "unknown",
type: data.type,
mode: data.mode,
});

}

Expand All @@ -77,6 +89,7 @@ const CreateEventForm = () => {
console.error(error);

toast.error("Something went wrong");
captureException(error instanceof Error ? error : new Error("event_creation_exception"));

}
};
Expand Down
8 changes: 7 additions & 1 deletion components/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
import { captureEvent } from "@/lib/posthog/helpers";
import { POSTHOG_EVENTS } from "@/lib/posthog/events";

interface Props {
title: string;
Expand Down Expand Up @@ -48,19 +50,23 @@ const EventCard = ({
(item: string) => item !== slug
);
setBookmarked(false);
captureEvent(POSTHOG_EVENTS.EVENT_UNBOOKMARKED, { slug, title });
} else {
updated = [...saved, slug];
setBookmarked(true);
captureEvent(POSTHOG_EVENTS.EVENT_BOOKMARKED, { slug, title });
}

localStorage.setItem(
"bookmarkedEvents",
JSON.stringify(updated)
);
};

return (
<Link
href={`/events/${slug}`}
onClick={() => captureEvent(POSTHOG_EVENTS.EVENT_VIEWED, { slug, title })}
className="
event-card
group
Expand Down Expand Up @@ -139,4 +145,4 @@ const EventCard = ({
);
};

export default EventCard;
export default EventCard;
6 changes: 6 additions & 0 deletions components/SearchFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import { useRouter, useSearchParams, usePathname } from 'next/navigation';
import { useState, useEffect } from 'react';
import { captureEvent } from '@/lib/posthog/helpers';
import { POSTHOG_EVENTS } from '@/lib/posthog/events';

const MODES = ['All', 'Online', 'Offline', 'Hybrid'];
const POPULAR_TAGS = ['All', 'Hackathon', 'Meetup', 'Web3', 'React', 'DevOps', 'AI'];
Expand All @@ -21,11 +23,15 @@ export default function SearchFilters() {
params.delete(key);
}
router.push(`${pathname}?${params.toString()}`, { scroll: false });
captureEvent(POSTHOG_EVENTS.EVENT_FILTER_CHANGED, { filter: key, value });
};

useEffect(() => {
const delayDebounceFn = setTimeout(() => {
handleFilterChange('query', search);
if (search.trim()) {
captureEvent(POSTHOG_EVENTS.EVENT_SEARCHED, { query: search });
}
Comment thread
SatyamPandey-07 marked this conversation as resolved.
}, 400);
return () => clearTimeout(delayDebounceFn);
}, [search]);
Expand Down
5 changes: 5 additions & 0 deletions instrumentation-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import posthog from "posthog-js";

posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
});
9 changes: 0 additions & 9 deletions lib/posthog.js

This file was deleted.

21 changes: 21 additions & 0 deletions lib/posthog/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export const POSTHOG_EVENTS = {
// Navigation
PAGE_VIEW: "$pageview",

// Event discovery
EVENT_VIEWED: "event_viewed",
EVENT_SEARCHED: "event_searched",
EVENT_FILTER_CHANGED: "event_filter_changed",

// Bookmarks
EVENT_BOOKMARKED: "event_bookmarked",
EVENT_UNBOOKMARKED: "event_unbookmarked",

// Booking
EVENT_BOOKED: "event_booked",
BOOKING_FAILED: "booking_failed",

// Creation
EVENT_CREATED: "event_created",
EVENT_CREATION_FAILED: "event_creation_failed",
} as const;
22 changes: 22 additions & 0 deletions lib/posthog/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import posthog from "posthog-js";

export function identifyUser(
userId: string,
traits?: Record<string, unknown>
) {
posthog.identify(userId, traits);
}

export function captureEvent(
event: string,
properties?: Record<string, unknown>
) {
posthog.capture(event, properties);
}

export function captureException(
error: unknown,
properties?: Record<string, unknown>
) {
posthog.captureException(error, properties);
}
Loading