From f3b3b89fca7c6c84600b2e65c3a3906a93365211 Mon Sep 17 00:00:00 2001 From: MananTank Date: Thu, 18 Sep 2025 21:03:00 +0000 Subject: [PATCH] Dashboard: Add tracking for SwapWidget impression, chain pageview (#8071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR introduces analytics tracking for chain page views and enhances the reporting for swap widgets in the dashboard application. ### Detailed summary - Added `ChainPageView` component to track impressions of chain pages. - Integrated `reportChainPageview` function in the analytics module. - Enhanced `BuyAndSwapEmbed` to report when the swap widget is shown. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit - Chores - Added one-time telemetry when the Swap widget is displayed to improve usage insights. - Tracks the page context (asset, bridge, or chain) when the widget first appears. - Added one-time telemetry to record chain pageviews (captures the chain identifier) when visiting chain pages. - Integrated with existing UI; no impact on behavior, user action, or performance. --- apps/dashboard/src/@/analytics/report.ts | 25 +++++++++++++++++++ .../@/components/blocks/BuyAndSwapEmbed.tsx | 16 +++++++++++- .../components/client/chain-pageview.tsx | 13 ++++++++++ .../(chain)/[chain_id]/(chainPage)/layout.tsx | 2 ++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/chain-pageview.tsx diff --git a/apps/dashboard/src/@/analytics/report.ts b/apps/dashboard/src/@/analytics/report.ts index 1292edaa834..bbea78f2ab8 100644 --- a/apps/dashboard/src/@/analytics/report.ts +++ b/apps/dashboard/src/@/analytics/report.ts @@ -255,6 +255,20 @@ export function reportTokenSwapSuccessful(properties: TokenSwapParams) { posthog.capture("token swap successful", properties); } +/** + * ### Why do we need to report this event? + * - To track impressions of the swap widget + * - To create a funnel "swap widget shown" -> "swap widget successful" to understand the conversion rate + * + * ### Who is responsible for this event? + * @MananTank + */ +export function reportSwapWidgetShown(properties: { + pageType: "asset" | "bridge" | "chain"; +}) { + posthog.capture("swap widget shown", properties); +} + /** * ### Why do we need to report this event? * - To track number of failed token swaps from the token page @@ -530,6 +544,17 @@ export function reportAssetPageview(properties: { posthog.capture("asset pageview", properties); } +/** + * ### Why do we need to report this event? + * - To understand which chains are being viewed the most + * + * ### Who is responsible for this event? + * @MananTank + */ +export function reportChainPageview(properties: { chainId: number }) { + posthog.capture("chain pageview", properties); +} + /** * ### Why do we need to report this event? * - To track the usage of fund wallet modal diff --git a/apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx b/apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx index 498867f9bff..73ccf6ae774 100644 --- a/apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx +++ b/apps/dashboard/src/@/components/blocks/BuyAndSwapEmbed.tsx @@ -1,13 +1,14 @@ "use client"; import { useTheme } from "next-themes"; -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import type { Chain, ThirdwebClient } from "thirdweb"; import { BuyWidget, SwapWidget } from "thirdweb/react"; import { reportAssetBuyCancelled, reportAssetBuyFailed, reportAssetBuySuccessful, + reportSwapWidgetShown, reportTokenSwapCancelled, reportTokenSwapFailed, reportTokenSwapSuccessful, @@ -27,6 +28,19 @@ export function BuyAndSwapEmbed(props: { const { theme } = useTheme(); const [tab, setTab] = useState<"buy" | "swap">("swap"); const themeObj = getSDKTheme(theme === "light" ? "light" : "dark"); + const isMounted = useRef(false); + + // eslint-disable-next-line no-restricted-syntax + useEffect(() => { + if (isMounted.current) { + return; + } + isMounted.current = true; + reportSwapWidgetShown({ + pageType: props.pageType, + }); + }, [props.pageType]); + return (
diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/chain-pageview.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/chain-pageview.tsx new file mode 100644 index 00000000000..3e6c9345acc --- /dev/null +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/chain-pageview.tsx @@ -0,0 +1,13 @@ +"use client"; +import { reportChainPageview } from "@/analytics/report"; +import { useEffectOnce } from "@/hooks/useEffectOnce"; + +export function ChainPageView(props: { chainId: number }) { + useEffectOnce(() => { + reportChainPageview({ + chainId: props.chainId, + }); + }); + + return null; +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx index 43bfbc89c91..475a4a99c86 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/layout.tsx @@ -24,6 +24,7 @@ import { TeamHeader } from "../../../../team/components/TeamHeader/team-header"; import { StarButton } from "../../components/client/star-button"; import { getChain, getChainMetadata } from "../../utils"; import { AddChainToWallet } from "./components/client/add-chain-to-wallet"; +import { ChainPageView } from "./components/client/chain-pageview"; import { ChainHeader } from "./components/server/chain-header"; // TODO: improve the behavior when clicking "Get started with thirdweb", currently just redirects to the dashboard @@ -71,6 +72,7 @@ export default async function ChainPageLayout(props: { return (
+