feat: dashboard: add additional segment events (#3313)

### **PR Type**
Enhancement


___

### **Description**
- Added Segment analytics tracking for key actions

- Implemented event tracking for project upgrades

- Added tracking for organization invites

- Included analytics for GitHub project connections

- Implemented tracking for new project creation


___



### **Changes walkthrough** 📝
<table><thead><tr><th></th><th align="left">Relevant
files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>UpgradeProjectDialogContent.tsx</strong><dd><code>Add
Segment tracking for project upgrades</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/components/common/TransferOrUpgradeProjectDialog/UpgradeProjectDialogContent.tsx

<li>Imported useCurrentOrg and analytics<br> <li> Added Segment tracking
for 'Project Upgraded' event<br> <li> Included detailed project and
organization data in the event


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3313/files#diff-ced98d2b8b0e83e41fd9bd569a6dd3fb5c4013861d3352628e63abe0c285d2ba">+20/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>PendingInvites.tsx</strong><dd><code>Implement Segment
tracking for organization invites</code>&nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/components/members/components/PendingInvites/PendingInvites.tsx

<li>Imported analytics from Segment<br> <li> Added tracking for
'Organization Invite Sent' event<br> <li> Included organization and
invitee details in the event


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3313/files#diff-dec81af68d9403085c09185e0153335ddf7d629f64f626cae394108bcb42d685">+11/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>EditRepositorySettingsModal.tsx</strong><dd><code>Add
Segment tracking for GitHub project connections</code>&nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>


dashboard/src/features/orgs/projects/git/common/components/EditRepositorySettingsModal/EditRepositorySettingsModal.tsx

<li>Imported analytics from Segment<br> <li> Added tracking for 'Project
Connected to GitHub' event<br> <li> Included project and repository
details in the event


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3313/files#diff-eb88f4f79aa0286c7f1d06ff73908f34009e7e9e8b982f54866f157fd81c5c3a">+12/-0</a>&nbsp;
&nbsp; </td>

</tr>

<tr>
  <td>
    <details>
<summary><strong>new.tsx</strong><dd><code>Implement Segment tracking
for new project creation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

dashboard/src/pages/orgs/[orgSlug]/projects/new.tsx

<li>Imported analytics from Segment<br> <li> Added tracking for 'Project
Created' event<br> <li> Included project, organization, and region
details in the event


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3313/files#diff-ef97470126e3edc146dda51337aaec556387e2f8a37afa70810d1dc94958f4fd">+10/-0</a>&nbsp;
&nbsp; </td>

</tr>
</table></td></tr><tr><td><strong>Documentation</strong></td><td><table>
<tr>
  <td>
    <details>
<summary><strong>hungry-terms-retire.md</strong><dd><code>Add changeset
for Segment analytics feature</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
</dd></summary>
<hr>

.changeset/hungry-terms-retire.md

<li>Added changeset file for minor version bump<br> <li> Described
feature addition of Segment events


</details>


  </td>
<td><a
href="https://github.com/nhost/nhost/pull/3313/files#diff-3accee3677ac6171593ed474c4c867ce1d27b490b69c9fd738f1cff121791ba9">+5/-0</a>&nbsp;
&nbsp; &nbsp; </td>

</tr>
</table></td></tr></tr></tbody></table>

___

> <details> <summary> Need help?</summary><li>Type <code>/help how to
...</code> in the comments thread for any questions about PR-Agent
usage.</li><li>Check out the <a
href="https://qodo-merge-docs.qodo.ai/usage-guide/">documentation</a>
for more information.</li></details>
This commit is contained in:
Nuno Pato
2025-04-28 11:14:51 +00:00
committed by GitHub
parent fad7f640de
commit 85526782f2
6 changed files with 75 additions and 3 deletions

View File

@@ -0,0 +1,5 @@
---
'@nhost/dashboard': minor
---
feat: dashboard: add additional events to segment

View File

@@ -9,6 +9,7 @@ import { type FinishOrgCreationOnCompletedCb } from '@/features/orgs/hooks/useFi
import { useOrgs } from '@/features/orgs/projects/hooks/useOrgs';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import { analytics } from '@/lib/segment';
import { isEmptyValue } from '@/lib/utils';
import { useBillingTransferAppMutation } from '@/utils/__generated__/graphql';
import { useRouter } from 'next/router';
@@ -44,6 +45,18 @@ function UpgradeProjectDialogContent({
organizationID: newOrg?.id,
},
});
analytics.track('Project Upgraded', {
projectId: project?.id,
projectName: project?.name,
projectSubdomain: project?.subdomain,
newOrganizationId: newOrg?.id,
newOrganizationName: newOrg?.name,
newOrganizationSlug: newOrg?.slug,
newOrganizationPlan: newOrg?.plan?.name,
newOrganizationPlanId: newOrg?.plan?.id,
});
await push(`/orgs/${newOrg?.slug}/projects`);
},
{

View File

@@ -31,6 +31,7 @@ import { OrgInvite } from '@/features/orgs/components/members/components/OrgInvi
import { useIsOrgAdmin } from '@/features/orgs/hooks/useIsOrgAdmin';
import { useCurrentOrg } from '@/features/orgs/projects/hooks/useCurrentOrg';
import execPromiseWithErrorToast from '@/features/orgs/utils/execPromiseWithErrorToast/execPromiseWithErrorToast';
import { analytics } from '@/lib/segment';
import {
Organization_Members_Role_Enum,
useGetOrganizationInvitesQuery,
@@ -91,6 +92,16 @@ export default function PendingInvites() {
},
});
analytics.track('Organization Invite Sent', {
organizationId: org?.id,
organizationName: org?.name,
organizationSlug: org?.slug,
organizationPlan: org?.plan?.name,
organizationPlanId: org?.plan?.id,
inviteeEmail: email,
inviteeRole: role,
});
setInviteDialogOpen(false);
setOrgInviteError(null);
form.reset();

View File

@@ -7,6 +7,7 @@ import { EditRepositoryAndBranchSettings } from '@/features/orgs/projects/git/co
import type { EditRepositorySettingsFormData } from '@/features/orgs/projects/git/common/components/EditRepositorySettings';
import { useProject } from '@/features/orgs/projects/hooks/useProject';
import { useUpdateApplicationMutation } from '@/generated/graphql';
import { analytics } from '@/lib/segment';
import { discordAnnounce } from '@/utils/discordAnnounce';
import { triggerToast } from '@/utils/toast';
import { useFormContext } from 'react-hook-form';
@@ -49,6 +50,17 @@ export default function EditRepositorySettingsModal({
},
},
});
if (selectedRepoId) {
analytics.track('Project Connected to GitHub', {
projectId: project.id,
projectName: project.name,
projectSubdomain: project.subdomain,
repositoryId: selectedRepoId,
productionBranch: data.productionBranch,
baseFolder: data.repoBaseFolder,
});
}
} else {
await updateApp({
variables: {

View File

@@ -12,6 +12,7 @@ import { ProjectLayout } from '@/features/orgs/layout/ProjectLayout';
import { useOrgs } from '@/features/orgs/projects/hooks/useOrgs';
import { execPromiseWithErrorToast } from '@/features/orgs/utils/execPromiseWithErrorToast';
import { useSubmitState } from '@/hooks/useSubmitState';
import { analytics } from '@/lib/segment';
import {
useInsertOrgApplicationMutation,
usePrefetchNewAppQuery,
@@ -113,6 +114,15 @@ export function NewProjectPageContent({
});
if (subdomain) {
analytics.track('Project Created', {
projectName: name,
projectSlug: slug,
organizationId: selectedOrg.id,
organizationName: selectedOrg.name,
regionId: selectedRegion.id,
regionName: selectedRegion.name,
});
await router.push(`/orgs/${selectedOrg.slug}/projects/${subdomain}`);
}
},

View File

@@ -4,8 +4,10 @@ import { BaseLayout } from '@/components/layout/BaseLayout';
import { Header } from '@/components/layout/Header';
import { FinishOrgCreationProcess } from '@/features/orgs/components/common/FinishOrgCreationProcess';
import { useIsPlatform } from '@/features/orgs/projects/common/hooks/useIsPlatform';
import { analytics } from '@/lib/segment';
import type { PostOrganizationRequestMutation } from '@/utils/__generated__/graphql';
import { useAuthenticationStatus } from '@nhost/nextjs';
import { useGetOrganizationLazyQuery } from '@/utils/__generated__/graphql';
import { useAuthenticationStatus, useUserData } from '@nhost/nextjs';
import { useRouter } from 'next/router';
import { useCallback, useEffect } from 'react';
@@ -13,6 +15,8 @@ export default function PostCheckout() {
const router = useRouter();
const isPlatform = useIsPlatform();
const { isAuthenticated, isLoading } = useAuthenticationStatus();
const currentUser = useUserData();
const [getOrganizations] = useGetOrganizationLazyQuery();
useEffect(() => {
if (!isPlatform || isLoading || isAuthenticated) {
@@ -23,13 +27,30 @@ export default function PostCheckout() {
}, [isLoading, isAuthenticated, router, isPlatform]);
const onCompleted = useCallback(
(
async (
data: PostOrganizationRequestMutation['billingPostOrganizationRequest'],
) => {
const { Slug } = data;
const { data: orgData } = await getOrganizations({
variables: {
orgSlug: Slug,
},
});
const { id, name, slug, plan } = orgData.organizations[0];
analytics.track('Organization Created', {
organizationId: id,
organizationSlug: slug,
organizationName: name,
organizationPlan: plan?.name,
organizationOwnerId: currentUser?.id,
organizationOwnerEmail: currentUser?.email,
});
router.push(`/orgs/${Slug}/projects`);
},
[router],
[router, currentUser?.email, currentUser?.id, getOrganizations],
);
return (