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.
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
).Avoid using generic or common path names like
/analytics
,/tracking
,/ingest
, or/posthog
for your reverse proxy. They will most likely be blocked. Instead, use a non-obvious path name or something random and unique to your application that's unlikely to appear in a filter list.
If you are using Remix, you can use API routes to set up a reverse proxy.
Create a file <ph_proxy_path>.$.tsx
in the routes folder. For example, if your proxy path is /ph-relay-xyz123
, name the file ph-relay-xyz123.$.tsx
.
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.
import type { ActionFunction, LoaderFunction } from "@remix-run/node";const API_HOST = "eu.i.posthog.com";const ASSET_HOST = "eu-assets.i.posthog.com";const posthogProxy = async (request: Request) => {const url = new URL(request.url);const hostname = url.pathname.startsWith("/<ph_proxy_path>/static/")? ASSET_HOST: API_HOST;const newUrl = new URL(url);newUrl.protocol = "https";newUrl.hostname = hostname;newUrl.port = "443";newUrl.pathname = newUrl.pathname.replace(/^\/<ph_proxy_path>/, "");const headers = new Headers(request.headers);headers.set("host", hostname);const response = await fetch(newUrl, {method: request.method,headers,body: request.body,});return new Response(response.body, {status: response.status,statusText: response.statusText,headers: response.headers,});};export const loader: LoaderFunction = async ({ request }) =>posthogProxy(request);export const action: ActionFunction = async ({ request }) =>posthogProxy(request);
Once done, configure the PostHog client to send requests via your rewrite.
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {api_host: "/<ph_proxy_path>",ui_host: "<ph_app_host>"})