diff --git a/README.md b/README.md index 9e9d6d0..41cb7b4 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,19 @@ export const test = withPostHogTracking(base); export const expect = baseExpect.extend(matchers); ``` +### Local Ingestion Support + +If your app uses local ingestion (e.g., proxying PostHog requests through your own server), configure the ingestion path: + +```typescript +// fixtures.ts - for local ingestion at /ph/* +export const test = withPostHogTracking(base, { + ingestPath: '/ph' +}); +``` + +This will intercept requests to `/ph/e`, `/ph/capture`, `/ph/batch`, and `/ph/s` instead of `posthog.com`. + ### Configure PostHog for Testing PostHog needs specific settings to work reliably in Playwright tests. Add these conditionally in your app: @@ -56,15 +69,24 @@ test('user signup tracking works', async ({ page }) => { ## 📖 API Reference -### `withPostHogTracking(test)` +### `withPostHogTracking(test, config?)` Extends a Playwright test instance with PostHog event tracking on the `page` fixture. +**Parameters:** +- `test`: The Playwright test instance to extend +- `config` (optional): Configuration options + - `ingestPath`: Path prefix for local ingestion (e.g., `'/ph'`). Defaults to `posthog.com` if not provided. + ```typescript import { test as base } from '@playwright/test'; import { withPostHogTracking } from 'posthog-playwright'; +// Default: intercepts posthog.com export const test = withPostHogTracking(base); + +// Local ingestion: intercepts /ph/* +export const test = withPostHogTracking(base, { ingestPath: '/ph' }); ``` Works with already-extended tests too: @@ -77,7 +99,7 @@ const testWithAuth = base.extend({ }, }); -export const test = withPostHogTracking(testWithAuth); +export const test = withPostHogTracking(testWithAuth, { ingestPath: '/ph' }); ``` ### `matchers` diff --git a/examples/example.spec.ts b/examples/example.spec.ts index 05923d6..b6f56ab 100644 --- a/examples/example.spec.ts +++ b/examples/example.spec.ts @@ -9,7 +9,12 @@ import { test as base, expect as baseExpect } from '@playwright/test'; import { withPostHogTracking, matchers } from 'posthog-playwright'; // Setup: extend your test with PostHog tracking +// Default: intercepts requests to posthog.com const test = withPostHogTracking(base); + +// For local ingestion (e.g., /ph/*, /api/posthog/*, etc.): +// const test = withPostHogTracking(base, { ingestPath: '/ph' }); + const expect = baseExpect.extend(matchers); test.describe('PostHog Analytics Tracking', () => { diff --git a/src/index.ts b/src/index.ts index 341b052..49e1490 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,18 +9,43 @@ export type HogPage = Page & { [kHogEvents]: CapturedEvent[]; }; -const posthogIngestPattern = /posthog\.com\/(e|capture|batch|s)(\/|$|\?)/; +export interface PostHogTrackingConfig { + /** + * Custom path prefix for local ingestion (e.g., '/ph' will match /ph/e, /ph/capture, etc.) + * If not provided, defaults to intercepting posthog.com requests. + */ + ingestPath?: string; +} + +const defaultPosthogPattern = /posthog\.com\/(e|capture|batch|s)(\/|$|\?)/; + +function buildIngestPattern(config?: PostHogTrackingConfig): RegExp { + if (config?.ingestPath) { + // Escape special regex characters in the path + const escapedPath = config.ingestPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return new RegExp(`${escapedPath}\\/(i\\/v\\d+\\/)?(e|capture|batch|s)(\\/|$|\\?)`); + } -export function withPostHogTracking>(test: T): T { + return defaultPosthogPattern; +} + +export function withPostHogTracking>( + test: T, + config?: PostHogTrackingConfig +): T { return test.extend({ page: async ({ page: originalPage }: { page: Page }, use: (page: HogPage) => Promise) => { const hogPage = originalPage as HogPage; const debug = isDebugEnabled(); + const ingestPattern = buildIngestPattern(config); hogPage[kHogEvents] = []; + if (debug) { + console.log(`[posthog-playwright] Intercepting pattern: ${ingestPattern}`); + } - await hogPage.route(posthogIngestPattern, async (route: Route) => { + await hogPage.route(ingestPattern, async (route: Route) => { const request = route.request(); const url = request.url(); const postDataBuffer = request.postDataBuffer(); @@ -51,7 +76,9 @@ export function withPostHogTracking>(test: T): T { await use(hogPage); if (debug) { - console.log(`[posthog-playwright] Test complete. Total: ${hogPage[kHogEvents].length} event(s)`); + console.log( + `[posthog-playwright] Test complete. Total: ${hogPage[kHogEvents].length} event(s)` + ); } }, }) as T;