diff --git a/apps/dashboard/src/@/analytics/report.ts b/apps/dashboard/src/@/analytics/report.ts index dcc55ad4fb1..1f3352e90ea 100644 --- a/apps/dashboard/src/@/analytics/report.ts +++ b/apps/dashboard/src/@/analytics/report.ts @@ -1,3 +1,4 @@ +"use client"; import posthog from "posthog-js"; import type { Team } from "@/api/team"; @@ -269,22 +270,6 @@ export function reportAssetBuyFailed(properties: { // Assets Landing Page ---------------------------- -/** - * ### Why do we need to report this event? - * - To track number of asset creation started from the assets page - * - To track which asset types are being created the most - * - * ### Who is responsible for this event? - * @MananTank - */ -export function reportAssetCreationStarted(properties: { - assetType: "nft" | "coin"; -}) { - posthog.capture("asset creation started", { - assetType: properties.assetType, - }); -} - /** * ### Why do we need to report this event? * - To track number of assets imported successfully from the assets page @@ -431,28 +416,59 @@ export function reportPaymentCardClick(properties: { id: string }) { /** * ### Why do we need to report this event? - * - To track payment link usage + * - To create a funnel "create payment link pageview" -> "payment link created" to understand the conversion rate + * + * ### Who is responsible for this event? + * @greg + */ +export function reportPaymentLinkCreated(properties: { + linkId: string; + clientId: string; +}) { + posthog.capture("payment link created", properties); +} + +/** + * ### Why do we need to report this event? + * - To track funnel "payment link pageview" -> "payment link buy successful" to understand the conversion rate * * ### Who is responsible for this event? * @greg */ -export function reportPaymentLinkVisited(properties: { +export function reportPaymentLinkBuySuccessful(properties: { linkId: string; clientId: string; }) { - posthog.capture("payment link visited", properties); + posthog.capture("payment link buy successful", properties); } /** * ### Why do we need to report this event? - * - To track payment link usage + * - To track the number of failed payment link buys + * - To track what errors users encounter when trying to buy from a payment link * * ### Who is responsible for this event? * @greg */ -export function reportPaymentLinkCompleted(properties: { +export function reportPaymentLinkBuyFailed(properties: { linkId: string; clientId: string; + errorMessage: string; +}) { + posthog.capture("payment link buy failed", properties); +} + +/** + * ### Why do we need to report this event? + * - To create a funnel for "asset pageview" -> "asset purchase successful" to understand the conversion rate + * - To understand which asset types are being viewed the most + * + * ### Who is responsible for this event? + * @MananTank + */ +export function reportAssetPageview(properties: { + assetType: "nft" | "coin"; + chainId: number; }) { - posthog.capture("payment link completed", properties); + posthog.capture("asset pageview", properties); } diff --git a/apps/dashboard/src/@/api/universal-bridge/developer.ts b/apps/dashboard/src/@/api/universal-bridge/developer.ts index 05a4c9709be..f5987f3ef8e 100644 --- a/apps/dashboard/src/@/api/universal-bridge/developer.ts +++ b/apps/dashboard/src/@/api/universal-bridge/developer.ts @@ -200,7 +200,11 @@ export async function createPaymentLink(props: { throw new Error(text); } - return; + const response = (await res.json()) as { + data: PaymentLink; + }; + + return response.data; } export async function deletePaymentLink(props: { diff --git a/apps/dashboard/src/@/hooks/useEffectOnce.ts b/apps/dashboard/src/@/hooks/useEffectOnce.ts new file mode 100644 index 00000000000..6e7d37629b4 --- /dev/null +++ b/apps/dashboard/src/@/hooks/useEffectOnce.ts @@ -0,0 +1,14 @@ +/** biome-ignore-all lint/correctness/useExhaustiveDependencies: we only want to run effect once */ +"use client"; +import { useEffect, useRef } from "react"; + +export function useEffectOnce(effect: () => void) { + const hasCalledEffect = useRef(false); + + // eslint-disable-next-line no-restricted-syntax + useEffect(() => { + if (hasCalledEffect.current) return; + hasCalledEffect.current = true; + effect(); + }, []); +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/_components/asset-page-view.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/_components/asset-page-view.tsx new file mode 100644 index 00000000000..f08dfcf594e --- /dev/null +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/_components/asset-page-view.tsx @@ -0,0 +1,17 @@ +"use client"; +import { reportAssetPageview } from "@/analytics/report"; +import { useEffectOnce } from "@/hooks/useEffectOnce"; + +export function AssetPageView(props: { + assetType: "nft" | "coin"; + chainId: number; +}) { + useEffectOnce(() => { + reportAssetPageview({ + assetType: props.assetType, + chainId: props.chainId, + }); + }); + + return null; +} diff --git a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/erc20.tsx b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/erc20.tsx index e7534a4dd56..2fbd519762e 100644 --- a/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/erc20.tsx +++ b/apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/erc20.tsx @@ -4,6 +4,7 @@ import { getContractMetadata } from "thirdweb/extensions/common"; import { decimals, getActiveClaimCondition } from "thirdweb/extensions/erc20"; import { GridPattern } from "@/components/ui/background-patterns"; import { resolveFunctionSelectors } from "@/lib/selectors"; +import { AssetPageView } from "../_components/asset-page-view"; import { getContractCreator } from "../_components/getContractCreator"; import { PageHeader } from "../_components/PageHeader"; import { getTokenPriceData } from "./_apis/token-price-data"; @@ -85,6 +86,7 @@ export async function ERC20PublicPage(props: { return (