From aab6798b29cd38845bac39e64b77e4650f2173ff Mon Sep 17 00:00:00 2001 From: Johannes <72809645+jobenjada@users.noreply.github.com> Date: Tue, 25 Nov 2025 04:57:43 -0800 Subject: [PATCH] chore: Remove old telemetry & usage tracking (#6844) Co-authored-by: Matti Nannt --- .cursor/rules/database.mdc | 9 +-- .cursor/rules/performance-optimization.mdc | 5 -- .cursor/rules/react-context-providers.mdc | 5 -- .github/workflows/e2e.yml | 1 - .../organizations/[organizationId]/layout.tsx | 10 --- .../environments/[environmentId]/layout.tsx | 15 +--- .../components/PosthogIdentify.tsx | 61 --------------- .../environments/[environmentId]/layout.tsx | 9 +-- .../components/response-filter-context.tsx} | 0 .../surveys/[surveyId]/(analysis)/layout.tsx | 3 +- .../responses/components/ResponsePage.tsx | 2 +- .../summary/components/SummaryList.tsx | 4 +- .../summary/components/SummaryPage.tsx | 2 +- .../[surveyId]/components/CustomFilter.tsx | 2 +- .../[surveyId]/components/ResponseFilter.tsx | 2 +- apps/web/app/(app)/layout.tsx | 20 +---- apps/web/app/api/lib/utils.ts | 34 --------- .../app/sync/[userId]/route.ts | 23 +----- .../client/[environmentId]/displays/route.ts | 2 - .../environment/lib/environmentState.test.ts | 50 ------------- .../environment/lib/environmentState.ts | 34 +-------- .../responses/lib/response.test.ts | 59 +-------------- .../[environmentId]/responses/lib/response.ts | 5 -- .../client/[environmentId]/responses/route.ts | 6 -- .../management/responses/lib/response.test.ts | 74 +------------------ .../v1/management/responses/lib/response.ts | 5 -- .../client/[environmentId]/displays/route.ts | 2 - .../responses/lib/response.test.ts | 53 +------------ .../[environmentId]/responses/lib/response.ts | 5 -- .../client/[environmentId]/responses/route.ts | 6 -- apps/web/app/lib/surveys/surveys.test.ts | 2 +- apps/web/app/lib/surveys/surveys.ts | 2 +- apps/web/lib/constants.ts | 4 - apps/web/lib/env.ts | 6 -- apps/web/lib/environment/service.ts | 5 -- apps/web/lib/posthogServer.ts | 56 -------------- apps/web/lib/survey/service.test.ts | 7 -- apps/web/lib/survey/service.ts | 6 -- apps/web/lib/telemetry.ts | 38 ---------- .../v2/management/responses/lib/response.ts | 27 +------ .../responses/lib/tests/response.test.ts | 12 --- .../webhooks/lib/tests/webhook.test.ts | 6 -- .../api/v2/management/webhooks/lib/webhook.ts | 3 - .../project-teams/lib/project-teams.ts | 3 - .../[organizationId]/teams/lib/teams.ts | 3 - .../[organizationId]/users/lib/users.ts | 5 -- apps/web/modules/auth/signup/actions.ts | 12 +-- .../auth/signup/components/signup-form.tsx | 2 - .../web/modules/auth/signup/lib/utils.test.ts | 18 +---- apps/web/modules/auth/signup/lib/utils.ts | 9 --- .../modules/ee/contacts/lib/contacts.test.ts | 3 - .../template-list/lib/survey.test.ts | 10 --- .../components/template-list/lib/survey.ts | 6 -- .../environmentId-base-layout/index.tsx | 39 ---------- .../ui/components/post-hog-client/index.tsx | 56 -------------- apps/web/package.json | 2 - apps/web/vite.config.mts | 1 - apps/web/vitestSetup.ts | 3 - .../configuration/environment-variables.mdx | 1 - pnpm-lock.yaml | 52 ------------- sonar-project.properties | 4 +- turbo.json | 3 - 62 files changed, 36 insertions(+), 878 deletions(-) delete mode 100644 .cursor/rules/performance-optimization.mdc delete mode 100644 .cursor/rules/react-context-providers.mdc delete mode 100644 apps/web/app/(app)/environments/[environmentId]/components/PosthogIdentify.tsx rename apps/web/app/(app)/environments/[environmentId]/{components/ResponseFilterContext.tsx => surveys/[surveyId]/(analysis)/components/response-filter-context.tsx} (100%) delete mode 100644 apps/web/app/api/lib/utils.ts delete mode 100644 apps/web/lib/posthogServer.ts delete mode 100644 apps/web/lib/telemetry.ts delete mode 100644 apps/web/modules/ui/components/environmentId-base-layout/index.tsx delete mode 100644 apps/web/modules/ui/components/post-hog-client/index.tsx 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 (
- {children}
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 ( - -
-
{children}
-
-
+
+
{children}
+
); }; 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",