diff --git a/apps/web/src/app/(dashboard)/documents/upload-document.tsx b/apps/web/src/app/(dashboard)/documents/upload-document.tsx index 9963d072a..5e93495e3 100644 --- a/apps/web/src/app/(dashboard)/documents/upload-document.tsx +++ b/apps/web/src/app/(dashboard)/documents/upload-document.tsx @@ -9,6 +9,7 @@ import { Loader } from 'lucide-react'; import { useSession } from 'next-auth/react'; import { useLimits } from '@documenso/ee/server-only/limits/provider/client'; +import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data'; import { putFile } from '@documenso/lib/universal/upload/put-file'; import { TRPCClientError } from '@documenso/trpc/client'; @@ -23,6 +24,7 @@ export type UploadDocumentProps = { export const UploadDocument = ({ className }: UploadDocumentProps) => { const router = useRouter(); + const analytics = useAnalytics(); const { data: session } = useSession(); const { toast } = useToast(); @@ -55,6 +57,12 @@ export const UploadDocument = ({ className }: UploadDocumentProps) => { duration: 5000, }); + analytics.capture('App: Document Uploaded', { + userId: session?.user.id, + documentId: id, + timestamp: new Date().toISOString(), + }); + router.push(`/documents/${id}`); } catch (error) { console.error(error); diff --git a/apps/web/src/app/(signing)/sign/[token]/form.tsx b/apps/web/src/app/(signing)/sign/[token]/form.tsx index 6589572a3..29cd77995 100644 --- a/apps/web/src/app/(signing)/sign/[token]/form.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/form.tsx @@ -7,6 +7,7 @@ import { useRouter } from 'next/navigation'; import { useSession } from 'next-auth/react'; import { useForm } from 'react-hook-form'; +import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { sortFieldsByPosition, validateFieldsInserted } from '@documenso/lib/utils/fields'; import type { Document, Field, Recipient } from '@documenso/prisma/client'; import { trpc } from '@documenso/trpc/react'; @@ -29,6 +30,7 @@ export type SigningFormProps = { export const SigningForm = ({ document, recipient, fields }: SigningFormProps) => { const router = useRouter(); + const analytics = useAnalytics(); const { data: session } = useSession(); const { fullName, signature, setFullName, setSignature } = useRequiredSigningContext(); @@ -60,6 +62,12 @@ export const SigningForm = ({ document, recipient, fields }: SigningFormProps) = documentId: document.id, }); + analytics.capture('App: Recipient has completed signing', { + signerId: recipient.id, + documentId: document.id, + timestamp: new Date().toISOString(), + }); + router.push(`/sign/${recipient.token}/complete`); }; diff --git a/apps/web/src/components/forms/signup.tsx b/apps/web/src/components/forms/signup.tsx index 11068ac68..862f4f83e 100644 --- a/apps/web/src/components/forms/signup.tsx +++ b/apps/web/src/components/forms/signup.tsx @@ -8,6 +8,7 @@ import { signIn } from 'next-auth/react'; import { Controller, useForm } from 'react-hook-form'; import { z } from 'zod'; +import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { TRPCClientError } from '@documenso/trpc/client'; import { trpc } from '@documenso/trpc/react'; import { cn } from '@documenso/ui/lib/utils'; @@ -36,6 +37,7 @@ export type SignUpFormProps = { export const SignUpForm = ({ className }: SignUpFormProps) => { const { toast } = useToast(); + const analytics = useAnalytics(); const [showPassword, setShowPassword] = useState(false); const { @@ -64,6 +66,11 @@ export const SignUpForm = ({ className }: SignUpFormProps) => { password, callbackUrl: '/', }); + + analytics.capture('App: User Sign Up', { + email, + timestamp: new Date().toISOString(), + }); } catch (err) { if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') { toast({ diff --git a/packages/ee/server-only/stripe/webhook/on-early-adopters-checkout.ts b/packages/ee/server-only/stripe/webhook/on-early-adopters-checkout.ts index a8403e05a..22f60069e 100644 --- a/packages/ee/server-only/stripe/webhook/on-early-adopters-checkout.ts +++ b/packages/ee/server-only/stripe/webhook/on-early-adopters-checkout.ts @@ -1,4 +1,4 @@ -import Stripe from 'stripe'; +import type Stripe from 'stripe'; import { hashSync } from '@documenso/lib/server-only/auth/hash'; import { sealDocument } from '@documenso/lib/server-only/document/seal-document'; diff --git a/packages/lib/server-only/document/seal-document.ts b/packages/lib/server-only/document/seal-document.ts index 318d540b8..5fa4b1a00 100644 --- a/packages/lib/server-only/document/seal-document.ts +++ b/packages/lib/server-only/document/seal-document.ts @@ -1,8 +1,10 @@ 'use server'; +import { nanoid } from 'nanoid'; import path from 'node:path'; import { PDFDocument } from 'pdf-lib'; +import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-post-hog-server-client'; import { prisma } from '@documenso/prisma'; import { DocumentStatus, SigningStatus } from '@documenso/prisma/client'; import { signPdf } from '@documenso/signing'; @@ -83,6 +85,18 @@ export const sealDocument = async ({ documentId, sendEmail = true }: SealDocumen arrayBuffer: async () => Promise.resolve(pdfBuffer), }); + const postHog = PostHogServerClient(); + + if (postHog) { + postHog.capture({ + distinctId: nanoid(), + event: 'App: Document Sealed', + properties: { + documentId: document.id, + }, + }); + } + await prisma.documentData.update({ where: { id: documentData.id, diff --git a/packages/lib/universal/get-feature-flag.ts b/packages/lib/universal/get-feature-flag.ts index 38707d41b..0fc0aa131 100644 --- a/packages/lib/universal/get-feature-flag.ts +++ b/packages/lib/universal/get-feature-flag.ts @@ -1,9 +1,7 @@ import { z } from 'zod'; -import { - TFeatureFlagValue, - ZFeatureFlagValueSchema, -} from '@documenso/lib/client-only/providers/feature-flag.types'; +import type { TFeatureFlagValue } from '@documenso/lib/client-only/providers/feature-flag.types'; +import { ZFeatureFlagValueSchema } from '@documenso/lib/client-only/providers/feature-flag.types'; import { APP_BASE_URL } from '@documenso/lib/constants/app'; import { LOCAL_FEATURE_FLAGS, isFeatureFlagEnabled } from '@documenso/lib/constants/feature-flags';