Note: The following self-hosted proxy isn't provided by PostHog, so we can't take responsibility for it! If unsure, we recommend using our managed reverse proxy.
Note: If you are using the EU cloud then use
eu
instead ofus
in all domains (e.g.us.i.posthog.com
->eu.i.posthog.com
)
For SvelteKit, you can use server hooks to proxy requests to PostHog. We've tested this (and it works)with Cloudflare Workers.
To do this, create a file named hooks.server.ts
in your src
directory (or the dir
you configured to contain source files). In this file, set up code to match requests to a custom route, set a new host
header, change the URL to point to PostHog, and rewrite the response.
Note: This only works in SSR mode. If your site is statically generated, SvelteKit ignores
hooks.server.ts
.
import type { Handle } from '@sveltejs/kit';export const handle: Handle = async ({ event, resolve }) => {const { pathname } = event.url;if (pathname.startsWith('/ingest')) {// Determine target hostname based on static or dynamic ingestionconst hostname = pathname.startsWith('/ingest/static/')? 'us-assets.i.posthog.com' // change us to eu for EU Cloud: 'us.i.posthog.com'; // change us to eu for EU Cloud// Build external URLconst url = new URL(event.request.url);url.protocol = 'https:';url.hostname = hostname;url.port = '443';url.pathname = pathname.replace('/ingest/', '');// Clone and adjust headersconst headers = new Headers(event.request.headers);headers.set('host', hostname);// Proxy the request to the external hostconst response = await fetch(url.toString(), {method: event.request.method,headers,body: event.request.body});return response;}const response = await resolve(event);return response;};
Once done, configure the PostHog client to send requests via your rewrite like we do in this sample:
// src/routes/+layout.tsimport posthog from 'posthog-js';import { browser } from '$app/environment';import { PUBLIC_POSTHOG_KEY as POSTHOG_KEY } from '$env/static/public';export function initTelemetry() {if (!browser) return;posthog.init(POSTHOG_KEY, {api_host: '/ingest',ui_host: 'https://us.posthog.com', // change us to eu for EU Cloudperson_profiles: 'always',persistence: 'localStorage'});}initTelemetry();