diff --git a/apps/web/src/app/(dashboard)/documents/page.tsx b/apps/web/src/app/(dashboard)/documents/page.tsx
index f38668fd9..cd7f868ad 100644
--- a/apps/web/src/app/(dashboard)/documents/page.tsx
+++ b/apps/web/src/app/(dashboard)/documents/page.tsx
@@ -63,7 +63,7 @@ export default async function DocumentsPage({ searchParams = {} }: DocumentsPage
return (
-
+
Documents
diff --git a/apps/web/src/app/(dashboard)/documents/upload-document.tsx b/apps/web/src/app/(dashboard)/documents/upload-document.tsx
index 644c9017a..eec881e67 100644
--- a/apps/web/src/app/(dashboard)/documents/upload-document.tsx
+++ b/apps/web/src/app/(dashboard)/documents/upload-document.tsx
@@ -8,6 +8,7 @@ import { useRouter } from 'next/navigation';
import { Loader } from 'lucide-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';
@@ -18,10 +19,12 @@ import { useToast } from '@documenso/ui/primitives/use-toast';
export type UploadDocumentProps = {
className?: string;
+ userId?: number;
};
-export const UploadDocument = ({ className }: UploadDocumentProps) => {
+export const UploadDocument = ({ className, userId }: UploadDocumentProps) => {
const router = useRouter();
+ const analytics = useAnalytics();
const { toast } = useToast();
@@ -53,6 +56,12 @@ export const UploadDocument = ({ className }: UploadDocumentProps) => {
duration: 5000,
});
+ analytics.capture('App: Document Uploaded', {
+ userId,
+ 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 5c6779c62..034b93c6d 100644
--- a/apps/web/src/app/(signing)/sign/[token]/form.tsx
+++ b/apps/web/src/app/(signing)/sign/[token]/form.tsx
@@ -7,9 +7,10 @@ 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 { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token';
import { sortFieldsByPosition, validateFieldsInserted } from '@documenso/lib/utils/fields';
-import { Document, Field, Recipient } from '@documenso/prisma/client';
+import type { Document, Field, Recipient } from '@documenso/prisma/client';
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
import { cn } from '@documenso/ui/lib/utils';
import { Button } from '@documenso/ui/primitives/button';
@@ -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();
@@ -57,6 +59,12 @@ export const SigningForm = ({ document, recipient, fields }: SigningFormProps) =
documentId: document.id,
});
+ analytics.capture('App: Document Signing Complete', {
+ 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 fc85510f3..8eb2ac0cc 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';
@@ -33,6 +34,7 @@ export type SignUpFormProps = {
export const SignUpForm = ({ className }: SignUpFormProps) => {
const { toast } = useToast();
+ const analytics = useAnalytics();
const [showPassword, setShowPassword] = useState(false);
const {
@@ -61,6 +63,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/universal/get-feature-flag.ts b/packages/lib/universal/get-feature-flag.ts
index 38707d41b..bf79f79ce 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';
@@ -20,6 +18,10 @@ export const getFlag = async (
): Promise => {
const requestHeaders = options?.requestHeaders ?? {};
+ if (!LOCAL_FEATURE_FLAGS[flag]) {
+ return LOCAL_FEATURE_FLAGS[flag];
+ }
+
if (!isFeatureFlagEnabled()) {
return LOCAL_FEATURE_FLAGS[flag] ?? true;
}