From 52c44788a22cbc0d92a69a7425e96df02baac783 Mon Sep 17 00:00:00 2001 From: Ian Jones Date: Sat, 1 Aug 2026 18:01:22 -0600 Subject: [PATCH] Filter Instagram webview bridge errors --- apps/wodsmith-start/src/lib/posthog/client.ts | 3 ++ .../src/lib/posthog/event-filter.ts | 27 +++++++++++++ .../test/lib/posthog-event-filter.test.ts | 40 +++++++++++++++++++ lat.md/architecture.md | 6 +++ 4 files changed, 76 insertions(+) create mode 100644 apps/wodsmith-start/src/lib/posthog/event-filter.ts create mode 100644 apps/wodsmith-start/test/lib/posthog-event-filter.test.ts diff --git a/apps/wodsmith-start/src/lib/posthog/client.ts b/apps/wodsmith-start/src/lib/posthog/client.ts index 0b4868d15..3f12e9fc4 100644 --- a/apps/wodsmith-start/src/lib/posthog/client.ts +++ b/apps/wodsmith-start/src/lib/posthog/client.ts @@ -1,5 +1,7 @@ import posthog from "posthog-js" +import { filterPostHogEvent } from "./event-filter" + const POSTHOG_KEY = import.meta.env.VITE_POSTHOG_KEY || "phc_UCtCVOUXvpuKzF50prCLKIWWCFc61j5CPTbt99OrKsK" @@ -41,6 +43,7 @@ export function initPostHog(): void { ui_host: "https://us.posthog.com", // Match Next.js app settings defaults: "2025-05-24", + before_send: filterPostHogEvent, capture_exceptions: true, debug: false, // We'll handle pageviews manually with router integration diff --git a/apps/wodsmith-start/src/lib/posthog/event-filter.ts b/apps/wodsmith-start/src/lib/posthog/event-filter.ts new file mode 100644 index 000000000..991b97953 --- /dev/null +++ b/apps/wodsmith-start/src/lib/posthog/event-filter.ts @@ -0,0 +1,27 @@ +import type { CaptureResult } from "posthog-js" + +const INSTAGRAM_WEBVIEW_BRIDGE = "window.webkit.messageHandlers" + +/** + * Drop errors from Instagram's injected iOS webview bridge while preserving + * application exceptions and every other PostHog event. + */ +// @lat: [[architecture#Client Error Filtering]] +export function filterPostHogEvent( + event: CaptureResult | null, +): CaptureResult | null { + if (event?.event !== "$exception") { + return event + } + + const exceptionList = event.properties.$exception_list + const isInstagramBridgeError = + Array.isArray(exceptionList) && + exceptionList.some( + (exception) => + typeof exception?.value === "string" && + exception.value.includes(INSTAGRAM_WEBVIEW_BRIDGE), + ) + + return isInstagramBridgeError ? null : event +} diff --git a/apps/wodsmith-start/test/lib/posthog-event-filter.test.ts b/apps/wodsmith-start/test/lib/posthog-event-filter.test.ts new file mode 100644 index 000000000..b5043e21c --- /dev/null +++ b/apps/wodsmith-start/test/lib/posthog-event-filter.test.ts @@ -0,0 +1,40 @@ +import type { CaptureResult } from "posthog-js" +import { describe, expect, it } from "vitest" + +import { filterPostHogEvent } from "@/lib/posthog/event-filter" + +function exceptionEvent(value: string): CaptureResult { + return { + uuid: "exception-event-id", + event: "$exception", + properties: { + $exception_list: [{ type: "TypeError", value }], + }, + } +} + +describe("filterPostHogEvent", () => { + it("drops the broken Instagram iOS webview bridge exception", () => { + const event = exceptionEvent( + "undefined is not an object (evaluating 'window.webkit.messageHandlers')", + ) + + expect(filterPostHogEvent(event)).toBeNull() + }) + + it("preserves unrelated exceptions", () => { + const event = exceptionEvent("Something in the application failed") + + expect(filterPostHogEvent(event)).toBe(event) + }) + + it("preserves non-exception events", () => { + const event: CaptureResult = { + uuid: "pageview-event-id", + event: "$pageview", + properties: {}, + } + + expect(filterPostHogEvent(event)).toBe(event) + }) +}) diff --git a/lat.md/architecture.md b/lat.md/architecture.md index cca333b00..bac871cd6 100644 --- a/lat.md/architecture.md +++ b/lat.md/architecture.md @@ -15,6 +15,12 @@ TanStack Start (React + Vite) deployed to Cloudflare Workers, with PlanetScale ( - **Deployment**: Alchemy IaC to Cloudflare Workers, Vite build pipeline - **Testing**: Vitest (unit/integration), Playwright (E2E), Testing Library (components) +## Client Error Filtering + +Client error capture excludes known browser-injected failures while preserving application exceptions and analytics events. + +[[apps/wodsmith-start/src/lib/posthog/event-filter.ts#filterPostHogEvent]] drops only PostHog `$exception` events containing `window.webkit.messageHandlers`. Instagram's iOS in-app browser injects this broken native bridge; the string does not occur in WODsmith application source. Other exceptions and non-exception events pass through unchanged. + ## Monorepo Structure The monorepo uses Turborepo with pnpm workspaces. The main app lives in `apps/wodsmith-start/`.