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 Next.js and rewrites aren't working for you, you can write custom middleware to proxy requests to PostHog.
To do this using the app router, create a file named middleware.js
in your base directory (same level as the app
folder). 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 { NextResponse } from 'next/server'export function middleware(request) {let url = request.nextUrl.clone()const hostname = url.pathname.startsWith("/<ph_proxy_path>/static/") ? 'us-assets.i.posthog.com' : 'us.i.posthog.com'const requestHeaders = new Headers(request.headers)requestHeaders.set('host', hostname)url.protocol = 'https'url.hostname = hostnameurl.port = 443url.pathname = url.pathname.replace(/^\/<ph_proxy_path>/, '');return NextResponse.rewrite(url, {headers: requestHeaders,})}export const config = {matcher: '/<ph_proxy_path>/:path*',}
Add the skipTrailingSlashRedirect
option to your next.config.js
file:
// next.config.jsconst nextConfig = {// This is required to support PostHog trailing slash API requestsskipTrailingSlashRedirect: true,}module.exports = nextConfig
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>"})