Skip to content

posthog migration: part 5 #7367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2025
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
233 changes: 233 additions & 0 deletions apps/dashboard/src/@/analytics/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { Team } from "../api/team";
* ### Why do we need to report this event?
* - To track the number of contracts deployed
* - To track the number of contracts deployed on each chain
* - To track if the contract was deployed on the asset page vs on the deploy page
*
* ### Who is responsible for this event?
* @jnsdls
Expand All @@ -20,6 +21,7 @@ export function reportContractDeployed(properties: {
chainId: number;
publisher: string | undefined;
contractName: string | undefined;
deploymentType?: "asset";
}) {
posthog.capture("contract deployed", properties);
}
Expand All @@ -39,6 +41,25 @@ export function reportContractDeployFailed(properties: {
posthog.capture("contract deploy failed", properties);
}

/**
* ### Why do we need to report this event?
* - To track the number of contracts published
* - To understand the type of contracts published
* - To understand who publishes contracts
*
* ### Who is responsible for this event?
* @jnsdls
*
*/
export function reportContractPublished(properties: {
publisher: string;
contractName: string;
version: string;
deployType: string | undefined;
}) {
posthog.capture("contract published", properties);
}

// ----------------------------
// ONBOARDING (TEAM)
// ----------------------------
Expand Down Expand Up @@ -148,3 +169,215 @@ export function reportOnboardingMembersUpsellPlanSelected(properties: {
export function reportOnboardingCompleted() {
posthog.capture("onboarding completed");
}

// ----------------------------
// FAUCET
// ----------------------------
/**
* ### Why do we need to report this event?
* - To track which chain the faucet was used on
* - To track how popular specific faucets are
*
* ### Who is responsible for this event?
* @jnsdls
*
*/
export function reportFaucetUsed(properties: {
chainId: number;
}) {
posthog.capture("faucet used", {
chainId: properties.chainId,
});
}

// ----------------------------
// CHAIN CONFIGURATION
// ----------------------------
/**
* ### Why do we need to report this event?
* - To track which custom chains customers are adding that we may want to add to the app
*
* ### Who is responsible for this event?
* @jnsdls
*
*/
export function reportChainConfigurationAdded(properties: {
chainId: number;
chainName: string;
rpcURLs: readonly string[];
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
}) {
posthog.capture("chain configuration added", {
chainId: properties.chainId,
chainName: properties.chainName,
rpcURLs: properties.rpcURLs,
nativeCurrency: properties.nativeCurrency,
});
}

// ----------------------------
// ASSETS
// ----------------------------

type AssetContractType = "DropERC20" | "DropERC1155" | "DropERC721";

/**
* ### Why do we need to report this event?
* - To track number of successful asset purchases from the asset page
* - To track which asset and contract types are being purchased the most
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetBuySuccessful(properties: {
chainId: number;
contractType: AssetContractType;
assetType: "nft" | "coin";
}) {
posthog.capture("asset buy successful", {
chainId: properties.chainId,
contractType: properties.contractType,
assetType: properties.assetType,
});
}

/**
* ### Why do we need to report this event?
* - To track number of failed asset purchases from the asset page
* - To track the errors that users encounter when trying to purchase an asset
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetBuyFailed(properties: {
chainId: number;
contractType: AssetContractType;
assetType: "nft" | "coin";
error: string;
}) {
posthog.capture("asset buy failed", {
chainId: properties.chainId,
contractType: properties.contractType,
assetType: properties.assetType,
error: properties.error,
});
}

// 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
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetImportSuccessful() {
posthog.capture("asset import successful");
}

/**
* ### Why do we need to report this event?
* - To track number of asset import started in the assets page
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetImportStarted() {
posthog.capture("asset import started");
}

/**
* ### Why do we need to report this event?
* - To track the steps users are configuring in the asset creation to understand if there are any drop-offs
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetCreationStepConfigured(
properties:
| {
assetType: "nft";
step: "collection-info" | "upload-assets" | "sales-settings";
}
| {
assetType: "coin";
step: "coin-info" | "token-distribution" | "launch-coin";
},
) {
posthog.capture("asset creation step configured", {
assetType: properties.assetType,
step: properties.step,
});
}

/**
* ### Why do we need to report this event?
* - To track number of successful asset creations
* - To track which asset types are being created the most
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetCreationSuccessful(properties: {
assetType: "nft" | "coin";
contractType: AssetContractType;
}) {
posthog.capture("asset creation successful", {
assetType: properties.assetType,
contractType: properties.contractType,
});
}

/**
* ### Why do we need to report this event?
* - To track number of failed asset creations
* - To track the errors that users encounter when trying to create an asset
* - To track the step that is failing in the asset creation
*
* ### Who is responsible for this event?
* @MananTank
*/
export function reportAssetCreationFailed(
properties: { contractType: AssetContractType; error: string } & (
| {
assetType: "nft";
step: "deploy-contract" | "mint-nfts" | "set-claim-conditions";
}
| {
assetType: "coin";
step:
| "deploy-contract"
| "set-claim-conditions"
| "mint-tokens"
| "airdrop-tokens";
}
),
) {
posthog.capture("asset creation failed", {
assetType: properties.assetType,
contractType: properties.contractType,
error: properties.error,
step: properties.step,
});
}
15 changes: 2 additions & 13 deletions apps/dashboard/src/@/components/blocks/pricing-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Button } from "@/components/ui/button";
import { ToolTipLabel } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
import { RenewSubscriptionButton } from "components/settings/Account/Billing/renew-subscription/renew-subscription-button";
import { useTrack } from "hooks/analytics/useTrack";
import { CheckIcon, DollarSignIcon } from "lucide-react";
import Link from "next/link";
import type React from "react";
Expand Down Expand Up @@ -58,7 +57,6 @@ export const PricingCard: React.FC<PricingCardProps> = ({
}) => {
const plan = TEAM_PLANS[billingPlan];

const trackEvent = useTrack();
const remainingTrialDays =
(activeTrialEndsAt ? remainingDays(activeTrialEndsAt) : 0) || 0;

Expand All @@ -68,15 +66,6 @@ export const PricingCard: React.FC<PricingCardProps> = ({
billingStatus === "noPayment" &&
billingPlan === "growth";

const handleCTAClick = () => {
cta?.onClick?.();
trackEvent({
category: "account",
label: `${billingPlan}Plan`,
action: "click",
});
};

return (
<div
className={cn(
Expand Down Expand Up @@ -163,7 +152,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
buttonProps={{
variant: highlighted ? "default" : "outline",
className: highlighted ? undefined : "bg-background",
onClick: handleCTAClick,
onClick: cta.onClick,
}}
teamSlug={teamSlug}
sku={billingPlanToSkuMap[billingPlan]}
Expand All @@ -181,7 +170,7 @@ export const PricingCard: React.FC<PricingCardProps> = ({
<Link
href={cta.href}
target="_blank"
onClick={handleCTAClick}
onClick={cta.onClick}
rel="noopener noreferrer"
>
{has7DayTrial ? "Start 7 Day Free Trial" : cta.label}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import { reportFaucetUsed } from "@/analytics/report";
import { CopyTextButton } from "@/components/ui/CopyTextButton";
import { Spinner } from "@/components/ui/Spinner/Spinner";
import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -29,7 +30,6 @@ import { Turnstile } from "@marsidev/react-turnstile";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import type { CanClaimResponseType } from "app/(app)/api/testnet-faucet/can-claim/CanClaimResponseType";
import { mapV4ChainToV5Chain } from "contexts/map-chains";
import { useTrack } from "hooks/analytics/useTrack";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useForm } from "react-hook-form";
Expand Down Expand Up @@ -95,17 +95,11 @@ export function FaucetButton({
chain: definedChain,
client,
});
const trackEvent = useTrack();

const queryClient = useQueryClient();

const claimMutation = useMutation({
mutationFn: async (turnstileToken: string) => {
trackEvent({
category: "faucet",
action: "claim",
label: "attempt",
chain_id: chainId,
});
const response = await fetch("/api/testnet-faucet/claim", {
method: "POST",
headers: {
Expand All @@ -124,20 +118,8 @@ export function FaucetButton({
}
},
onSuccess: () => {
trackEvent({
category: "faucet",
action: "claim",
label: "success",
chain_id: chainId,
});
},
onError: (error) => {
trackEvent({
category: "faucet",
action: "claim",
label: "error",
chain_id: chainId,
errorMsg: error instanceof Error ? error.message : "Unknown error",
reportFaucetUsed({
chainId,
});
},
onSettled: () => {
Expand Down Expand Up @@ -223,8 +205,9 @@ export function FaucetButton({
{canClaimFaucetQuery.data.type === "unsupported-chain" &&
"Faucet is empty right now"}

{/* TODO: add an upsell path here to subscribe to one of these plans */}
{canClaimFaucetQuery.data.type === "paid-plan-required" &&
"Faucet is only available on Starter, Growth and Pro plans."}
"Faucet is only available on Starter, Growth, Scale and Pro plans."}
</Button>
);
}
Expand Down
Loading
Loading