chore: add onboarding events in posthog (#25981)

* add onboarding events in posthog

* Update apps/web/modules/onboarding/organization/teams/organization-teams-view.tsx

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
sean-brydon
2025-12-17 22:43:54 +00:00
committed by GitHub
co-authored by cubic-dev-ai[bot]
parent e84550ba76
commit 64767cec4f
7 changed files with 77 additions and 9 deletions
@@ -2,6 +2,7 @@
import { AnimatePresence } from "framer-motion";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useEffect, useRef, useTransition } from "react";
import { useTeamInvites } from "@calcom/features/billing/hooks/useHasPaidPlan";
@@ -69,6 +70,11 @@ export const OnboardingView = ({ userEmail }: OnboardingViewProps) => {
}, [selectedPlan]);
const handleContinue = () => {
if (selectedPlan) {
posthog.capture("onboarding_plan_continue_clicked", {
plan_type: selectedPlan,
});
}
startTransition(() => {
if (selectedPlan === "organization") {
router.push("/onboarding/organization/details");
@@ -157,7 +163,13 @@ export const OnboardingView = ({ userEmail }: OnboardingViewProps) => {
{/* Plan options */}
<RadioAreaGroup.Group
value={selectedPlan ?? undefined}
onValueChange={(value) => setSelectedPlan(value as PlanType)}
onValueChange={(value) => {
const planType = value as PlanType;
setSelectedPlan(planType);
posthog.capture("onboarding_plan_selected", {
plan_type: planType,
});
}}
className="flex w-full flex-col gap-1 rounded-[10px]">
{plans.map((plan) => {
const isSelected = selectedPlan === plan.id;
@@ -1,6 +1,7 @@
"use client";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useEffect, useRef, useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -72,6 +73,11 @@ export const OrganizationBrandView = ({ userEmail }: OrganizationBrandViewProps)
};
const handleContinue = () => {
posthog.capture("onboarding_organization_brand_continue_clicked", {
has_logo: !!logoPreview,
has_banner: !!bannerPreview,
has_custom_color: brandColor !== "#000000",
});
// Save to store (already saved on change, but ensure it's persisted)
setOrganizationBrand({
logo: logoPreview,
@@ -82,6 +88,7 @@ export const OrganizationBrandView = ({ userEmail }: OrganizationBrandViewProps)
};
const handleSkip = () => {
posthog.capture("onboarding_organization_brand_skip_clicked");
// Skip brand customization and go to teams
router.push("/onboarding/organization/teams");
};
@@ -97,7 +104,10 @@ export const OrganizationBrandView = ({ userEmail }: OrganizationBrandViewProps)
<Button
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/organization/details")}>
onClick={() => {
posthog.capture("onboarding_organization_brand_back_clicked");
router.push("/onboarding/organization/details");
}}>
{t("back")}
</Button>
<div className="flex items-center gap-2">
@@ -1,6 +1,7 @@
"use client";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useEffect, useState } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -67,6 +68,10 @@ export const OrganizationDetailsView = ({ userEmail }: OrganizationDetailsViewPr
return;
}
posthog.capture("onboarding_organization_details_continue_clicked", {
has_bio: !!organizationBio,
});
// Save to store
setOrganizationDetails({
name: organizationName,
@@ -87,7 +92,10 @@ export const OrganizationDetailsView = ({ userEmail }: OrganizationDetailsViewPr
<Button
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/getting-started")}>
onClick={() => {
posthog.capture("onboarding_organization_details_back_clicked");
router.push("/onboarding/getting-started");
}}>
{t("back")}
</Button>
<Button
@@ -1,6 +1,7 @@
"use client";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import React from "react";
import { useFlags } from "@calcom/features/flags/hooks";
@@ -48,6 +49,7 @@ export const OrganizationInviteView = ({ userEmail }: OrganizationInviteViewProp
};
const handleSkip = async () => {
posthog.capture("onboarding_organization_invite_skip_clicked");
setInvites([]);
await submitOnboarding(store, userEmail, []);
};
@@ -67,7 +69,10 @@ export const OrganizationInviteView = ({ userEmail }: OrganizationInviteViewProp
<Button
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/organization/teams")}
onClick={() => {
posthog.capture("onboarding_organization_invite_back_clicked");
router.push("/onboarding/organization/teams");
}}
disabled={isSubmitting}>
{t("back")}
</Button>
@@ -2,6 +2,7 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useForm, useFieldArray } from "react-hook-form";
import { z } from "zod";
@@ -49,12 +50,17 @@ export const OrganizationTeamsView = ({ userEmail }: OrganizationTeamsViewProps)
});
const handleContinue = (data: FormValues) => {
const validTeams = data.teams.filter((team) => team.name.trim().length > 0);
posthog.capture("onboarding_organization_teams_continue_clicked", {
team_count: validTeams.length,
});
// Save teams to store
setTeams(data.teams);
router.push("/onboarding/organization/invite/email");
};
const handleSkip = () => {
posthog.capture("onboarding_organization_teams_skip_clicked");
// Skip teams and go to invite
router.push("/onboarding/organization/invite/email");
};
@@ -76,7 +82,10 @@ export const OrganizationTeamsView = ({ userEmail }: OrganizationTeamsViewProps)
type="button"
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/organization/brand")}>
onClick={() => {
posthog.capture("onboarding_organization_teams_back_clicked");
router.push("/onboarding/organization/brand");
}}>
{t("back")}
</Button>
<div className="flex items-center gap-2">
@@ -121,7 +130,12 @@ export const OrganizationTeamsView = ({ userEmail }: OrganizationTeamsViewProps)
size="sm"
className="h-7 w-7"
disabled={fields.length === 1}
onClick={() => remove(index)}>
onClick={() => {
posthog.capture("onboarding_organization_teams_remove_clicked", {
team_count: fields.length,
});
remove(index);
}}>
<Icon name="x" className="h-4 w-4" />
</Button>
</div>
@@ -135,7 +149,12 @@ export const OrganizationTeamsView = ({ userEmail }: OrganizationTeamsViewProps)
size="sm"
StartIcon="plus"
className="w-fit"
onClick={() => append({ name: "" })}>
onClick={() => {
posthog.capture("onboarding_organization_teams_add_clicked", {
team_count: fields.length,
});
append({ name: "" });
}}>
{t("add")}
</Button>
</div>
@@ -1,6 +1,7 @@
"use client";
import { useRouter } from "next/navigation";
import posthog from "posthog-js";
import { useEffect, useRef, useState, type FormEvent } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
@@ -72,6 +73,11 @@ export const TeamDetailsView = ({ userEmail }: TeamDetailsViewProps) => {
return;
}
posthog.capture("onboarding_team_details_continue_clicked", {
has_logo: !!teamLogo,
has_bio: !!teamBio,
});
setTeamDetails({
name: teamName,
slug: teamSlug,
@@ -102,7 +108,10 @@ export const TeamDetailsView = ({ userEmail }: TeamDetailsViewProps) => {
type="button"
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/getting-started")}>
onClick={() => {
posthog.capture("onboarding_team_details_back_clicked");
router.push("/onboarding/getting-started");
}}>
{t("back")}
</Button>
<Button
@@ -1,6 +1,7 @@
"use client";
import { useRouter, useSearchParams } from "next/navigation";
import posthog from "posthog-js";
import React, { useEffect } from "react";
import { useFlags } from "@calcom/features/flags/hooks";
@@ -62,6 +63,7 @@ export const TeamInviteView = ({ userEmail }: TeamInviteViewProps) => {
};
const handleSkip = async () => {
posthog.capture("onboarding_team_invite_skip_clicked");
setTeamInvites([]);
// Create the team without invites (will handle checkout redirect if needed)
await createTeam(store);
@@ -80,7 +82,10 @@ export const TeamInviteView = ({ userEmail }: TeamInviteViewProps) => {
<Button
color="minimal"
className="rounded-[10px]"
onClick={() => router.push("/onboarding/teams/details")}
onClick={() => {
posthog.capture("onboarding_team_invite_back_clicked");
router.push("/onboarding/teams/details");
}}
disabled={isSubmitting}>
{t("back")}
</Button>