Using SvelteKit server hooks as a reverse proxy

Last updated:

|Edit this page

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 of us 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.

TypeScript
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 ingestion
const 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 URL
const url = new URL(event.request.url);
url.protocol = 'https:';
url.hostname = hostname;
url.port = '443';
url.pathname = pathname.replace('/ingest/', '');
// Clone and adjust headers
const headers = new Headers(event.request.headers);
headers.set('host', hostname);
// Proxy the request to the external host
const 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:

TypeScript
// src/routes/+layout.ts
import 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 Cloud
person_profiles: 'always',
persistence: 'localStorage'
});
}
initTelemetry();

Questions? Ask Max AI.

It's easier than reading through 634 docs articles.

Community questions

Was this page useful?

Next article

Using Vercel rewrites as a reverse proxy

Vercel supports rewrites which we can use as a reverse proxy. Create a vercel.json file and add a rewrites object from the /ingest route. Some frameworks, like SvelteKit and Astro , require a hungrier regex pattern like: Note: Some frameworks, like T3 app, don't support Vercel rewrites well. If neither of these options work, we recommend trying another proxy method. Once done, set the /ingest route of your domain as the API host in your PostHog initialization like this: Once…

Read next article