diff --git a/backend/app/api/endpoints/search_endpoint.py b/backend/app/api/endpoints/search_endpoint.py
index 734a5093..56d13183 100644
--- a/backend/app/api/endpoints/search_endpoint.py
+++ b/backend/app/api/endpoints/search_endpoint.py
@@ -29,7 +29,7 @@
summary="List all Search Results",
description="List all Search Results",
dependencies=[Depends(security.access_token_required)],
- response_model=str,
+ response_model=dict[str, str]
)
@version(1, 0)
async def get_search_results(
@@ -54,7 +54,7 @@ async def get_search_results(
logger.info(f"get_search_results. result: {search_result}")
- return JSONResponse(status_code=200, content=search_result)
+ return JSONResponse(status_code=200, content={"result": search_result})
@router.get(
diff --git a/backend/app/config.py b/backend/app/config.py
index 759e22b8..8d7013bd 100644
--- a/backend/app/config.py
+++ b/backend/app/config.py
@@ -127,6 +127,7 @@
# Sentry Configuration
SENTRY_DSN: Secret = config("SENTRY_DSN", cast=Secret)
+SENTRY_ENABLE_TRACING: bool = config("SENTRY_ENABLE_TRACING", cast=bool, default=False)
# GROQ API Configuration
diff --git a/backend/app/services/tracing.py b/backend/app/services/tracing.py
index 675eb5dd..4736beae 100644
--- a/backend/app/services/tracing.py
+++ b/backend/app/services/tracing.py
@@ -5,12 +5,12 @@
from sentry_sdk.integrations.starlette import StarletteIntegration
from sentry_sdk.integrations.fastapi import FastApiIntegration
-from app.config import SENTRY_DSN
+from app.config import SENTRY_DSN, SENTRY_ENABLE_TRACING
def setup_tracing():
sentry_sdk.init(
dsn=str(SENTRY_DSN),
- enable_tracing=True,
+ enable_tracing=SENTRY_ENABLE_TRACING,
integrations=[
AsyncioIntegration(),
StarletteIntegration(
diff --git a/frontend/README.md b/frontend/README.md
index fc96b081..6f514803 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -10,6 +10,14 @@ Install `yarn`
## Getting Started
+Create a `.env.local` file in the root of the project and add the following environment variables:
+
+```bash
+NEXT_PUBLIC_POSTHOG_KEY=
+NEXT_PUBLIC_POSTHOG_API_HOST=
+NEXT_PUBLIC_POSTHOG_UI_HOST=
+```
+
Run the development server:
```bash
diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs
index b11bca44..71101f37 100644
--- a/frontend/next.config.mjs
+++ b/frontend/next.config.mjs
@@ -8,6 +8,14 @@ const nextConfig = {
source: '/api/:path*',
destination: 'http://127.0.0.1:8000/:path*',
},
+ {
+ source: "/ingest/static/:path*",
+ destination: "https://us-assets.i.posthog.com/static/:path*",
+ },
+ {
+ source: "/ingest/:path*",
+ destination: "https://us.i.posthog.com/:path*",
+ },
]
};
}
diff --git a/frontend/package.json b/frontend/package.json
index 84552552..3fe5bc23 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -18,6 +18,7 @@
"nanoid": "^5.0.6",
"next": "14.1.3",
"next-axiom": "^1.1.1",
+ "posthog-js": "^1.116.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
diff --git a/frontend/src/app/PostHogPageView.tsx b/frontend/src/app/PostHogPageView.tsx
new file mode 100644
index 00000000..7c76c038
--- /dev/null
+++ b/frontend/src/app/PostHogPageView.tsx
@@ -0,0 +1,28 @@
+'use client'
+
+import { usePathname, useSearchParams } from "next/navigation";
+import { useEffect } from "react";
+import { usePostHog } from 'posthog-js/react';
+
+export default function PostHogPageView() : null {
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+ const posthog = usePostHog();
+
+ useEffect(() => {
+ if (pathname && posthog) {
+ let url = window.origin + pathname
+ if (searchParams.toString()) {
+ url = url + `?${searchParams.toString()}`
+ }
+ posthog.capture(
+ '$pageview',
+ {
+ '$current_url': url,
+ }
+ )
+ }
+ }, [pathname, searchParams, posthog])
+
+ return null
+}
\ No newline at end of file
diff --git a/frontend/src/app/_components/providers.tsx b/frontend/src/app/_components/providers.tsx
index 14a53cca..6065f7c8 100644
--- a/frontend/src/app/_components/providers.tsx
+++ b/frontend/src/app/_components/providers.tsx
@@ -3,6 +3,27 @@
import { Analytics } from "@vercel/analytics/react"
import { AxiomWebVitals } from "next-axiom"
import { Toaster } from "react-hot-toast"
+import posthog from "posthog-js"
+import { PostHogProvider } from 'posthog-js/react'
+
+const posthog_enabled = process.env.NEXT_PUBLIC_POSTHOG_KEY != null
+
+if (typeof window !== 'undefined' && posthog_enabled) {
+ posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY || '', {
+ api_host: process.env.NEXT_PUBLIC_POSTHOG_API_HOST || '',
+ ui_host: process.env.NEXT_PUBLIC_POSTHOG_UI_HOST || '',
+ capture_pageview: false,
+ })
+}
+
+export function PosthogProvider({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return