diff --git a/.cursor/rules/database.mdc b/.cursor/rules/database.mdc
index beee6adfa1..e1f58c50b7 100644
--- a/.cursor/rules/database.mdc
+++ b/.cursor/rules/database.mdc
@@ -1,13 +1,8 @@
---
description: >
- This rule provides comprehensive knowledge about the Formbricks database structure, relationships,
- and data patterns. It should be used **only when the agent explicitly requests database schema-level
- details** to support tasks such as: writing/debugging Prisma queries, designing/reviewing data models,
- investigating multi-tenancy behavior, creating API endpoints, or understanding data relationships.
-globs: []
-alwaysApply: agent-requested
+globs: schema.prisma
+alwaysApply: false
---
-
# Formbricks Database Schema Reference
This rule provides a reference to the Formbricks database structure. For the most up-to-date and complete schema definitions, please refer to the schema.prisma file directly.
diff --git a/.cursor/rules/performance-optimization.mdc b/.cursor/rules/performance-optimization.mdc
deleted file mode 100644
index b93c988bf4..0000000000
--- a/.cursor/rules/performance-optimization.mdc
+++ /dev/null
@@ -1,5 +0,0 @@
----
-description:
-globs:
-alwaysApply: false
----
diff --git a/.cursor/rules/react-context-providers.mdc b/.cursor/rules/react-context-providers.mdc
deleted file mode 100644
index b93c988bf4..0000000000
--- a/.cursor/rules/react-context-providers.mdc
+++ /dev/null
@@ -1,5 +0,0 @@
----
-description:
-globs:
-alwaysApply: false
----
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index 51e18c51da..ebdfa42909 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -17,7 +17,6 @@ on:
workflow_dispatch:
env:
- TELEMETRY_DISABLED: 1
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
diff --git a/apps/web/app/(app)/(onboarding)/organizations/[organizationId]/layout.tsx b/apps/web/app/(app)/(onboarding)/organizations/[organizationId]/layout.tsx
index ab6309e4d6..261388c920 100644
--- a/apps/web/app/(app)/(onboarding)/organizations/[organizationId]/layout.tsx
+++ b/apps/web/app/(app)/(onboarding)/organizations/[organizationId]/layout.tsx
@@ -1,8 +1,6 @@
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { AuthorizationError } from "@formbricks/types/errors";
-import { PosthogIdentify } from "@/app/(app)/environments/[environmentId]/components/PosthogIdentify";
-import { IS_POSTHOG_CONFIGURED } from "@/lib/constants";
import { canUserAccessOrganization } from "@/lib/organization/auth";
import { getOrganization } from "@/lib/organization/service";
import { getUser } from "@/lib/user/service";
@@ -40,14 +38,6 @@ const ProjectOnboardingLayout = async (props) => {
return (
diff --git a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/layout.tsx b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/layout.tsx
index 7311ef319e..d1ff590389 100644
--- a/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/layout.tsx
+++ b/apps/web/app/(app)/(survey-editor)/environments/[environmentId]/layout.tsx
@@ -1,14 +1,13 @@
import { redirect } from "next/navigation";
import { getEnvironment } from "@/lib/environment/service";
import { environmentIdLayoutChecks } from "@/modules/environments/lib/utils";
-import { EnvironmentIdBaseLayout } from "@/modules/ui/components/environmentId-base-layout";
const SurveyEditorEnvironmentLayout = async (props) => {
const params = await props.params;
const { children } = props;
- const { t, session, user, organization } = await environmentIdLayoutChecks(params.environmentId);
+ const { t, session, user } = await environmentIdLayoutChecks(params.environmentId);
if (!session) {
return redirect(`/auth/login`);
@@ -25,15 +24,9 @@ const SurveyEditorEnvironmentLayout = async (props) => {
}
return (
-
-
-
+
);
};
diff --git a/apps/web/app/(app)/environments/[environmentId]/components/PosthogIdentify.tsx b/apps/web/app/(app)/environments/[environmentId]/components/PosthogIdentify.tsx
deleted file mode 100644
index d62d2abd63..0000000000
--- a/apps/web/app/(app)/environments/[environmentId]/components/PosthogIdentify.tsx
+++ /dev/null
@@ -1,61 +0,0 @@
-"use client";
-
-import type { Session } from "next-auth";
-import { usePostHog } from "posthog-js/react";
-import { useEffect } from "react";
-import { TOrganizationBilling } from "@formbricks/types/organizations";
-import { TUser } from "@formbricks/types/user";
-
-interface PosthogIdentifyProps {
- session: Session;
- user: TUser;
- environmentId?: string;
- organizationId?: string;
- organizationName?: string;
- organizationBilling?: TOrganizationBilling;
- isPosthogEnabled: boolean;
-}
-
-export const PosthogIdentify = ({
- session,
- user,
- environmentId,
- organizationId,
- organizationName,
- organizationBilling,
- isPosthogEnabled,
-}: PosthogIdentifyProps) => {
- const posthog = usePostHog();
-
- useEffect(() => {
- if (isPosthogEnabled && session.user && posthog) {
- posthog.identify(session.user.id, {
- name: user.name,
- email: user.email,
- });
- if (environmentId) {
- posthog.group("environment", environmentId, { name: environmentId });
- }
- if (organizationId) {
- posthog.group("organization", organizationId, {
- name: organizationName,
- plan: organizationBilling?.plan,
- responseLimit: organizationBilling?.limits.monthly.responses,
- miuLimit: organizationBilling?.limits.monthly.miu,
- });
- }
- }
- }, [
- posthog,
- session.user,
- environmentId,
- organizationId,
- organizationName,
- organizationBilling,
- user.name,
- user.email,
- isPosthogEnabled,
- ]);
-
- return null;
-};
diff --git a/apps/web/app/(app)/environments/[environmentId]/layout.tsx b/apps/web/app/(app)/environments/[environmentId]/layout.tsx
index ff2f4a07c5..8196a948d7 100644
--- a/apps/web/app/(app)/environments/[environmentId]/layout.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/layout.tsx
@@ -4,7 +4,6 @@ import { EnvironmentLayout } from "@/app/(app)/environments/[environmentId]/comp
import { EnvironmentContextWrapper } from "@/app/(app)/environments/[environmentId]/context/environment-context";
import { authOptions } from "@/modules/auth/lib/authOptions";
import { getEnvironmentLayoutData } from "@/modules/environments/lib/utils";
-import { EnvironmentIdBaseLayout } from "@/modules/ui/components/environmentId-base-layout";
import EnvironmentStorageHandler from "./components/EnvironmentStorageHandler";
const EnvLayout = async (props: {
@@ -24,11 +23,7 @@ const EnvLayout = async (props: {
const layoutData = await getEnvironmentLayoutData(params.environmentId, session.user.id);
return (
-
+ <>
{children}
-
+ >
);
};
diff --git a/apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context.tsx
similarity index 100%
rename from apps/web/app/(app)/environments/[environmentId]/components/ResponseFilterContext.tsx
rename to apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context.tsx
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/layout.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/layout.tsx
index ef78ab7323..634a25f3b3 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/layout.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/layout.tsx
@@ -1,5 +1,6 @@
import { Metadata } from "next";
import { getServerSession } from "next-auth";
+import { ResponseFilterProvider } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import { getResponseCountBySurveyId } from "@/lib/response/service";
import { getSurvey } from "@/lib/survey/service";
import { authOptions } from "@/modules/auth/lib/authOptions";
@@ -25,7 +26,7 @@ export const generateMetadata = async (props: Props): Promise => {
};
const SurveyLayout = async ({ children }) => {
- return <>{children}>;
+ return {children};
};
export default SurveyLayout;
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/components/ResponsePage.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/components/ResponsePage.tsx
index c82f365a61..c934868b31 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/components/ResponsePage.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/components/ResponsePage.tsx
@@ -8,8 +8,8 @@ import { TResponseWithQuotas } from "@formbricks/types/responses";
import { TSurvey } from "@formbricks/types/surveys/types";
import { TTag } from "@formbricks/types/tags";
import { TUser, TUserLocale } from "@formbricks/types/user";
-import { useResponseFilter } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
import { getResponsesAction } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/actions";
+import { useResponseFilter } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import { ResponseDataView } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/responses/components/ResponseDataView";
import { CustomFilter } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter";
import { getFormattedFilters } from "@/app/lib/surveys/surveys";
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx
index 1a96f43071..388f83e67d 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryList.tsx
@@ -12,11 +12,11 @@ import {
} from "@formbricks/types/surveys/types";
import { getTextContent } from "@formbricks/types/surveys/validation";
import { TUserLocale } from "@formbricks/types/user";
+import { EmptyAppSurveys } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys";
import {
SelectedFilterValue,
useResponseFilter,
-} from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
-import { EmptyAppSurveys } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/EmptyInAppSurveys";
+} from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import { CTASummary } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CTASummary";
import { CalSummary } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/CalSummary";
import { ConsentSummary } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/ConsentSummary";
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryPage.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryPage.tsx
index fe2f9ef5f5..47d977d805 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryPage.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryPage.tsx
@@ -5,8 +5,8 @@ import { useEffect, useMemo, useState } from "react";
import { TEnvironment } from "@formbricks/types/environment";
import { TSurvey, TSurveySummary } from "@formbricks/types/surveys/types";
import { TUserLocale } from "@formbricks/types/user";
-import { useResponseFilter } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
import { getSurveySummaryAction } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/actions";
+import { useResponseFilter } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import ScrollToTop from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/ScrollToTop";
import { SummaryDropOffs } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/SummaryDropOffs";
import { CustomFilter } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter";
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter.tsx
index 59c9d5b531..821c71d615 100755
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/CustomFilter.tsx
@@ -25,7 +25,7 @@ import { TSurvey } from "@formbricks/types/surveys/types";
import {
DateRange,
useResponseFilter,
-} from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
+} from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import { getResponsesDownloadUrlAction } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/actions";
import { downloadResponsesFile } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/utils";
import { getFormattedFilters, getTodayDate } from "@/app/lib/surveys/surveys";
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx
index aafc9d231e..5116eb13b0 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/ResponseFilter.tsx
@@ -9,7 +9,7 @@ import {
SelectedFilterValue,
TResponseStatus,
useResponseFilter,
-} from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
+} from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/components/response-filter-context";
import { getSurveyFilterDataAction } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/actions";
import { QuestionFilterComboBox } from "@/app/(app)/environments/[environmentId]/surveys/[surveyId]/components/QuestionFilterComboBox";
import { generateQuestionAndFilterOptions } from "@/app/lib/surveys/surveys";
diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx
index c515fabf3d..65465c32a4 100644
--- a/apps/web/app/(app)/layout.tsx
+++ b/apps/web/app/(app)/layout.tsx
@@ -1,12 +1,9 @@
import { getServerSession } from "next-auth";
-import { Suspense } from "react";
import { IntercomClientWrapper } from "@/app/intercom/IntercomClientWrapper";
-import { IS_POSTHOG_CONFIGURED, POSTHOG_API_HOST, POSTHOG_API_KEY } from "@/lib/constants";
import { getUser } from "@/lib/user/service";
import { authOptions } from "@/modules/auth/lib/authOptions";
import { ClientLogout } from "@/modules/ui/components/client-logout";
import { NoMobileOverlay } from "@/modules/ui/components/no-mobile-overlay";
-import { PHProvider, PostHogPageview } from "@/modules/ui/components/post-hog-client";
import { ToasterClient } from "@/modules/ui/components/toaster-client";
const AppLayout = async ({ children }) => {
@@ -21,20 +18,9 @@ const AppLayout = async ({ children }) => {
return (
<>
-
-
-
-
- <>
-
-
- {children}
- >
-
+
+
+ {children}
>
);
};
diff --git a/apps/web/app/api/lib/utils.ts b/apps/web/app/api/lib/utils.ts
deleted file mode 100644
index 7cf869a09c..0000000000
--- a/apps/web/app/api/lib/utils.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Organization } from "@prisma/client";
-import { logger } from "@formbricks/logger";
-import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
-import { getMonthlyOrganizationResponseCount } from "@/lib/organization/service";
-import { sendPlanLimitsReachedEventToPosthogWeekly } from "@/lib/posthogServer";
-
-export const handleBillingLimitsCheck = async (
- environmentId: string,
- organizationId: string,
- organizationBilling: Organization["billing"]
-): Promise => {
- if (!IS_FORMBRICKS_CLOUD) return;
-
- const responsesCount = await getMonthlyOrganizationResponseCount(organizationId);
- const responsesLimit = organizationBilling.limits.monthly.responses;
-
- if (responsesLimit && responsesCount >= responsesLimit) {
- try {
- await sendPlanLimitsReachedEventToPosthogWeekly(environmentId, {
- plan: organizationBilling.plan,
- limits: {
- projects: null,
- monthly: {
- responses: responsesLimit,
- miu: null,
- },
- },
- });
- } catch (err) {
- // Log error but do not throw
- logger.error(err, "Error sending plan limits reached event to Posthog");
- }
- }
-};
diff --git a/apps/web/app/api/v1/client/[environmentId]/app/sync/[userId]/route.ts b/apps/web/app/api/v1/client/[environmentId]/app/sync/[userId]/route.ts
index 82cd7c5a42..0df10918d8 100644
--- a/apps/web/app/api/v1/client/[environmentId]/app/sync/[userId]/route.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/app/sync/[userId]/route.ts
@@ -18,10 +18,6 @@ import {
getMonthlyOrganizationResponseCount,
getOrganizationByEnvironmentId,
} from "@/lib/organization/service";
-import {
- capturePosthogEnvironmentEvent,
- sendPlanLimitsReachedEventToPosthogWeekly,
-} from "@/lib/posthogServer";
import { getProjectByEnvironmentId } from "@/lib/project/service";
import { COLOR_DEFAULTS } from "@/lib/styling/constants";
@@ -58,20 +54,6 @@ const checkResponseLimit = async (environmentId: string): Promise => {
const monthlyResponseLimit = organization.billing.limits.monthly.responses;
const isLimitReached = monthlyResponseLimit !== null && currentResponseCount >= monthlyResponseLimit;
- if (isLimitReached) {
- try {
- await sendPlanLimitsReachedEventToPosthogWeekly(environmentId, {
- plan: organization.billing.plan,
- limits: {
- projects: null,
- monthly: { responses: monthlyResponseLimit, miu: null },
- },
- });
- } catch (error) {
- logger.error({ error }, `Error sending plan limits reached event to Posthog`);
- }
- }
-
return isLimitReached;
};
@@ -111,10 +93,7 @@ export const GET = withV1ApiWrapper({
}
if (!environment.appSetupCompleted) {
- await Promise.all([
- updateEnvironment(environment.id, { appSetupCompleted: true }),
- capturePosthogEnvironmentEvent(environmentId, "app setup completed"),
- ]);
+ await updateEnvironment(environment.id, { appSetupCompleted: true });
}
// check organization subscriptions and response limits
diff --git a/apps/web/app/api/v1/client/[environmentId]/displays/route.ts b/apps/web/app/api/v1/client/[environmentId]/displays/route.ts
index b6167e4849..9d3233e637 100644
--- a/apps/web/app/api/v1/client/[environmentId]/displays/route.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/displays/route.ts
@@ -5,7 +5,6 @@ import { ResourceNotFoundError } from "@formbricks/types/errors";
import { responses } from "@/app/lib/api/response";
import { transformErrorToDetails } from "@/app/lib/api/validator";
import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
import { createDisplay } from "./lib/display";
@@ -59,7 +58,6 @@ export const POST = withV1ApiWrapper({
try {
const response = await createDisplay(inputValidation.data);
- await capturePosthogEnvironmentEvent(inputValidation.data.environmentId, "display created");
return {
response: responses.successResponse(response, true),
};
diff --git a/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.test.ts b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.test.ts
index 854a4c4403..c19ec3ee4c 100644
--- a/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.test.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.test.ts
@@ -8,16 +8,11 @@ import { TOrganization } from "@formbricks/types/organizations";
import { TSurvey } from "@formbricks/types/surveys/types";
import { cache } from "@/lib/cache";
import { getMonthlyOrganizationResponseCount } from "@/lib/organization/service";
-import {
- capturePosthogEnvironmentEvent,
- sendPlanLimitsReachedEventToPosthogWeekly,
-} from "@/lib/posthogServer";
import { EnvironmentStateData, getEnvironmentStateData } from "./data";
import { getEnvironmentState } from "./environmentState";
// Mock dependencies
vi.mock("@/lib/organization/service");
-vi.mock("@/lib/posthogServer");
vi.mock("@/lib/cache", () => ({
cache: {
withCache: vi.fn(),
@@ -43,7 +38,6 @@ vi.mock("@/lib/constants", () => ({
RECAPTCHA_SECRET_KEY: "mock_recaptcha_secret_key",
IS_RECAPTCHA_CONFIGURED: true,
IS_PRODUCTION: true,
- IS_POSTHOG_CONFIGURED: false,
ENTERPRISE_LICENSE_KEY: "mock_enterprise_license_key",
}));
@@ -188,9 +182,7 @@ describe("getEnvironmentState", () => {
expect(result.data).toEqual(expectedData);
expect(getEnvironmentStateData).toHaveBeenCalledWith(environmentId);
expect(prisma.environment.update).not.toHaveBeenCalled();
- expect(capturePosthogEnvironmentEvent).not.toHaveBeenCalled();
expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(mockOrganization.id);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
});
test("should throw ResourceNotFoundError if environment not found", async () => {
@@ -226,7 +218,6 @@ describe("getEnvironmentState", () => {
where: { id: environmentId },
data: { appSetupCompleted: true },
});
- expect(capturePosthogEnvironmentEvent).toHaveBeenCalledWith(environmentId, "app setup completed");
expect(result.data).toBeDefined();
});
@@ -237,16 +228,6 @@ describe("getEnvironmentState", () => {
expect(result.data.surveys).toEqual([]);
expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(mockOrganization.id);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalledWith(environmentId, {
- plan: mockOrganization.billing.plan,
- limits: {
- projects: null,
- monthly: {
- miu: null,
- responses: mockOrganization.billing.limits.monthly.responses,
- },
- },
- });
});
test("should return surveys if monthly response limit not reached (Cloud)", async () => {
@@ -256,21 +237,6 @@ describe("getEnvironmentState", () => {
expect(result.data.surveys).toEqual(mockSurveys);
expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(mockOrganization.id);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
- });
-
- test("should handle error when sending Posthog limit reached event", async () => {
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(100);
- const posthogError = new Error("Posthog failed");
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockRejectedValue(posthogError);
-
- const result = await getEnvironmentState(environmentId);
-
- expect(result.data.surveys).toEqual([]);
- expect(logger.error).toHaveBeenCalledWith(
- posthogError,
- "Error sending plan limits reached event to Posthog"
- );
});
test("should include recaptchaSiteKey if recaptcha variables are set", async () => {
@@ -313,7 +279,6 @@ describe("getEnvironmentState", () => {
// Should return surveys even with high count since limit is null (unlimited)
expect(result.data.surveys).toEqual(mockSurveys);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
});
test("should propagate database update errors", async () => {
@@ -331,21 +296,6 @@ describe("getEnvironmentState", () => {
await expect(getEnvironmentState(environmentId)).rejects.toThrow("Database error");
});
- test("should propagate PostHog event capture errors", async () => {
- const incompleteEnvironmentData = {
- ...mockEnvironmentStateData,
- environment: {
- ...mockEnvironmentStateData.environment,
- appSetupCompleted: false,
- },
- };
- vi.mocked(getEnvironmentStateData).mockResolvedValue(incompleteEnvironmentData);
- vi.mocked(capturePosthogEnvironmentEvent).mockRejectedValue(new Error("PostHog error"));
-
- // Should throw error since Promise.all will fail if PostHog event capture fails
- await expect(getEnvironmentState(environmentId)).rejects.toThrow("PostHog error");
- });
-
test("should include recaptchaSiteKey when IS_RECAPTCHA_CONFIGURED is true", async () => {
const result = await getEnvironmentState(environmentId);
diff --git a/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts
index 7c26b10f26..b62a02f840 100644
--- a/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/environment/lib/environmentState.ts
@@ -1,15 +1,10 @@
import "server-only";
import { createCacheKey } from "@formbricks/cache";
import { prisma } from "@formbricks/database";
-import { logger } from "@formbricks/logger";
import { TJsEnvironmentState } from "@formbricks/types/js";
import { cache } from "@/lib/cache";
import { IS_FORMBRICKS_CLOUD, IS_RECAPTCHA_CONFIGURED, RECAPTCHA_SITE_KEY } from "@/lib/constants";
import { getMonthlyOrganizationResponseCount } from "@/lib/organization/service";
-import {
- capturePosthogEnvironmentEvent,
- sendPlanLimitsReachedEventToPosthogWeekly,
-} from "@/lib/posthogServer";
import { getEnvironmentStateData } from "./data";
/**
@@ -33,13 +28,10 @@ export const getEnvironmentState = async (
// Handle app setup completion update if needed
// This is a one-time setup flag that can tolerate TTL-based cache expiration
if (!environment.appSetupCompleted) {
- await Promise.all([
- prisma.environment.update({
- where: { id: environmentId },
- data: { appSetupCompleted: true },
- }),
- capturePosthogEnvironmentEvent(environmentId, "app setup completed"),
- ]);
+ await prisma.environment.update({
+ where: { id: environmentId },
+ data: { appSetupCompleted: true },
+ });
}
// Check monthly response limits for Formbricks Cloud
@@ -49,24 +41,6 @@ export const getEnvironmentState = async (
const currentResponseCount = await getMonthlyOrganizationResponseCount(organization.id);
isMonthlyResponsesLimitReached =
monthlyResponseLimit !== null && currentResponseCount >= monthlyResponseLimit;
-
- // Send plan limits event if needed
- if (isMonthlyResponsesLimitReached) {
- try {
- await sendPlanLimitsReachedEventToPosthogWeekly(environmentId, {
- plan: organization.billing.plan,
- limits: {
- projects: null,
- monthly: {
- miu: null,
- responses: organization.billing.limits.monthly.responses,
- },
- },
- });
- } catch (err) {
- logger.error(err, "Error sending plan limits reached event to Posthog");
- }
- }
}
// Build the response data
diff --git a/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.test.ts b/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.test.ts
index 48a87da33a..8a5aa1b08a 100644
--- a/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.test.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.test.ts
@@ -1,15 +1,10 @@
import { Prisma } from "@prisma/client";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
-import { logger } from "@formbricks/logger";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
import { TSurveyQuota } from "@formbricks/types/quota";
import { TResponseInput } from "@formbricks/types/responses";
-import {
- getMonthlyOrganizationResponseCount,
- getOrganizationByEnvironmentId,
-} from "@/lib/organization/service";
-import { sendPlanLimitsReachedEventToPosthogWeekly } from "@/lib/posthogServer";
+import { getOrganizationByEnvironmentId } from "@/lib/organization/service";
import { calculateTtcTotal } from "@/lib/response/utils";
import { evaluateResponseQuotas } from "@/modules/ee/quotas/lib/evaluation-service";
import { createResponse, createResponseWithQuotaEvaluation } from "./response";
@@ -24,22 +19,13 @@ vi.mock("@/lib/constants", () => ({
}));
vi.mock("@/lib/organization/service", () => ({
- getMonthlyOrganizationResponseCount: vi.fn(),
getOrganizationByEnvironmentId: vi.fn(),
}));
-vi.mock("@/lib/posthogServer", () => ({
- sendPlanLimitsReachedEventToPosthogWeekly: vi.fn(),
-}));
-
vi.mock("@/lib/response/utils", () => ({
calculateTtcTotal: vi.fn((ttc) => ttc),
}));
-vi.mock("@/lib/telemetry", () => ({
- captureTelemetry: vi.fn(),
-}));
-
vi.mock("@/lib/utils/validate", () => ({
validateInputs: vi.fn(),
}));
@@ -138,35 +124,6 @@ describe("createResponse", () => {
);
});
- test("should check response limits if IS_FORMBRICKS_CLOUD is true", async () => {
- mockIsFormbricksCloud = true;
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(50);
-
- await createResponse(mockResponseInput, prisma);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
- });
-
- test("should send limit reached event if IS_FORMBRICKS_CLOUD is true and limit reached", async () => {
- mockIsFormbricksCloud = true;
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(100);
-
- await createResponse(mockResponseInput, prisma);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalledWith(environmentId, {
- plan: "free",
- limits: {
- projects: null,
- monthly: {
- responses: 100,
- miu: null,
- },
- },
- });
- });
-
test("should throw ResourceNotFoundError if organization not found", async () => {
vi.mocked(getOrganizationByEnvironmentId).mockResolvedValue(null);
await expect(createResponse(mockResponseInput, prisma)).rejects.toThrow(ResourceNotFoundError);
@@ -186,20 +143,6 @@ describe("createResponse", () => {
vi.mocked(prisma.response.create).mockRejectedValue(genericError);
await expect(createResponse(mockResponseInput)).rejects.toThrow(genericError);
});
-
- test("should log error but not throw if sendPlanLimitsReachedEventToPosthogWeekly fails", async () => {
- mockIsFormbricksCloud = true;
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(100);
- const posthogError = new Error("PostHog error");
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockRejectedValue(posthogError);
-
- await createResponse(mockResponseInput);
-
- expect(logger.error).toHaveBeenCalledWith(
- posthogError,
- "Error sending plan limits reached event to Posthog"
- );
- });
});
describe("createResponseWithQuotaEvaluation", () => {
diff --git a/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.ts b/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.ts
index bd67f3150c..2239761c4a 100644
--- a/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/responses/lib/response.ts
@@ -6,11 +6,9 @@ import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
import { TResponseWithQuotaFull } from "@formbricks/types/quota";
import { TResponse, TResponseInput, ZResponseInput } from "@formbricks/types/responses";
import { TTag } from "@formbricks/types/tags";
-import { handleBillingLimitsCheck } from "@/app/api/lib/utils";
import { buildPrismaResponseData } from "@/app/api/v1/lib/utils";
import { getOrganizationByEnvironmentId } from "@/lib/organization/service";
import { calculateTtcTotal } from "@/lib/response/utils";
-import { captureTelemetry } from "@/lib/telemetry";
import { validateInputs } from "@/lib/utils/validate";
import { evaluateResponseQuotas } from "@/modules/ee/quotas/lib/evaluation-service";
import { getContactByUserId } from "./contact";
@@ -83,7 +81,6 @@ export const createResponse = async (
tx: Prisma.TransactionClient
): Promise => {
validateInputs([responseInput, ZResponseInput]);
- captureTelemetry("response created");
const { environmentId, userId, finished, ttc: initialTtc } = responseInput;
@@ -121,8 +118,6 @@ export const createResponse = async (
tags: responsePrisma.tags.map((tagPrisma: { tag: TTag }) => tagPrisma.tag),
};
- await handleBillingLimitsCheck(environmentId, organization.id, organization.billing);
-
return response;
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
diff --git a/apps/web/app/api/v1/client/[environmentId]/responses/route.ts b/apps/web/app/api/v1/client/[environmentId]/responses/route.ts
index 687269c29a..09012afe22 100644
--- a/apps/web/app/api/v1/client/[environmentId]/responses/route.ts
+++ b/apps/web/app/api/v1/client/[environmentId]/responses/route.ts
@@ -10,7 +10,6 @@ import { responses } from "@/app/lib/api/response";
import { transformErrorToDetails } from "@/app/lib/api/validator";
import { withV1ApiWrapper } from "@/app/lib/api/with-api-logging";
import { sendToPipeline } from "@/app/lib/pipelines";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { getSurvey } from "@/lib/survey/service";
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
import { createQuotaFullObject } from "@/modules/ee/quotas/lib/helpers";
@@ -172,11 +171,6 @@ export const POST = withV1ApiWrapper({
});
}
- await capturePosthogEnvironmentEvent(survey.environmentId, "response created", {
- surveyId: responseData.surveyId,
- surveyType: survey.type,
- });
-
const quotaObj = createQuotaFullObject(quotaFull);
const responseDataWithQuota = {
diff --git a/apps/web/app/api/v1/management/responses/lib/response.test.ts b/apps/web/app/api/v1/management/responses/lib/response.test.ts
index 3408b0cde6..fcda8cb9f5 100644
--- a/apps/web/app/api/v1/management/responses/lib/response.test.ts
+++ b/apps/web/app/api/v1/management/responses/lib/response.test.ts
@@ -4,11 +4,7 @@ import { prisma } from "@formbricks/database";
import { logger } from "@formbricks/logger";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
import { TResponse, TResponseInput } from "@formbricks/types/responses";
-import {
- getMonthlyOrganizationResponseCount,
- getOrganizationByEnvironmentId,
-} from "@/lib/organization/service";
-import { sendPlanLimitsReachedEventToPosthogWeekly } from "@/lib/posthogServer";
+import { getOrganizationByEnvironmentId } from "@/lib/organization/service";
import { getResponseContact } from "@/lib/response/service";
import { calculateTtcTotal } from "@/lib/response/utils";
import { validateInputs } from "@/lib/utils/validate";
@@ -96,9 +92,6 @@ const mockTransformedResponses = [mockResponse, { ...mockResponse, id: "response
// Mock dependencies
vi.mock("@/lib/constants", () => ({
IS_FORMBRICKS_CLOUD: true,
- POSTHOG_API_KEY: "mock-posthog-api-key",
- POSTHOG_HOST: "mock-posthog-host",
- IS_POSTHOG_CONFIGURED: true,
ENCRYPTION_KEY: "mock-encryption-key",
ENTERPRISE_LICENSE_KEY: "mock-enterprise-license-key",
GITHUB_ID: "mock-github-id",
@@ -118,10 +111,8 @@ vi.mock("@/lib/constants", () => ({
SENTRY_DSN: "mock-sentry-dsn",
}));
vi.mock("@/lib/organization/service");
-vi.mock("@/lib/posthogServer");
vi.mock("@/lib/response/service");
vi.mock("@/lib/response/utils");
-vi.mock("@/lib/telemetry");
vi.mock("@/lib/utils/validate");
vi.mock("@formbricks/database", () => ({
prisma: {
@@ -162,7 +153,6 @@ describe("Response Lib Tests", () => {
vi.mocked(mockTx.response.create).mockResolvedValue({
...mockResponsePrisma,
});
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(50);
const response = await createResponse(mockResponseInputWithUserId, mockTx);
@@ -217,68 +207,6 @@ describe("Response Lib Tests", () => {
await expect(createResponse(mockResponseInput, mockTx)).rejects.toThrow(genericError);
});
-
- describe("Cloud specific tests", () => {
- test("should check response limit and send event if limit reached", async () => {
- // IS_FORMBRICKS_CLOUD is true by default from the top-level mock
- const limit = 100;
- const mockOrgWithBilling = {
- ...mockOrganization,
- billing: { limits: { monthly: { responses: limit } } },
- } as any;
- vi.mocked(getOrganizationByEnvironmentId).mockResolvedValue(mockOrgWithBilling);
- vi.mocked(calculateTtcTotal).mockReturnValue({ total: 10 });
- vi.mocked(mockTx.response.create).mockResolvedValue(mockResponsePrisma);
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(limit); // Limit reached
-
- await createResponse(mockResponseInput, mockTx);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalled();
- });
-
- test("should check response limit and not send event if limit not reached", async () => {
- const limit = 100;
- const mockOrgWithBilling = {
- ...mockOrganization,
- billing: { limits: { monthly: { responses: limit } } },
- } as any;
- vi.mocked(getOrganizationByEnvironmentId).mockResolvedValue(mockOrgWithBilling);
- vi.mocked(calculateTtcTotal).mockReturnValue({ total: 10 });
- vi.mocked(mockTx.response.create).mockResolvedValue(mockResponsePrisma);
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(limit - 1); // Limit not reached
-
- await createResponse(mockResponseInput, mockTx);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
- });
-
- test("should log error if sendPlanLimitsReachedEventToPosthogWeekly fails", async () => {
- const limit = 100;
- const mockOrgWithBilling = {
- ...mockOrganization,
- billing: { limits: { monthly: { responses: limit } } },
- } as any;
- const posthogError = new Error("Posthog error");
- vi.mocked(getOrganizationByEnvironmentId).mockResolvedValue(mockOrgWithBilling);
- vi.mocked(calculateTtcTotal).mockReturnValue({ total: 10 });
- vi.mocked(mockTx.response.create).mockResolvedValue(mockResponsePrisma);
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(limit); // Limit reached
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockRejectedValue(posthogError);
-
- // Expecting successful response creation despite PostHog error
- const response = await createResponse(mockResponseInput, mockTx);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalled();
- expect(logger.error).toHaveBeenCalledWith(
- posthogError,
- "Error sending plan limits reached event to Posthog"
- );
- expect(response).toEqual(mockResponse); // Should still return the created response
- });
- });
});
describe("getResponsesByEnvironmentIds", () => {
diff --git a/apps/web/app/api/v1/management/responses/lib/response.ts b/apps/web/app/api/v1/management/responses/lib/response.ts
index 5c6ec48ad6..18f410a4f9 100644
--- a/apps/web/app/api/v1/management/responses/lib/response.ts
+++ b/apps/web/app/api/v1/management/responses/lib/response.ts
@@ -8,14 +8,12 @@ import { TContactAttributes } from "@formbricks/types/contact-attribute";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
import { TResponse, TResponseInput, ZResponseInput } from "@formbricks/types/responses";
import { TTag } from "@formbricks/types/tags";
-import { handleBillingLimitsCheck } from "@/app/api/lib/utils";
import { buildPrismaResponseData } from "@/app/api/v1/lib/utils";
import { RESPONSES_PER_PAGE } from "@/lib/constants";
import { getOrganizationByEnvironmentId } from "@/lib/organization/service";
import { getResponseContact } from "@/lib/response/service";
import { calculateTtcTotal } from "@/lib/response/utils";
import { getSurvey } from "@/lib/survey/service";
-import { captureTelemetry } from "@/lib/telemetry";
import { validateInputs } from "@/lib/utils/validate";
import { evaluateResponseQuotas } from "@/modules/ee/quotas/lib/evaluation-service";
import { getContactByUserId } from "./contact";
@@ -93,7 +91,6 @@ export const createResponse = async (
tx?: Prisma.TransactionClient
): Promise => {
validateInputs([responseInput, ZResponseInput]);
- captureTelemetry("response created");
const { environmentId, userId, finished, ttc: initialTtc } = responseInput;
@@ -131,8 +128,6 @@ export const createResponse = async (
tags: responsePrisma.tags.map((tagPrisma: { tag: TTag }) => tagPrisma.tag),
};
- await handleBillingLimitsCheck(environmentId, organization.id, organization.billing);
-
return response;
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
diff --git a/apps/web/app/api/v2/client/[environmentId]/displays/route.ts b/apps/web/app/api/v2/client/[environmentId]/displays/route.ts
index ba17c55a4e..ef312801e2 100644
--- a/apps/web/app/api/v2/client/[environmentId]/displays/route.ts
+++ b/apps/web/app/api/v2/client/[environmentId]/displays/route.ts
@@ -3,7 +3,6 @@ import { ResourceNotFoundError } from "@formbricks/types/errors";
import { ZDisplayCreateInputV2 } from "@/app/api/v2/client/[environmentId]/displays/types/display";
import { responses } from "@/app/lib/api/response";
import { transformErrorToDetails } from "@/app/lib/api/validator";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
import { createDisplay } from "./lib/display";
@@ -49,7 +48,6 @@ export const POST = async (request: Request, context: Context): Promise ({
}));
vi.mock("@/lib/organization/service");
-vi.mock("@/lib/posthogServer");
vi.mock("@/lib/response/utils");
-vi.mock("@/lib/telemetry");
vi.mock("@/lib/utils/validate");
vi.mock("@/modules/ee/quotas/lib/evaluation-service");
vi.mock("@formbricks/database", () => ({
@@ -166,9 +159,6 @@ describe("createResponse V2", () => {
...ttc,
_total: Object.values(ttc).reduce((a, b) => a + b, 0),
}));
- vi.mocked(captureTelemetry).mockResolvedValue(undefined);
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(50);
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockResolvedValue(undefined);
vi.mocked(evaluateResponseQuotas).mockResolvedValue({
shouldEndSurvey: false,
quotaFull: null,
@@ -179,32 +169,6 @@ describe("createResponse V2", () => {
mockIsFormbricksCloud = false;
});
- test("should check response limits if IS_FORMBRICKS_CLOUD is true", async () => {
- mockIsFormbricksCloud = true;
- await createResponse(mockResponseInput, mockTx);
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).not.toHaveBeenCalled();
- });
-
- test("should send limit reached event if IS_FORMBRICKS_CLOUD is true and limit reached", async () => {
- mockIsFormbricksCloud = true;
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(100);
-
- await createResponse(mockResponseInput, mockTx);
-
- expect(getMonthlyOrganizationResponseCount).toHaveBeenCalledWith(organizationId);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalledWith(environmentId, {
- plan: "free",
- limits: {
- projects: null,
- monthly: {
- responses: 100,
- miu: null,
- },
- },
- });
- });
-
test("should throw ResourceNotFoundError if organization not found", async () => {
vi.mocked(getOrganizationByEnvironmentId).mockResolvedValue(null);
await expect(createResponse(mockResponseInput, mockTx)).rejects.toThrow(ResourceNotFoundError);
@@ -225,20 +189,6 @@ describe("createResponse V2", () => {
await expect(createResponse(mockResponseInput, mockTx)).rejects.toThrow(genericError);
});
- test("should log error but not throw if sendPlanLimitsReachedEventToPosthogWeekly fails", async () => {
- mockIsFormbricksCloud = true;
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(100);
- const posthogError = new Error("PostHog error");
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockRejectedValue(posthogError);
-
- await createResponse(mockResponseInput, mockTx); // Should not throw
-
- expect(logger.error).toHaveBeenCalledWith(
- posthogError,
- "Error sending plan limits reached event to Posthog"
- );
- });
-
test("should correctly map prisma tags to response tags", async () => {
const mockTag: TTag = { id: "tag1", name: "Tag 1", environmentId };
const prismaResponseWithTags = {
@@ -269,7 +219,6 @@ describe("createResponseWithQuotaEvaluation V2", () => {
...ttc,
_total: Object.values(ttc).reduce((a, b) => a + b, 0),
}));
- vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(50);
vi.mocked(evaluateResponseQuotas).mockResolvedValue({
shouldEndSurvey: false,
quotaFull: null,
diff --git a/apps/web/app/api/v2/client/[environmentId]/responses/lib/response.ts b/apps/web/app/api/v2/client/[environmentId]/responses/lib/response.ts
index c1942c9d48..f6a828c396 100644
--- a/apps/web/app/api/v2/client/[environmentId]/responses/lib/response.ts
+++ b/apps/web/app/api/v2/client/[environmentId]/responses/lib/response.ts
@@ -6,12 +6,10 @@ import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors";
import { TResponseWithQuotaFull } from "@formbricks/types/quota";
import { TResponse, ZResponseInput } from "@formbricks/types/responses";
import { TTag } from "@formbricks/types/tags";
-import { handleBillingLimitsCheck } from "@/app/api/lib/utils";
import { responseSelection } from "@/app/api/v1/client/[environmentId]/responses/lib/response";
import { TResponseInputV2 } from "@/app/api/v2/client/[environmentId]/responses/types/response";
import { getOrganizationByEnvironmentId } from "@/lib/organization/service";
import { calculateTtcTotal } from "@/lib/response/utils";
-import { captureTelemetry } from "@/lib/telemetry";
import { validateInputs } from "@/lib/utils/validate";
import { evaluateResponseQuotas } from "@/modules/ee/quotas/lib/evaluation-service";
import { getContact } from "./contact";
@@ -91,7 +89,6 @@ export const createResponse = async (
tx?: Prisma.TransactionClient
): Promise => {
validateInputs([responseInput, ZResponseInput]);
- captureTelemetry("response created");
const { environmentId, contactId, finished, ttc: initialTtc } = responseInput;
@@ -129,8 +126,6 @@ export const createResponse = async (
tags: responsePrisma.tags.map((tagPrisma: { tag: TTag }) => tagPrisma.tag),
};
- await handleBillingLimitsCheck(environmentId, organization.id, organization.billing);
-
return response;
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
diff --git a/apps/web/app/api/v2/client/[environmentId]/responses/route.ts b/apps/web/app/api/v2/client/[environmentId]/responses/route.ts
index 9a920ece64..68eda74abb 100644
--- a/apps/web/app/api/v2/client/[environmentId]/responses/route.ts
+++ b/apps/web/app/api/v2/client/[environmentId]/responses/route.ts
@@ -8,7 +8,6 @@ import { checkSurveyValidity } from "@/app/api/v2/client/[environmentId]/respons
import { responses } from "@/app/lib/api/response";
import { transformErrorToDetails } from "@/app/lib/api/validator";
import { sendToPipeline } from "@/app/lib/pipelines";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { getSurvey } from "@/lib/survey/service";
import { validateOtherOptionLengthForMultipleChoice } from "@/modules/api/v2/lib/question";
import { getIsContactsEnabled } from "@/modules/ee/license-check/lib/utils";
@@ -148,11 +147,6 @@ export const POST = async (request: Request, context: Context): Promise {
- if (!enabled || typeof POSTHOG_API_HOST !== "string" || typeof POSTHOG_API_KEY !== "string") {
- return;
- }
- try {
- const client = new PostHog(POSTHOG_API_KEY, {
- host: POSTHOG_API_HOST,
- });
- client.capture({
- // workaround with a static string as exaplained in PostHog docs: https://posthog.com/docs/product-analytics/group-analytics
- distinctId: "environmentEvents",
- event: eventName,
- groups: { environment: environmentId },
- properties,
- });
- await client.shutdown();
- } catch (error) {
- logger.error(error, "error sending posthog event");
- }
-};
-
-export const sendPlanLimitsReachedEventToPosthogWeekly = async (
- environmentId: string,
- billing: {
- plan: TOrganizationBillingPlan;
- limits: TOrganizationBillingPlanLimits;
- }
-) =>
- await cache.withCache(
- async () => {
- try {
- await capturePosthogEnvironmentEvent(environmentId, "plan limit reached", {
- ...billing,
- });
- return "success";
- } catch (error) {
- logger.error(error, "error sending plan limits reached event to posthog weekly");
- throw error;
- }
- },
- createCacheKey.custom("analytics", environmentId, `plan_limits_${billing.plan}`),
- 60 * 60 * 24 * 7 * 1000 // 7 days in milliseconds
- );
diff --git a/apps/web/lib/survey/service.test.ts b/apps/web/lib/survey/service.test.ts
index 4253c78a12..8970d82ca4 100644
--- a/apps/web/lib/survey/service.test.ts
+++ b/apps/web/lib/survey/service.test.ts
@@ -13,7 +13,6 @@ import {
getOrganizationByEnvironmentId,
subscribeOrganizationMembersToSurveyResponses,
} from "@/lib/organization/service";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { evaluateLogic } from "@/lib/surveyLogic/utils";
import {
mockActionClass,
@@ -44,11 +43,6 @@ vi.mock("@/lib/organization/service", () => ({
subscribeOrganizationMembersToSurveyResponses: vi.fn(),
}));
-// Mock posthogServer
-vi.mock("@/lib/posthogServer", () => ({
- capturePosthogEnvironmentEvent: vi.fn(),
-}));
-
// Mock actionClass service
vi.mock("@/lib/actionClass/service", () => ({
getActionClasses: vi.fn(),
@@ -646,7 +640,6 @@ describe("Tests for createSurvey", () => {
expect(prisma.survey.create).toHaveBeenCalled();
expect(result.name).toEqual(mockSurveyOutput.name);
expect(subscribeOrganizationMembersToSurveyResponses).toHaveBeenCalled();
- expect(capturePosthogEnvironmentEvent).toHaveBeenCalled();
});
test("creates a private segment for app surveys", async () => {
diff --git a/apps/web/lib/survey/service.ts b/apps/web/lib/survey/service.ts
index 6f3a801b07..779854c069 100644
--- a/apps/web/lib/survey/service.ts
+++ b/apps/web/lib/survey/service.ts
@@ -13,7 +13,6 @@ import {
} from "@/lib/organization/service";
import { getActionClasses } from "../actionClass/service";
import { ITEMS_PER_PAGE } from "../constants";
-import { capturePosthogEnvironmentEvent } from "../posthogServer";
import { validateInputs } from "../utils/validate";
import { checkForInvalidImagesInQuestions, transformPrismaSurvey } from "./utils";
@@ -673,11 +672,6 @@ export const createSurvey = async (
await subscribeOrganizationMembersToSurveyResponses(survey.id, createdBy, organization.id);
}
- await capturePosthogEnvironmentEvent(survey.environmentId, "survey created", {
- surveyId: survey.id,
- surveyType: survey.type,
- });
-
return transformedSurvey;
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
diff --git a/apps/web/lib/telemetry.ts b/apps/web/lib/telemetry.ts
deleted file mode 100644
index 25cc2408a9..0000000000
--- a/apps/web/lib/telemetry.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/* We use this telemetry service to better understand how Formbricks is being used
- and how we can improve it. All data including the IP address is collected anonymously
- and we cannot trace anything back to you or your customers. If you still want to
- disable telemetry, set the environment variable TELEMETRY_DISABLED=1 */
-import { logger } from "@formbricks/logger";
-import { IS_PRODUCTION } from "./constants";
-import { env } from "./env";
-
-const crypto = require("crypto");
-
-// We are using the hashed CRON_SECRET as the distinct identifier for the instance for telemetry.
-// The hash cannot be traced back to the original value or the instance itself.
-// This is to ensure that the telemetry data is anonymous but still unique to the instance.
-const getTelemetryId = (): string => {
- return crypto.createHash("sha256").update(env.CRON_SECRET).digest("hex");
-};
-
-export const captureTelemetry = async (eventName: string, properties = {}) => {
- if (env.TELEMETRY_DISABLED !== "1" && IS_PRODUCTION) {
- try {
- await fetch("https://telemetry.formbricks.com/capture/", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
- api_key: "phc_SoIFUJ8b9ufDm0YOnoOxJf6PXyuHpO7N6RztxFdZTy", // NOSONAR // This is a public API key for telemetry and not a secret
- event: eventName,
- properties: {
- distinct_id: getTelemetryId(),
- ...properties,
- },
- timestamp: new Date().toISOString(),
- }),
- });
- } catch (error) {
- logger.error(error, "error sending telemetry");
- }
- }
-};
diff --git a/apps/web/modules/api/v2/management/responses/lib/response.ts b/apps/web/modules/api/v2/management/responses/lib/response.ts
index 09de56b895..07b578e96a 100644
--- a/apps/web/modules/api/v2/management/responses/lib/response.ts
+++ b/apps/web/modules/api/v2/management/responses/lib/response.ts
@@ -1,13 +1,10 @@
import "server-only";
import { Prisma, Response } from "@prisma/client";
import { prisma } from "@formbricks/database";
-import { logger } from "@formbricks/logger";
import { TContactAttributes } from "@formbricks/types/contact-attribute";
import { Result, err, ok } from "@formbricks/types/error-handlers";
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
-import { sendPlanLimitsReachedEventToPosthogWeekly } from "@/lib/posthogServer";
import { calculateTtcTotal } from "@/lib/response/utils";
-import { captureTelemetry } from "@/lib/telemetry";
import { getContactByUserId } from "@/modules/api/v2/management/responses/lib/contact";
import {
getMonthlyOrganizationResponseCount,
@@ -51,8 +48,6 @@ export const createResponse = async (
responseInput: TResponseInput,
tx?: Prisma.TransactionClient
): Promise> => {
- captureTelemetry("response created");
-
const {
surveyId,
displayId,
@@ -126,7 +121,6 @@ export const createResponse = async (
if (!billing.ok) {
return err(billing.error as ApiErrorResponseV2);
}
- const billingData = billing.data;
const prismaClient = tx ?? prisma;
@@ -140,26 +134,7 @@ export const createResponse = async (
return err(responsesCountResult.error as ApiErrorResponseV2);
}
- const responsesCount = responsesCountResult.data;
- const responsesLimit = billingData.limits?.monthly.responses;
-
- if (responsesLimit && responsesCount >= responsesLimit) {
- try {
- await sendPlanLimitsReachedEventToPosthogWeekly(environmentId, {
- plan: billingData.plan,
- limits: {
- projects: null,
- monthly: {
- responses: responsesLimit,
- miu: null,
- },
- },
- });
- } catch (err) {
- // Log error but do not throw it
- logger.error(err, "Error sending plan limits reached event to Posthog");
- }
- }
+ // Limit check completed
}
return ok(response);
diff --git a/apps/web/modules/api/v2/management/responses/lib/tests/response.test.ts b/apps/web/modules/api/v2/management/responses/lib/tests/response.test.ts
index 4aa6fdb052..d5752fdd6d 100644
--- a/apps/web/modules/api/v2/management/responses/lib/tests/response.test.ts
+++ b/apps/web/modules/api/v2/management/responses/lib/tests/response.test.ts
@@ -12,7 +12,6 @@ import {
import { beforeEach, describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
import { err, ok } from "@formbricks/types/error-handlers";
-import { sendPlanLimitsReachedEventToPosthogWeekly } from "@/lib/posthogServer";
import {
getMonthlyOrganizationResponseCount,
getOrganizationBilling,
@@ -20,10 +19,6 @@ import {
} from "@/modules/api/v2/management/responses/lib/organization";
import { createResponse, getResponses } from "../response";
-vi.mock("@/lib/posthogServer", () => ({
- sendPlanLimitsReachedEventToPosthogWeekly: vi.fn().mockResolvedValue(undefined),
-}));
-
vi.mock("@/modules/api/v2/management/responses/lib/organization", () => ({
getOrganizationIdFromEnvironmentId: vi.fn(),
getOrganizationBilling: vi.fn(),
@@ -150,11 +145,8 @@ describe("Response Lib", () => {
vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(ok(100));
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockImplementation(() => Promise.resolve(""));
-
const result = await createResponse(environmentId, responseInput);
- expect(sendPlanLimitsReachedEventToPosthogWeekly).toHaveBeenCalled();
expect(result.ok).toBe(true);
if (result.ok) {
expect(result.data).toEqual(response);
@@ -191,10 +183,6 @@ describe("Response Lib", () => {
vi.mocked(getMonthlyOrganizationResponseCount).mockResolvedValue(ok(100));
- vi.mocked(sendPlanLimitsReachedEventToPosthogWeekly).mockRejectedValue(
- new Error("Error sending plan limits")
- );
-
const result = await createResponse(environmentId, responseInput);
expect(result.ok).toBe(true);
if (result.ok) {
diff --git a/apps/web/modules/api/v2/management/webhooks/lib/tests/webhook.test.ts b/apps/web/modules/api/v2/management/webhooks/lib/tests/webhook.test.ts
index 2ba67a31a0..8ea78540b6 100644
--- a/apps/web/modules/api/v2/management/webhooks/lib/tests/webhook.test.ts
+++ b/apps/web/modules/api/v2/management/webhooks/lib/tests/webhook.test.ts
@@ -1,7 +1,6 @@
import { WebhookSource } from "@prisma/client";
import { describe, expect, test, vi } from "vitest";
import { prisma } from "@formbricks/database";
-import { captureTelemetry } from "@/lib/telemetry";
import { TGetWebhooksFilter, TWebhookInput } from "@/modules/api/v2/management/webhooks/types/webhooks";
import { createWebhook, getWebhooks } from "../webhook";
@@ -16,10 +15,6 @@ vi.mock("@formbricks/database", () => ({
},
}));
-vi.mock("@/lib/telemetry", () => ({
- captureTelemetry: vi.fn(),
-}));
-
describe("getWebhooks", () => {
const environmentId = "env1";
const params = {
@@ -86,7 +81,6 @@ describe("createWebhook", () => {
vi.mocked(prisma.webhook.create).mockResolvedValueOnce(createdWebhook);
const result = await createWebhook(inputWebhook);
- expect(captureTelemetry).toHaveBeenCalledWith("webhook_created");
expect(prisma.webhook.create).toHaveBeenCalled();
expect(result.ok).toBe(true);
diff --git a/apps/web/modules/api/v2/management/webhooks/lib/webhook.ts b/apps/web/modules/api/v2/management/webhooks/lib/webhook.ts
index d0fc369fc8..76d981efbc 100644
--- a/apps/web/modules/api/v2/management/webhooks/lib/webhook.ts
+++ b/apps/web/modules/api/v2/management/webhooks/lib/webhook.ts
@@ -1,7 +1,6 @@
import { Prisma, Webhook } from "@prisma/client";
import { prisma } from "@formbricks/database";
import { Result, err, ok } from "@formbricks/types/error-handlers";
-import { captureTelemetry } from "@/lib/telemetry";
import { getWebhooksQuery } from "@/modules/api/v2/management/webhooks/lib/utils";
import { TGetWebhooksFilter, TWebhookInput } from "@/modules/api/v2/management/webhooks/types/webhooks";
import { ApiErrorResponseV2 } from "@/modules/api/v2/types/api-error";
@@ -47,8 +46,6 @@ export const getWebhooks = async (
};
export const createWebhook = async (webhook: TWebhookInput): Promise> => {
- captureTelemetry("webhook_created");
-
const { environmentId, name, url, source, triggers, surveyIds } = webhook;
try {
diff --git a/apps/web/modules/api/v2/organizations/[organizationId]/project-teams/lib/project-teams.ts b/apps/web/modules/api/v2/organizations/[organizationId]/project-teams/lib/project-teams.ts
index 26d081280f..1b3ec50ac5 100644
--- a/apps/web/modules/api/v2/organizations/[organizationId]/project-teams/lib/project-teams.ts
+++ b/apps/web/modules/api/v2/organizations/[organizationId]/project-teams/lib/project-teams.ts
@@ -2,7 +2,6 @@ import { ProjectTeam } from "@prisma/client";
import { z } from "zod";
import { prisma } from "@formbricks/database";
import { Result, err, ok } from "@formbricks/types/error-handlers";
-import { captureTelemetry } from "@/lib/telemetry";
import { getProjectTeamsQuery } from "@/modules/api/v2/organizations/[organizationId]/project-teams/lib/utils";
import {
TGetProjectTeamsFilter,
@@ -44,8 +43,6 @@ export const getProjectTeams = async (
export const createProjectTeam = async (
teamInput: TProjectTeamInput
): Promise> => {
- captureTelemetry("project team created");
-
const { teamId, projectId, permission } = teamInput;
try {
diff --git a/apps/web/modules/api/v2/organizations/[organizationId]/teams/lib/teams.ts b/apps/web/modules/api/v2/organizations/[organizationId]/teams/lib/teams.ts
index 3f6fb32020..c60621a2bc 100644
--- a/apps/web/modules/api/v2/organizations/[organizationId]/teams/lib/teams.ts
+++ b/apps/web/modules/api/v2/organizations/[organizationId]/teams/lib/teams.ts
@@ -2,7 +2,6 @@ import "server-only";
import { Team } from "@prisma/client";
import { prisma } from "@formbricks/database";
import { Result, err, ok } from "@formbricks/types/error-handlers";
-import { captureTelemetry } from "@/lib/telemetry";
import { getTeamsQuery } from "@/modules/api/v2/organizations/[organizationId]/teams/lib/utils";
import {
TGetTeamsFilter,
@@ -15,8 +14,6 @@ export const createTeam = async (
teamInput: TTeamInput,
organizationId: string
): Promise> => {
- captureTelemetry("team created");
-
const { name } = teamInput;
try {
diff --git a/apps/web/modules/api/v2/organizations/[organizationId]/users/lib/users.ts b/apps/web/modules/api/v2/organizations/[organizationId]/users/lib/users.ts
index ef81b32cde..5ccbe2f37e 100644
--- a/apps/web/modules/api/v2/organizations/[organizationId]/users/lib/users.ts
+++ b/apps/web/modules/api/v2/organizations/[organizationId]/users/lib/users.ts
@@ -2,7 +2,6 @@ import { OrganizationRole, Prisma, TeamUserRole } from "@prisma/client";
import { prisma } from "@formbricks/database";
import { TUser } from "@formbricks/database/zod/users";
import { Result, err, ok } from "@formbricks/types/error-handlers";
-import { captureTelemetry } from "@/lib/telemetry";
import { getUsersQuery } from "@/modules/api/v2/organizations/[organizationId]/users/lib/utils";
import {
TGetUsersFilter,
@@ -73,8 +72,6 @@ export const createUser = async (
userInput: TUserInput,
organizationId
): Promise> => {
- captureTelemetry("user created");
-
const { name, email, role, teams, isActive } = userInput;
try {
@@ -150,8 +147,6 @@ export const updateUser = async (
userInput: TUserInputPatch,
organizationId: string
): Promise> => {
- captureTelemetry("user updated");
-
const { name, email, role, teams, isActive } = userInput;
let existingTeams: string[] = [];
let newTeams;
diff --git a/apps/web/modules/auth/signup/actions.ts b/apps/web/modules/auth/signup/actions.ts
index 8691071c08..f52965fc23 100644
--- a/apps/web/modules/auth/signup/actions.ts
+++ b/apps/web/modules/auth/signup/actions.ts
@@ -13,7 +13,7 @@ import { ActionClientCtx } from "@/lib/utils/action-client/types/context";
import { createUser, updateUser } from "@/modules/auth/lib/user";
import { deleteInvite, getInvite } from "@/modules/auth/signup/lib/invite";
import { createTeamMembership } from "@/modules/auth/signup/lib/team";
-import { captureFailedSignup, verifyTurnstileToken } from "@/modules/auth/signup/lib/utils";
+import { verifyTurnstileToken } from "@/modules/auth/signup/lib/utils";
import { applyIPRateLimit } from "@/modules/core/rate-limit/helpers";
import { rateLimitConfigs } from "@/modules/core/rate-limit/rate-limit-configs";
import { withAuditLogging } from "@/modules/ee/audit-logs/lib/handler";
@@ -46,21 +46,15 @@ const ZCreateUserAction = z.object({
),
});
-async function verifyTurnstileIfConfigured(
- turnstileToken: string | undefined,
- email: string,
- name: string
-): Promise {
+async function verifyTurnstileIfConfigured(turnstileToken: string | undefined): Promise {
if (!IS_TURNSTILE_CONFIGURED) return;
if (!turnstileToken || !TURNSTILE_SECRET_KEY) {
- captureFailedSignup(email, name);
throw new UnknownError("Server configuration error");
}
const isHuman = await verifyTurnstileToken(TURNSTILE_SECRET_KEY, turnstileToken);
if (!isHuman) {
- captureFailedSignup(email, name);
throw new UnknownError("reCAPTCHA verification failed");
}
}
@@ -180,7 +174,7 @@ export const createUserAction = actionClient.schema(ZCreateUserAction).action(
"user",
async ({ ctx, parsedInput }: { ctx: ActionClientCtx; parsedInput: Record }) => {
await applyIPRateLimit(rateLimitConfigs.auth.signup);
- await verifyTurnstileIfConfigured(parsedInput.turnstileToken, parsedInput.email, parsedInput.name);
+ await verifyTurnstileIfConfigured(parsedInput.turnstileToken);
const hashedPassword = await hashPassword(parsedInput.password);
const { user, userAlreadyExisted } = await createUserSafely(
diff --git a/apps/web/modules/auth/signup/components/signup-form.tsx b/apps/web/modules/auth/signup/components/signup-form.tsx
index 78bb6add4f..0aa419892e 100644
--- a/apps/web/modules/auth/signup/components/signup-form.tsx
+++ b/apps/web/modules/auth/signup/components/signup-form.tsx
@@ -13,7 +13,6 @@ import { TUserLocale, ZUserName, ZUserPassword } from "@formbricks/types/user";
import { getFormattedErrorMessage } from "@/lib/utils/helper";
import { createUserAction } from "@/modules/auth/signup/actions";
import { TermsPrivacyLinks } from "@/modules/auth/signup/components/terms-privacy-links";
-import { captureFailedSignup } from "@/modules/auth/signup/lib/utils";
import { SSOOptions } from "@/modules/ee/sso/components/sso-options";
import { Button } from "@/modules/ui/components/button";
import { FormControl, FormError, FormField, FormItem } from "@/modules/ui/components/form";
@@ -236,7 +235,6 @@ export const SignupForm = ({
onError={() => {
setTurnstileToken(undefined);
toast.error(t("auth.signup.captcha_failed"));
- captureFailedSignup(form.getValues("email"), form.getValues("name"));
}}
/>
)}
diff --git a/apps/web/modules/auth/signup/lib/utils.test.ts b/apps/web/modules/auth/signup/lib/utils.test.ts
index 4bf22150dd..a90e4ae93d 100644
--- a/apps/web/modules/auth/signup/lib/utils.test.ts
+++ b/apps/web/modules/auth/signup/lib/utils.test.ts
@@ -1,6 +1,5 @@
-import posthog from "posthog-js";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
-import { captureFailedSignup, verifyTurnstileToken } from "./utils";
+import { verifyTurnstileToken } from "./utils";
beforeEach(() => {
global.fetch = vi.fn();
@@ -62,18 +61,3 @@ describe("verifyTurnstileToken", () => {
expect(result).toBe(false);
});
});
-
-describe("captureFailedSignup", () => {
- test("should capture TELEMETRY_FAILED_SIGNUP event with email and name", () => {
- const captureSpy = vi.spyOn(posthog, "capture");
- const email = "test@example.com";
- const name = "Test User";
-
- captureFailedSignup(email, name);
-
- expect(captureSpy).toHaveBeenCalledWith("TELEMETRY_FAILED_SIGNUP", {
- email,
- name,
- });
- });
-});
diff --git a/apps/web/modules/auth/signup/lib/utils.ts b/apps/web/modules/auth/signup/lib/utils.ts
index 56356fa767..41b3e5583b 100644
--- a/apps/web/modules/auth/signup/lib/utils.ts
+++ b/apps/web/modules/auth/signup/lib/utils.ts
@@ -1,5 +1,3 @@
-import posthog from "posthog-js";
-
export const verifyTurnstileToken = async (secretKey: string, token: string): Promise => {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000);
@@ -29,10 +27,3 @@ export const verifyTurnstileToken = async (secretKey: string, token: string): Pr
clearTimeout(timeoutId);
}
};
-
-export const captureFailedSignup = (email: string, name: string) => {
- posthog.capture("TELEMETRY_FAILED_SIGNUP", {
- email,
- name,
- });
-};
diff --git a/apps/web/modules/ee/contacts/lib/contacts.test.ts b/apps/web/modules/ee/contacts/lib/contacts.test.ts
index b32374a844..5d26c0be74 100644
--- a/apps/web/modules/ee/contacts/lib/contacts.test.ts
+++ b/apps/web/modules/ee/contacts/lib/contacts.test.ts
@@ -56,9 +56,6 @@ vi.mock("@/lib/constants", () => ({
ITEMS_PER_PAGE: 2,
ENCRYPTION_KEY: "test-encryption-key-32-chars-long!",
IS_PRODUCTION: false,
- IS_POSTHOG_CONFIGURED: false,
- POSTHOG_API_HOST: "test-posthog-host",
- POSTHOG_API_KEY: "test-posthog-key",
}));
const environmentId = "cm123456789012345678901237";
diff --git a/apps/web/modules/survey/components/template-list/lib/survey.test.ts b/apps/web/modules/survey/components/template-list/lib/survey.test.ts
index 000f600e4f..b2cc637127 100644
--- a/apps/web/modules/survey/components/template-list/lib/survey.test.ts
+++ b/apps/web/modules/survey/components/template-list/lib/survey.test.ts
@@ -9,16 +9,11 @@ import {
getOrganizationByEnvironmentId,
subscribeOrganizationMembersToSurveyResponses,
} from "@/lib/organization/service";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { getActionClasses } from "@/modules/survey/lib/action-class";
import { selectSurvey } from "@/modules/survey/lib/survey";
import { createSurvey, handleTriggerUpdates } from "./survey";
// Mock dependencies
-vi.mock("@/lib/posthogServer", () => ({
- capturePosthogEnvironmentEvent: vi.fn(),
-}));
-
vi.mock("@/lib/survey/utils", () => ({
checkForInvalidImagesInQuestions: vi.fn(),
}));
@@ -121,11 +116,6 @@ describe("survey module", () => {
"user-123",
"org-123"
);
- expect(capturePosthogEnvironmentEvent).toHaveBeenCalledWith(
- environmentId,
- "survey created",
- expect.objectContaining({ surveyId: "survey-123" })
- );
expect(result).toBeDefined();
expect(result.id).toBe("survey-123");
});
diff --git a/apps/web/modules/survey/components/template-list/lib/survey.ts b/apps/web/modules/survey/components/template-list/lib/survey.ts
index df3c4a3b7d..af550254ef 100644
--- a/apps/web/modules/survey/components/template-list/lib/survey.ts
+++ b/apps/web/modules/survey/components/template-list/lib/survey.ts
@@ -7,7 +7,6 @@ import {
getOrganizationByEnvironmentId,
subscribeOrganizationMembersToSurveyResponses,
} from "@/lib/organization/service";
-import { capturePosthogEnvironmentEvent } from "@/lib/posthogServer";
import { checkForInvalidImagesInQuestions } from "@/lib/survey/utils";
import { TriggerUpdate } from "@/modules/survey/editor/types/survey-trigger";
import { getActionClasses } from "@/modules/survey/lib/action-class";
@@ -122,11 +121,6 @@ export const createSurvey = async (
await subscribeOrganizationMembersToSurveyResponses(survey.id, createdBy, organization.id);
}
- await capturePosthogEnvironmentEvent(survey.environmentId, "survey created", {
- surveyId: survey.id,
- surveyType: survey.type,
- });
-
return transformedSurvey;
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
diff --git a/apps/web/modules/ui/components/environmentId-base-layout/index.tsx b/apps/web/modules/ui/components/environmentId-base-layout/index.tsx
deleted file mode 100644
index 0c32b14128..0000000000
--- a/apps/web/modules/ui/components/environmentId-base-layout/index.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { Session } from "next-auth";
-import { TOrganization } from "@formbricks/types/organizations";
-import { TUser } from "@formbricks/types/user";
-import { PosthogIdentify } from "@/app/(app)/environments/[environmentId]/components/PosthogIdentify";
-import { ResponseFilterProvider } from "@/app/(app)/environments/[environmentId]/components/ResponseFilterContext";
-import { IS_POSTHOG_CONFIGURED } from "@/lib/constants";
-import { ToasterClient } from "@/modules/ui/components/toaster-client";
-
-interface EnvironmentIdBaseLayoutProps {
- children: React.ReactNode;
- environmentId: string;
- session: Session;
- user: TUser;
- organization: TOrganization;
-}
-
-export const EnvironmentIdBaseLayout = async ({
- children,
- environmentId,
- session,
- user,
- organization,
-}: EnvironmentIdBaseLayoutProps) => {
- return (
-
-
-
- {children}
-
- );
-};
diff --git a/apps/web/modules/ui/components/post-hog-client/index.tsx b/apps/web/modules/ui/components/post-hog-client/index.tsx
deleted file mode 100644
index 17e51e5f88..0000000000
--- a/apps/web/modules/ui/components/post-hog-client/index.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-"use client";
-
-import { usePathname, useSearchParams } from "next/navigation";
-import posthog from "posthog-js";
-import { PostHogProvider } from "posthog-js/react";
-import React, { type JSX, useEffect } from "react";
-
-interface PostHogPageviewProps {
- posthogEnabled: boolean;
- postHogApiHost?: string;
- postHogApiKey?: string;
-}
-
-export const PostHogPageview = ({
- posthogEnabled,
- postHogApiHost,
- postHogApiKey,
-}: PostHogPageviewProps): JSX.Element => {
- const pathname = usePathname();
- const searchParams = useSearchParams();
-
- useEffect(() => {
- if (!posthogEnabled) return;
- try {
- if (!postHogApiHost) {
- throw new Error("Posthog API host is required");
- }
- if (!postHogApiKey) {
- throw new Error("Posthog key is required");
- }
- posthog.init(postHogApiKey, { api_host: postHogApiHost });
- } catch (error) {
- console.error("Failed to initialize PostHog:", error);
- }
- }, []);
-
- useEffect(() => {
- if (!posthogEnabled) return;
- let url = window.origin + pathname;
- if (searchParams?.toString()) {
- url += `?${searchParams.toString()}`;
- }
- posthog.capture("$pageview", { $current_url: url });
- }, [pathname, searchParams, posthogEnabled]);
-
- return <>>;
-};
-
-interface PHPProviderProps {
- children: React.ReactNode;
- posthogEnabled: boolean;
-}
-
-export const PHProvider = ({ children, posthogEnabled }: PHPProviderProps) => {
- return posthogEnabled ? {children} : children;
-};
diff --git a/apps/web/package.json b/apps/web/package.json
index 9cbc965a32..9dbad18c9e 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -108,8 +108,6 @@
"nodemailer": "7.0.9",
"otplib": "12.0.1",
"papaparse": "5.5.2",
- "posthog-js": "1.240.0",
- "posthog-node": "5.9.2",
"prismjs": "1.30.0",
"qr-code-styling": "1.9.2",
"qrcode": "1.5.4",
diff --git a/apps/web/vite.config.mts b/apps/web/vite.config.mts
index 146edb9165..d116d321ac 100644
--- a/apps/web/vite.config.mts
+++ b/apps/web/vite.config.mts
@@ -57,7 +57,6 @@ export default defineConfig({
"**/actions.ts", // Server actions (plural)
"**/action.ts", // Server actions (singular)
"lib/env.ts", // Environment configuration
- "lib/posthogServer.ts", // PostHog server integration
"**/cache.ts", // Cache files
"**/cache/**", // Cache directories
diff --git a/apps/web/vitestSetup.ts b/apps/web/vitestSetup.ts
index 1ef491ed4c..fca5228acc 100644
--- a/apps/web/vitestSetup.ts
+++ b/apps/web/vitestSetup.ts
@@ -186,9 +186,6 @@ export const testInputValidation = async (service: Function, ...args: any[]): Pr
vi.mock("@/lib/constants", () => ({
IS_FORMBRICKS_CLOUD: false,
- POSTHOG_API_KEY: "mock-posthog-api-key",
- POSTHOG_HOST: "mock-posthog-host",
- IS_POSTHOG_CONFIGURED: true,
ENCRYPTION_KEY: "mock-encryption-key",
ENTERPRISE_LICENSE_KEY: "mock-enterprise-license-key",
GITHUB_ID: "mock-github-id",
diff --git a/docs/self-hosting/configuration/environment-variables.mdx b/docs/self-hosting/configuration/environment-variables.mdx
index 2267c017a3..11fb451651 100644
--- a/docs/self-hosting/configuration/environment-variables.mdx
+++ b/docs/self-hosting/configuration/environment-variables.mdx
@@ -52,7 +52,6 @@ These variables are present inside your machine's docker-compose file. Restart t
| GOOGLE_CLIENT_SECRET | Secret for Google. | optional (required if Google auth is enabled) | |
| STRIPE_SECRET_KEY | Secret key for Stripe integration. | optional | |
| STRIPE_WEBHOOK_SECRET | Webhook secret for Stripe integration. | optional | |
-| TELEMETRY_DISABLED | Disables telemetry if set to 1. | optional | |
| DEFAULT_BRAND_COLOR | Default brand color for your app (Can be overwritten from the UI as well). | optional | #64748b |
| DEFAULT_ORGANIZATION_ID | Automatically assign new users to a specific organization when joining | optional | |
| OIDC_DISPLAY_NAME | Display name for Custom OpenID Connect Provider | optional | |
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 43b9164032..75e542eb05 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -377,12 +377,6 @@ importers:
papaparse:
specifier: 5.5.2
version: 5.5.2
- posthog-js:
- specifier: 1.240.0
- version: 1.240.0
- posthog-node:
- specifier: 5.9.2
- version: 5.9.2
prismjs:
specifier: 1.30.0
version: 1.30.0
@@ -2882,9 +2876,6 @@ packages:
engines: {node: '>=18'}
hasBin: true
- '@posthog/core@1.2.2':
- resolution: {integrity: sha512-f16Ozx6LIigRG+HsJdt+7kgSxZTHeX5f1JlCGKI1lXcvlZgfsCR338FuMI2QRYXGl+jg/vYFzGOTQBxl90lnBg==}
-
'@preact/preset-vite@2.10.1':
resolution: {integrity: sha512-59lyGBXNfZIr5OOuBUB4/IB8AqF/ULbvYnyItgK/2BJnsGJqaeaJobRVtMp1129obHQuj8oZ/dVxB9inmH8Xig==}
peerDependencies:
@@ -5687,9 +5678,6 @@ packages:
core-js-compat@3.46.0:
resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==}
- core-js@3.46.0:
- resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==}
-
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -6462,9 +6450,6 @@ packages:
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
engines: {node: ^12.20 || >= 14.13}
- fflate@0.4.8:
- resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==}
-
fflate@0.7.4:
resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==}
@@ -8246,21 +8231,6 @@ packages:
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
engines: {node: '>=0.10.0'}
- posthog-js@1.240.0:
- resolution: {integrity: sha512-zZhedVycGracBMWVRvWJMkB2EiB/dUoe/eM+CsFCnda/PN3Se+V7a6CLGuLZKLF9EfHswCxxU/PIxgDrhbAgjQ==}
- peerDependencies:
- '@rrweb/types': 2.0.0-alpha.17
- rrweb-snapshot: 2.0.0-alpha.17
- peerDependenciesMeta:
- '@rrweb/types':
- optional: true
- rrweb-snapshot:
- optional: true
-
- posthog-node@5.9.2:
- resolution: {integrity: sha512-oU7FbFcH5cn40nhP04cBeT67zE76EiGWjKKzDvm6IOm5P83sqM0Ij0wMJQSHp+QI6ZN7MLzb+4xfMPUEZ4q6CA==}
- engines: {node: '>=20'}
-
preact-render-to-string@5.2.6:
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
peerDependencies:
@@ -9838,9 +9808,6 @@ packages:
resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==}
engines: {node: '>= 8'}
- web-vitals@4.2.4:
- resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==}
-
webidl-conversions@3.0.1:
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
@@ -13121,8 +13088,6 @@ snapshots:
dependencies:
playwright: 1.56.1
- '@posthog/core@1.2.2': {}
-
'@preact/preset-vite@2.10.1(@babel/core@7.28.5)(preact@10.26.6)(vite@6.4.1(@types/node@22.15.18)(jiti@2.4.2)(terser@5.39.1)(tsx@4.19.4)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.5
@@ -16287,8 +16252,6 @@ snapshots:
dependencies:
browserslist: 4.27.0
- core-js@3.46.0: {}
-
core-util-is@1.0.3: {}
create-require@1.1.1: {}
@@ -17251,8 +17214,6 @@ snapshots:
node-domexception: 1.0.0
web-streams-polyfill: 3.3.3
- fflate@0.4.8: {}
-
fflate@0.7.4: {}
file-entry-cache@6.0.1:
@@ -19128,17 +19089,6 @@ snapshots:
dependencies:
xtend: 4.0.2
- posthog-js@1.240.0:
- dependencies:
- core-js: 3.46.0
- fflate: 0.4.8
- preact: 10.26.6
- web-vitals: 4.2.4
-
- posthog-node@5.9.2:
- dependencies:
- '@posthog/core': 1.2.2
-
preact-render-to-string@5.2.6(preact@10.26.6):
dependencies:
preact: 10.26.6
@@ -20863,8 +20813,6 @@ snapshots:
web-streams-polyfill@3.3.3: {}
- web-vitals@4.2.4: {}
-
webidl-conversions@3.0.1: {}
webidl-conversions@7.0.0: {}
diff --git a/sonar-project.properties b/sonar-project.properties
index 70a5b4d84f..1f710fd0c7 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -21,5 +21,5 @@ sonar.scm.exclusions.disabled=false
sonar.sourceEncoding=UTF-8
# Coverage
-sonar.coverage.exclusions=**/*.test.*,**/*.spec.*,**/*.tsx,**/*.mdx,**/*.config.mts,**/*.config.ts,**/constants.ts,**/route.ts,**/route.tsx,**/types/**,**/types.ts,**/stories.*,**/*.mock.*,**/mocks/**,**/__mocks__/**,**/openapi.ts,**/openapi-document.ts,**/instrumentation.ts,scripts/openapi/merge-client-endpoints.ts,**/playwright/**,**/Dockerfile,**/*.config.cjs,**/*.css,**/templates.ts,**/actions.ts,apps/web/modules/ui/components/icons/*,**/*.json,apps/web/vitestSetup.ts,packages/js-core/src/index.ts,apps/web/tailwind.config.js,apps/web/postcss.config.js,apps/web/next.config.mjs,apps/web/scripts/**,packages/js-core/vitest.setup.ts,**/*.mjs,apps/web/modules/auth/lib/mock-data.ts,**/cache.ts,apps/web/app/**/billing-confirmation/**,apps/web/modules/ee/billing/**,apps/web/modules/ee/multi-language-surveys/**,apps/web/modules/email/**,apps/web/modules/integrations/**,apps/web/modules/setup/**/intro/**,apps/web/modules/setup/**/signup/**,apps/web/modules/setup/**/layout.tsx,apps/web/modules/survey/follow-ups/**,apps/web/app/share/**,apps/web/modules/ee/contacts/[contactId]/**,apps/web/modules/ee/contacts/components/**,apps/web/modules/ee/two-factor-auth/**,apps/web/lib/posthogServer.ts,apps/web/lib/slack/**,apps/web/lib/notion/**,apps/web/lib/googleSheet/**,apps/web/app/api/google-sheet/**,apps/web/app/api/billing/**,apps/web/lib/airtable/**,apps/web/app/api/v1/integrations/**,apps/web/lib/env.ts,**/instrumentation-node.ts,**/cache/**,**/*.svg,apps/web/modules/ui/components/icons/**,apps/web/modules/ui/components/table/**
-sonar.cpd.exclusions=**/*.test.*,**/*.spec.*,**/*.tsx,**/*.mdx,**/*.config.mts,**/*.config.ts,**/constants.ts,**/route.ts,**/route.tsx,**/types/**,**/types.ts,**/stories.*,**/*.mock.*,**/mocks/**,**/__mocks__/**,**/openapi.ts,**/openapi-document.ts,**/instrumentation.ts,scripts/openapi/merge-client-endpoints.ts,**/playwright/**,**/Dockerfile,**/*.config.cjs,**/*.css,**/templates.ts,**/actions.ts,apps/web/modules/ui/components/icons/*,**/*.json,apps/web/vitestSetup.ts,apps/web/tailwind.config.js,apps/web/postcss.config.js,apps/web/next.config.mjs,apps/web/scripts/**,packages/js-core/vitest.setup.ts,packages/js-core/src/index.ts,**/*.mjs,apps/web/modules/auth/lib/mock-data.ts,**/cache.ts,apps/web/app/**/billing-confirmation/**,apps/web/modules/ee/billing/**,apps/web/modules/ee/multi-language-surveys/**,apps/web/modules/email/**,apps/web/modules/integrations/**,apps/web/modules/setup/**/intro/**,apps/web/modules/setup/**/signup/**,apps/web/modules/setup/**/layout.tsx,apps/web/modules/survey/follow-ups/**,apps/web/app/share/**,apps/web/modules/ee/contacts/[contactId]/**,apps/web/modules/ee/contacts/components/**,apps/web/modules/ee/two-factor-auth/**,apps/web/lib/posthogServer.ts,apps/web/lib/slack/**,apps/web/lib/notion/**,apps/web/lib/googleSheet/**,apps/web/app/api/google-sheet/**,apps/web/app/api/billing/**,apps/web/lib/airtable/**,apps/web/app/api/v1/integrations/**,apps/web/lib/env.ts,**/instrumentation-node.ts,**/cache/**,**/*.svg,apps/web/modules/ui/components/icons/**,apps/web/modules/ui/components/table/**
+sonar.coverage.exclusions=**/*.test.*,**/*.spec.*,**/*.tsx,**/*.mdx,**/*.config.mts,**/*.config.ts,**/constants.ts,**/route.ts,**/route.tsx,**/types/**,**/types.ts,**/stories.*,**/*.mock.*,**/mocks/**,**/__mocks__/**,**/openapi.ts,**/openapi-document.ts,**/instrumentation.ts,scripts/openapi/merge-client-endpoints.ts,**/playwright/**,**/Dockerfile,**/*.config.cjs,**/*.css,**/templates.ts,**/actions.ts,apps/web/modules/ui/components/icons/*,**/*.json,apps/web/vitestSetup.ts,packages/js-core/src/index.ts,apps/web/tailwind.config.js,apps/web/postcss.config.js,apps/web/next.config.mjs,apps/web/scripts/**,packages/js-core/vitest.setup.ts,**/*.mjs,apps/web/modules/auth/lib/mock-data.ts,**/cache.ts,apps/web/app/**/billing-confirmation/**,apps/web/modules/ee/billing/**,apps/web/modules/ee/multi-language-surveys/**,apps/web/modules/email/**,apps/web/modules/integrations/**,apps/web/modules/setup/**/intro/**,apps/web/modules/setup/**/signup/**,apps/web/modules/setup/**/layout.tsx,apps/web/modules/survey/follow-ups/**,apps/web/app/share/**,apps/web/modules/ee/contacts/[contactId]/**,apps/web/modules/ee/contacts/components/**,apps/web/modules/ee/two-factor-auth/**,apps/web/lib/slack/**,apps/web/lib/notion/**,apps/web/lib/googleSheet/**,apps/web/app/api/google-sheet/**,apps/web/app/api/billing/**,apps/web/lib/airtable/**,apps/web/app/api/v1/integrations/**,apps/web/lib/env.ts,**/instrumentation-node.ts,**/cache/**,**/*.svg,apps/web/modules/ui/components/icons/**,apps/web/modules/ui/components/table/**
+sonar.cpd.exclusions=**/*.test.*,**/*.spec.*,**/*.tsx,**/*.mdx,**/*.config.mts,**/*.config.ts,**/constants.ts,**/route.ts,**/route.tsx,**/types/**,**/types.ts,**/stories.*,**/*.mock.*,**/mocks/**,**/__mocks__/**,**/openapi.ts,**/openapi-document.ts,**/instrumentation.ts,scripts/openapi/merge-client-endpoints.ts,**/playwright/**,**/Dockerfile,**/*.config.cjs,**/*.css,**/templates.ts,**/actions.ts,apps/web/modules/ui/components/icons/*,**/*.json,apps/web/vitestSetup.ts,apps/web/tailwind.config.js,apps/web/postcss.config.js,apps/web/next.config.mjs,apps/web/scripts/**,packages/js-core/vitest.setup.ts,packages/js-core/src/index.ts,**/*.mjs,apps/web/modules/auth/lib/mock-data.ts,**/cache.ts,apps/web/app/**/billing-confirmation/**,apps/web/modules/ee/billing/**,apps/web/modules/ee/multi-language-surveys/**,apps/web/modules/email/**,apps/web/modules/integrations/**,apps/web/modules/setup/**/intro/**,apps/web/modules/setup/**/signup/**,apps/web/modules/setup/**/layout.tsx,apps/web/modules/survey/follow-ups/**,apps/web/app/share/**,apps/web/modules/ee/contacts/[contactId]/**,apps/web/modules/ee/contacts/components/**,apps/web/modules/ee/two-factor-auth/**,apps/web/lib/slack/**,apps/web/lib/notion/**,apps/web/lib/googleSheet/**,apps/web/app/api/google-sheet/**,apps/web/app/api/billing/**,apps/web/lib/airtable/**,apps/web/app/api/v1/integrations/**,apps/web/lib/env.ts,**/instrumentation-node.ts,**/cache/**,**/*.svg,apps/web/modules/ui/components/icons/**,apps/web/modules/ui/components/table/**
diff --git a/turbo.json b/turbo.json
index 356b7e0d38..3178a6b024 100644
--- a/turbo.json
+++ b/turbo.json
@@ -172,8 +172,6 @@
"OIDC_SIGNING_ALGORITHM",
"PASSWORD_RESET_DISABLED",
"PLAYWRIGHT_CI",
- "POSTHOG_API_HOST",
- "POSTHOG_API_KEY",
"PRIVACY_URL",
"RATE_LIMITING_DISABLED",
"REDIS_URL",
@@ -203,7 +201,6 @@
"SURVEYS_PACKAGE_MODE",
"SURVEYS_PACKAGE_BUILD",
"PUBLIC_URL",
- "TELEMETRY_DISABLED",
"TURNSTILE_SECRET_KEY",
"TURNSTILE_SITE_KEY",
"RECAPTCHA_SITE_KEY",