chore: Remove MetricsWave tracking integration

MetricsWave visit tracker, event webhooks, and all funnel tracking
(lead, onboarding, import) are no longer needed.
This commit is contained in:
Víctor Falcón 2026-02-07 18:53:21 +01:00
parent e81c4345a0
commit 1c425da330
8 changed files with 4 additions and 173 deletions

View File

@ -6,7 +6,6 @@ use App\Http\Requests\StoreUserLeadRequest;
use App\Models\UserLead;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Http;
class UserLeadController extends Controller
{
@ -18,8 +17,6 @@ class UserLeadController extends Controller
$validated = $request->validated();
$lead = UserLead::create($validated);
$this->trackLeadCreatedEvent($validated['email']);
$redirectUrl = config('landing.lead_redirect_url');
if ($redirectUrl) {
@ -30,19 +27,4 @@ class UserLeadController extends Controller
return to_route('home')->with('success', 'Thank you for your interest!');
}
protected function trackLeadCreatedEvent(string $email): void
{
$eventUuid = config('landing.lead_funnel_event_uuid');
if (! $eventUuid || app()->environment('local', 'testing')) {
return;
}
Http::withoutVerifying()
->timeout(5)
->post("https://metricswave.com/webhooks/{$eventUuid}", [
'step' => 'Lead Created',
]);
}
}

View File

@ -26,15 +26,4 @@ return [
'lead_redirect_url' => env('LEAD_REDIRECT_URL', null),
/*
|--------------------------------------------------------------------------
| Lead Funnel Event UUID
|--------------------------------------------------------------------------
|
| The MetricsWave event UUID for tracking lead funnel events.
|
*/
'lead_funnel_event_uuid' => env('LEAD_FUNNEL_EVENT_UUID', '9668a06c-dee9-47a8-9bee-eaaa2a3a5915'),
];

View File

@ -9,7 +9,6 @@ import {
} from '@/components/ui/drawer';
import { Progress } from '@/components/ui/progress';
import { useEncryptionKey } from '@/contexts/encryption-key-context';
import { IMPORT_FUNNEL_EVENT_UUID } from '@/lib/constants';
import { importKey } from '@/lib/crypto';
import {
autoDetectColumns,
@ -22,7 +21,6 @@ import {
} from '@/lib/import-config-storage';
import { getStoredKey } from '@/lib/key-storage';
import { evaluateRulesForNewTransaction } from '@/lib/rule-engine';
import { useTrackEvent } from '@/lib/track-event';
import { transactionSyncService } from '@/services/transaction-sync';
import { type Account, type Bank } from '@/types/account';
import { type AutomationRule } from '@/types/automation-rule';
@ -34,7 +32,7 @@ import {
type ImportState,
} from '@/types/import';
import { router } from '@inertiajs/react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
import { toast } from 'sonner';
import { ImportStepAccount } from './import-step-account';
import { ImportStepMapping } from './import-step-mapping';
@ -61,14 +59,6 @@ interface ImportError {
error: string;
}
type ImportFunnelStep =
| 'Open'
| 'Choose account'
| 'Set file'
| 'Set mapping'
| 'Confirm Preview'
| 'Finish';
export function ImportTransactionsDrawer({
accounts = [],
categories = [],
@ -79,8 +69,6 @@ export function ImportTransactionsDrawer({
onImportComplete,
}: ImportTransactionsDrawerProps) {
const { isKeySet } = useEncryptionKey();
const trackEvent = useTrackEvent();
const trackedStepsRef = useRef<Set<ImportFunnelStep>>(new Set());
const [isImporting, setIsImporting] = useState(false);
const [importProgress, setImportProgress] = useState(0);
const [importTotal, setImportTotal] = useState(0);
@ -117,20 +105,8 @@ export function ImportTransactionsDrawer({
}
}, [state.selectedAccountId, accounts]);
const trackFunnelStep = useCallback(
(step: ImportFunnelStep) => {
if (!trackedStepsRef.current.has(step)) {
trackedStepsRef.current.add(step);
trackEvent(IMPORT_FUNNEL_EVENT_UUID, { step });
}
},
[trackEvent],
);
useEffect(() => {
if (open) {
trackFunnelStep('Open');
} else {
if (!open) {
setState({
step: ImportStep.SelectAccount,
selectedAccountId: null,
@ -150,9 +126,8 @@ export function ImportTransactionsDrawer({
setIsImporting(false);
setError(null);
setSelectedAccount(null);
trackedStepsRef.current.clear();
}
}, [open, trackFunnelStep]);
}, [open]);
const handleAccountSelect = (accountId: number) => {
setState((prev) => ({ ...prev, selectedAccountId: accountId }));
@ -322,7 +297,6 @@ export function ImportTransactionsDrawer({
transactions: transactionsWithDuplicateCheck,
step: ImportStep.Preview,
}));
trackFunnelStep('Set mapping');
} catch (err) {
setError(
err instanceof Error
@ -333,8 +307,6 @@ export function ImportTransactionsDrawer({
};
const handleConfirmImport = async () => {
trackFunnelStep('Confirm Preview');
if (!isKeySet) {
setError('Please unlock your encryption key first');
return;
@ -535,10 +507,6 @@ export function ImportTransactionsDrawer({
console.log('Import complete:', { successCount, errorCount, total });
if (successCount > 0) {
trackFunnelStep('Finish');
}
if (errorCount === 0 && successCount > 0) {
const message =
uncategorizedCount > 0
@ -675,7 +643,6 @@ export function ImportTransactionsDrawer({
selectedAccountId={state.selectedAccountId}
onAccountSelect={handleAccountSelect}
onNext={() => {
trackFunnelStep('Choose account');
moveToStep(ImportStep.UploadFile);
}}
/>
@ -686,7 +653,6 @@ export function ImportTransactionsDrawer({
file={state.file}
onFileSelect={handleFileSelect}
onNext={() => {
trackFunnelStep('Set file');
moveToStep(ImportStep.MapColumns);
}}
onBack={() => moveToStep(ImportStep.SelectAccount)}

View File

@ -1,4 +0,0 @@
export const LEAD_FUNNEL_EVENT_UUID = '9668a06c-dee9-47a8-9bee-eaaa2a3a5915';
export const IMPORT_FUNNEL_EVENT_UUID = 'eea25dce-75ef-4959-b975-a7e9094b3ef5';
export const ONBOARDING_FUNNEL_EVENT_UUID =
'8a10c1da-080b-44cc-8dcf-78734b29106c';

View File

@ -1,74 +0,0 @@
import type { SharedData } from '@/types';
import { usePage } from '@inertiajs/react';
export interface TrackEventPayload {
step: string;
user_id?: string | number;
[key: string]: unknown;
}
export interface TrackEventOptions {
method?: 'GET' | 'POST';
}
function isLocalEnvironment(): boolean {
if (typeof window === 'undefined') return true;
const hostname = window.location.hostname;
return hostname === 'localhost' || hostname.endsWith('.test');
}
export async function trackEvent(
eventUuid: string,
payload: TrackEventPayload,
options: TrackEventOptions = {},
): Promise<void> {
const { method = 'POST' } = options;
if (isLocalEnvironment()) {
console.log('[Track Event]', {
eventUuid,
method,
payload,
});
return;
}
const url = `https://metricswave.com/webhooks/${eventUuid}`;
if (method === 'GET') {
const queryParams = new URLSearchParams();
Object.entries(payload).forEach(([key, value]) => {
if (value !== undefined && value !== null) {
queryParams.append(key, String(value));
}
});
await fetch(`${url}?${queryParams.toString()}`, {
keepalive: true,
});
} else {
await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
keepalive: true,
});
}
}
export function useTrackEvent() {
const { auth } = usePage<SharedData>().props;
return (
eventUuid: string,
payload: Omit<TrackEventPayload, 'user_id'>,
options?: TrackEventOptions,
) => {
const finalPayload: TrackEventPayload = {
...payload,
user_id: auth?.user?.id,
};
return trackEvent(eventUuid, finalPayload, options);
};
}

View File

@ -17,8 +17,6 @@ import {
useOnboardingState,
} from '@/hooks/use-onboarding-state';
import OnboardingLayout from '@/layouts/onboarding-layout';
import { ONBOARDING_FUNNEL_EVENT_UUID } from '@/lib/constants';
import { useTrackEvent } from '@/lib/track-event';
import { type Bank } from '@/types/account';
import { Head } from '@inertiajs/react';
import { useEffect, useRef } from 'react';
@ -49,9 +47,7 @@ export default function Onboarding({
hasEncryptionSetup,
}: OnboardingProps) {
const { sync } = useSyncContext();
const trackEvent = useTrackEvent();
const hasSyncedRef = useRef(false);
const trackedStepsRef = useRef<Set<OnboardingStep>>(new Set());
// Sync banks on mount to ensure IndexedDB has the latest data
useEffect(() => {
@ -75,13 +71,6 @@ export default function Onboarding({
hasEncryptionSetup,
});
useEffect(() => {
if (!trackedStepsRef.current.has(currentStep)) {
trackedStepsRef.current.add(currentStep);
trackEvent(ONBOARDING_FUNNEL_EVENT_UUID, { step: currentStep });
}
}, [currentStep, trackEvent]);
const handleAccountCreated = async (account: CreatedAccount) => {
addCreatedAccount(account);

View File

@ -10,8 +10,6 @@ import {
TooltipTrigger,
} from '@/components/ui/tooltip';
import { usePwaInstall } from '@/hooks/use-pwa-install';
import { LEAD_FUNNEL_EVENT_UUID } from '@/lib/constants';
import { trackEvent } from '@/lib/track-event';
import { cn } from '@/lib/utils';
import { type SharedData } from '@/types';
import { Plan } from '@/types/pricing';
@ -31,7 +29,7 @@ import {
TrendingUpIcon,
ZapIcon,
} from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
const LANDING_IMAGES = [
{
@ -161,7 +159,6 @@ export default function Welcome({
const { appUrl, subscriptionsEnabled, pricing } =
usePage<SharedData>().props;
const planEntries = Object.entries(pricing.plans);
const visitTrackedRef = useRef(false);
const { isMobile } = usePwaInstall();
const [isPwa] = useState(() => {
@ -179,16 +176,7 @@ export default function Welcome({
useEffect(() => {
if (isPwa) {
router.visit('/dashboard');
return;
}
if (visitTrackedRef.current) {
return;
}
visitTrackedRef.current = true;
trackEvent(LEAD_FUNNEL_EVENT_UUID, {
step: 'Visit',
});
}, [isPwa]);
if (isPwa) {

View File

@ -58,11 +58,6 @@
<body class="font-sans antialiased">
@inertia
<script defer
event-uuid="696e6c66-33e0-482c-aa4a-a21410ec38c8"
src="https://tracker.metricswave.com/js/visits.js"
></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js', { scope: '/' });