Vercel 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 Vercel rewrites as a reverse proxy for PostHog.
How it works
Vercel rewrites map incoming request paths to different destinations. When you add PostHog rewrites to vercel.json, Vercel fetches content from PostHog's servers and returns it under your domain.
Here's the request flow:
- User triggers an event in your app
- Request goes to your Vercel domain (e.g.,
yourdomain.com/ph) - Vercel matches the request against your rewrite rules
- Vercel fetches the response from PostHog's servers
- Vercel returns PostHog's response under your domain
This works because the rewrite happens server-side, so the browser only sees requests to your domain. Ad blockers that filter by domain won't block these requests.
Using Next.js on Vercel?
If you're using Next.js, you can configure rewrites in either vercel.json or next.config.js. Both work identically on Vercel.
- Use this guide (
vercel.json) if you want all Vercel-specific settings in one file - Use Next.js rewrites if you prefer keeping config in
next.config.js
Don't use both at the same time as they may conflict.
Prerequisites
This guide requires a project deployed on Vercel.
Setup
- 1
Create vercel.json
In your project root, create or update
vercel.json:Here's what each part does:
- The first rewrite routes
/ph/static/*requests to PostHog's asset server. This serves the JavaScript SDK and other static files. - The second rewrite routes all other
/ph/*requests to PostHog's main API. This handles event capture, feature flags, and session recordings. - The
:path(.*)syntax captures everything after the matched prefix and passes it to the destination URL.
The static rewrite must come first. Vercel evaluates rewrites in order, so if the catch-all rule came first, it would match
/ph/static/*before the static-specific rule.See Vercel's rewrites documentation for more details.
- The first rewrite routes
- 2
Update your PostHog SDK
In your application code, update your PostHog initialization:
The
api_hosttells the SDK where to send events. Using a relative path ensures requests go to your domain. Theui_hostmust point to PostHog's actual domain so features like the toolbar link correctly. - 3
Deploy to Vercel
Commit and push your changes. The rewrites become active once deployed.
You can verify the configuration in your Vercel dashboard under Project Settings → Functions → Rewrites.
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
- 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
Rewrites not working
If requests to your proxy path return 404:
- Verify
vercel.jsonis in your project root (same level aspackage.json) - Check the file is valid JSON with no syntax errors
- Ensure the rewrites are in the correct order: static assets first, then catch-all
- Check the Vercel dashboard to confirm the config was deployed
401 errors after deployment
If events work locally but return 401 errors on Vercel, this usually indicates a region mismatch. Verify your rewrite destinations match your PostHog project's region:
- US region:
us.i.posthog.comandus-assets.i.posthog.com - EU region:
eu.i.posthog.comandeu-assets.i.posthog.com
Conflicts with Next.js rewrites
If you're using both vercel.json rewrites and Next.js next.config.js rewrites, they may conflict. Choose one method:
- Use
vercel.jsonfor all Vercel-specific config - Or use
next.config.jsfor framework-level config
Remove the PostHog rewrites from whichever file you're not using.
Rewrite pattern not matching
If your rewrites aren't matching correctly, ensure you're using Vercel's named parameter syntax:
The :path(.*) captures the path and :path in the destination references it. Don't use (.*) without the named parameter.