Netlify reverse proxy
Contents
- If you use a self-hosted proxy, PostHog can't help troubleshoot. Use our managed reverse proxy if you want support.
- Use domains matching your PostHog region:
us.i.posthog.comfor US,eu.i.posthog.comfor EU. - Don't use obvious path names like
/analytics,/tracking,/telemetry, or/posthog. Blockers will catch them. Use something unique to your app instead.
This guide shows you how to use Netlify redirects as a reverse proxy for PostHog.
How it works
Netlify's redirect rules can function as a reverse proxy by returning a 200 status code instead of a 301 or 302. When a request hits your Netlify site, Netlify fetches the content from the target URL and returns it to the user while keeping your domain in the browser's address bar.
Here's the request flow:
- User triggers an event in your app
- Request goes to your domain (e.g.,
yourdomain.com/ph) - Netlify intercepts the request and matches it against your redirect rules
- Netlify fetches the response from PostHog's servers
- Netlify returns PostHog's response to the user under your domain
This works because ad blockers see requests going to your domain, not PostHog's. The redirect happens server-side, so the browser never sees the PostHog domain.
Why two redirect rules? PostHog uses separate domains for API requests and static assets. You need two rules:
- Static assets: Routes
/static/*tous-assets.i.posthog.comoreu-assets.i.posthog.comfor the JavaScript SDK and other static files - API requests: Routes everything else to
us.i.posthog.comoreu.i.posthog.comfor event capture, feature flags, and API calls
Netlify modifies the Content-Encoding header when using redirects on .netlify.app domains, which causes PostHog to fail parsing requests. You must use a custom domain for this proxy to work.
Prerequisites
- A Netlify site with a custom domain configured
- Access to your project's
netlify.tomlfile or ability to create a_redirectsfile
Choose your setup option
Both options accomplish the same goal. Choose based on your project setup:
- netlify.toml: The standard approach for most Netlify projects. Configuration lives alongside your other Netlify settings.
- Redirects file: Required for SvelteKit projects because Netlify doesn't support redirects in
netlify.tomlfor SvelteKit. Also useful if you prefer a standalone redirects file.
Option 1: netlify.toml
This is the standard approach for most Netlify projects.
- 1
Add redirects to netlify.toml
In your project root, add these redirects to your
netlify.tomlfile:tomlReplace
uswitheufor EU region.Here's what each directive does:
from: The path pattern on your domain to match. The*captures everything after the path, and:splatinserts it into the target URL.to: The PostHog URL to fetch content from. The:splatplaceholder is replaced with whatever the*captured.host: Sets theHostheader sent to PostHog. Without this, PostHog receives your domain as the Host header and can't route the request, causing 401 errors.status = 200: Makes this a proxy (returns content) rather than a redirect (returns a redirect response). This is what makes the browser see your domain instead of PostHog's.force = true: Applies this rule even if a file exists at that path. Without this, Netlify might serve a local file instead of proxying to PostHog.
The static assets rule must come first because Netlify evaluates rules in order. If the catch-all rule came first, it would match
/ph/static/*requests before the static-specific rule could.See Netlify's redirects documentation for more details.
- 2
Deploy your changes
Commit and push your changes to trigger a Netlify deploy. The redirects become active once the deploy completes.
You can verify the redirects were processed by checking your deploy logs in the Netlify dashboard. Look for
Processed X redirect rulesin the output. - 3
Update your PostHog SDK
In your application code, update your PostHog initialization to use your proxy path:
Replace
yourdomain.comwith your custom domain.The
api_hosttells the SDK where to send events. Theui_hostmust point to PostHog's actual domain so features like the toolbar and session recordings link correctly.You can also use a relative path if you prefer:
Using a relative path avoids CORS issues when your primary domain differs from the one you're using in the SDK (e.g.,
mydomain.comvswww.mydomain.com). Verify your setup
CheckpointConfirm events are flowing through your proxy:
- Open your browser's developer tools and go to the Network tab
- Navigate to your site or trigger an event in your app
- Look for requests to your domain with your proxy path (e.g.,
yourdomain.com/ph) - Verify the response status is
200 OK - Check the PostHog app to confirm events appear in your activity feed
If you see errors, check troubleshooting below.
Option 2: Redirects file
Use this approach for SvelteKit projects or if you prefer a standalone redirects file.
- 1
Create a redirects file
Create a file named
_redirectsin the directory that gets deployed to Netlify. For most projects, this is your project root or build output directory.Add this content:
Replace
uswitheufor EU region.The format is
source destination status. The!after200is equivalent toforce = trueinnetlify.tomland ensures the redirect applies even if a file exists at that path.The static assets rule must come first because Netlify evaluates rules in order.
See Netlify's redirects file documentation for more details.
- 2
Ensure the file is deployed
The redirects file must end up in your publish directory after the build. How you achieve this depends on your framework:
- SvelteKit: Place the file in your
staticdirectory. SvelteKit copies static files to the build output. - Other frameworks: Check your framework's documentation for how to include static files in the build output.
If the file isn't in the publish directory, Netlify won't process the redirects.
- SvelteKit: Place the file in your
- 3
Deploy your changes
Commit and push your changes to trigger a Netlify deploy. The redirects become active once the deploy completes.
You can verify the redirects were processed by checking your deploy logs in the Netlify dashboard. Look for
Processed X redirect rulesin the output. - 4
Update your PostHog SDK
In your application code, update your PostHog initialization to use your proxy path:
Replace
yourdomain.comwith your custom domain.The
api_hosttells the SDK where to send events. Theui_hostmust point to PostHog's actual domain so features like the toolbar and session recordings link correctly.You can also use a relative path:
Using a relative path avoids CORS issues when your primary domain differs from the one you're using in the SDK.
Verify your setup
CheckpointConfirm events are flowing through your proxy:
- Open your browser's developer tools and go to the Network tab
- Navigate to your site or trigger an event in your app
- Look for requests to your domain with your proxy path (e.g.,
yourdomain.com/ph) - Verify the response status is
200 OK - Check the PostHog app to confirm events appear in your activity feed
If you see errors, check troubleshooting below.
Troubleshooting
404 errors on proxy path
If requests to your proxy path return 404:
- Check that your
netlify.tomlor_redirectsfile is in the correct location and being deployed - Look at your Netlify deploy logs to confirm the redirects were processed
- Verify the path in your redirect rule matches the path in your SDK configuration
For redirects files, make sure the file is in your publish directory after the build, not just in your source directory.
CORS errors
If you see CORS errors about a missing Access-Control-Allow-Origin header, try using a relative path instead of the full URL:
This often happens when your primary Netlify domain differs from the one in api_host. For example, if your primary domain is mydomain.com but you set api_host to https://www.mydomain.com/ph, browsers will treat this as a cross-origin request.
Redirects not working in SvelteKit
Netlify doesn't support netlify.toml redirects for SvelteKit projects. Use a _redirects file in your static directory instead.