Troubleshooting Proxy Setup
Common issues and solutions for Rybbit proxy configurations
This guide covers common issues you might encounter when setting up a Rybbit proxy and how to resolve them.
Script Loading Issues
Script Fails to Load (404 Error)
Symptoms:
- Network tab shows 404 for
/analytics/script.js - Console errors about failed script loading
- No tracking data in dashboard
Solutions:
Verify Proxy Configuration
Check your proxy rules are correctly configured:
- Next.js: Ensure rewrites are in
next.config.jsand server is restarted - Nginx: Verify location blocks are active and Nginx is reloaded
- Caddy: Check Caddyfile syntax with
caddy validate - Workers: Verify route is configured in Cloudflare dashboard
Check Path Mapping
Ensure paths are correctly mapped:
Your domain → Rybbit backend
----------------- ---------------
/analytics/script.js → /api/script.jsCommon mistakes:
- Wrong source path (
/trackinginstead of/analytics) - Incorrect destination (missing
/apiprefix) - Typos in configuration
Test Direct Backend Access
Verify Rybbit backend is accessible:
curl -I https://app.rybbit.io/api/script.jsShould return HTTP/2 200 with content-type: application/javascript.
Script Loads but Returns HTML
Symptoms:
- Script loads with 200 status
- Content-Type is
text/htmlinstead ofapplication/javascript - Console errors about unexpected token
<
Cause: Proxy is serving your application's 404 page instead of proxying.
Solutions:
-
Ensure proxy runs before app routing:
- Next.js: Rewrites run automatically before pages
- Express: Define proxy routes BEFORE catch-all routes
- Laravel: Place proxy routes at the top of
web.php
-
Check route specificity:
// ❌ Wrong order - catch-all comes first
app.get('*', (req, res) => res.sendFile('index.html'));
app.use('/analytics', proxyMiddleware);
// ✅ Correct order - proxy comes first
app.use('/analytics', proxyMiddleware);
app.get('*', (req, res) => res.sendFile('index.html'));Tracking Issues
Script Loads but No Events Tracked
Symptoms:
- Script loads successfully
- No errors in console
- No tracking data appears in Rybbit dashboard
- POST requests to
/analytics/trackfail or return errors
Solutions:
Verify All Endpoints Are Proxied
Ensure tracking endpoints are configured:
/analytics/track(required)/analytics/identify(for user identification)/analytics/session-replay/record/:siteId(for session replay)/analytics/site/tracking-config/:siteId(for configuration)
Check Network tab: Look for failed POST requests to /analytics/track.
Check CORS Headers
Tracking endpoints need proper CORS headers. Rybbit sets these automatically, but ensure your proxy preserves them:
# Nginx - preserve CORS headers
proxy_pass_header Access-Control-Allow-Origin;
proxy_pass_header Access-Control-Allow-Methods;// Express - don't override CORS
// ❌ Wrong - blocks CORS
app.use('/analytics', cors({ origin: 'https://yourdomain.com' }));
// ✅ Correct - allow all origins (or use Rybbit's headers)
app.use('/analytics', cors({ origin: true }));Verify Content-Type for POST Requests
Tracking POSTs send JSON data. Ensure Content-Type is preserved:
# Nginx
proxy_set_header Content-Type $content_type;// Express
onProxyReq: (proxyReq, req) => {
if (req.headers['content-type']) {
proxyReq.setHeader('Content-Type', req.headers['content-type']);
}
}Check Request Method Preservation
Ensure POST requests remain POST:
# Nginx - correct
proxy_method $request_method;
# Or let it default (preserves method)
proxy_pass https://app.rybbit.io;Events Tracked but Dashboard Shows Wrong Data
Symptoms:
- Events appear in dashboard
- But geolocation is wrong (all same location)
- Or user agents are incorrect
Cause: Client IP or headers not forwarded properly.
Solutions:
Critical: The X-Forwarded-For and X-Real-IP headers must contain the original client IP for accurate geolocation and user identification.
Nginx:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header User-Agent $http_user_agent;Caddy:
reverse_proxy https://app.rybbit.io {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}Express:
onProxyReq: (proxyReq, req) => {
const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
proxyReq.setHeader('X-Real-IP', clientIp);
proxyReq.setHeader('X-Forwarded-For', clientIp);
proxyReq.setHeader('User-Agent', req.headers['user-agent']);
}Cloudflare Workers:
const clientIp = request.headers.get('CF-Connecting-IP') || '0.0.0.0';
proxyHeaders.set('X-Real-IP', clientIp);Session Replay Issues
Session Replay Not Working
Symptoms:
- Basic tracking works fine
- Session replays don't appear in dashboard
- Console shows errors loading
/analytics/replay.js
Solutions:
- Add replay script endpoint:
// Next.js
{
source: '/analytics/replay.js',
destination: `${process.env.NEXT_PUBLIC_RYBBIT_HOST}/api/replay.js`,
}- Add replay recording endpoint:
{
source: '/analytics/session-replay/record/:siteId',
destination: `${process.env.NEXT_PUBLIC_RYBBIT_HOST}/api/session-replay/record/:siteId`,
}- Increase request size limits:
Session replay can send large payloads (up to 10MB). Ensure your proxy allows this:
# Nginx
location ~ ^/analytics/session-replay/record/ {
client_max_body_size 10M;
proxy_pass https://app.rybbit.io;
}// Express
app.use('/analytics/session-replay', express.json({ limit: '10mb' }));// Next.js - add to next.config.js
module.exports = {
api: {
bodyParser: {
sizeLimit: '10mb',
},
},
};Configuration and Caching Issues
Stale Configuration (Settings Changes Not Applied)
Symptoms:
- Changed settings in Rybbit dashboard
- But tracking script still uses old settings
- Takes a long time for changes to appear
Cause: Configuration endpoint is cached too aggressively.
Solutions:
- Check cache duration for config endpoint:
# Nginx - cache for 5 minutes max
location ~ ^/analytics/site/tracking-config/ {
proxy_cache_valid 200 5m; # Not longer!
proxy_pass https://app.rybbit.io;
}- Clear cache manually:
# Nginx
sudo nginx -s reload
# Or clear cache directory
sudo rm -rf /var/cache/nginx/rybbit/*// Node.js/Express with node-cache
cache.del(`rybbit_config_${siteId}`);
// Or flush all
cache.flushAll();- Don't cache config endpoint at all (if issues persist):
# Nginx - no caching
location ~ ^/analytics/site/tracking-config/ {
proxy_cache off;
proxy_pass https://app.rybbit.io;
}Script Updates Not Appearing
Symptoms:
- Rybbit released an update
- Your site still loads old script version
- Missing new features or bug fixes
Cause: Script cached too long.
Solutions:
- Recommended cache duration: 1 hour maximum
# Nginx
proxy_cache_valid 200 1h; # Not longer!- Clear script cache:
# Nginx - purge cache
sudo rm -rf /var/cache/nginx/rybbit/
sudo nginx -s reload# Vercel - clear via dashboard
# Deployments → Your deployment → Clear cache// Cloudflare Workers - purge via dashboard
// Caching → Configuration → Purge Everything- Add cache busting (advanced):
// Next.js - revalidate on each deployment
{
source: '/analytics/script.js',
destination: `${rybbitHost}/api/script.js`,
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=3600, must-revalidate',
},
],
}Performance Issues
High Bandwidth Usage
Symptoms:
- Bandwidth costs increasing significantly
- Server struggling with traffic
- Slow response times
Solutions:
Implement Caching
Cache static scripts to reduce backend requests:
# Nginx with caching
proxy_cache_path /var/cache/nginx/rybbit levels=1:2 keys_zone=rybbit:10m;
location = /analytics/script.js {
proxy_cache rybbit;
proxy_cache_valid 200 1h;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache-Status $upstream_cache_status;
proxy_pass https://app.rybbit.io/api/script.js;
}Use CDN
Put a CDN in front of your proxy:
- Cloudflare (recommended)
- AWS CloudFront
- Fastly
Monitor and Limit
Add monitoring and rate limiting:
// Express with rate limiting
const rateLimit = require('express-rate-limit');
app.use('/analytics/track', rateLimit({
windowMs: 60 * 1000,
max: 100, // 100 requests per minute per IP
}));Slow Response Times
Symptoms:
- Tracking requests take multiple seconds
- Script loading is slow
- Poor user experience
Solutions:
- Enable compression:
# Nginx
gzip on;
gzip_types application/javascript;- Use connection keepalive:
# Nginx
proxy_http_version 1.1;
proxy_set_header Connection "";
upstream rybbit {
server app.rybbit.io:443;
keepalive 32;
}- Check backend connectivity:
# Test latency to Rybbit
curl -w "@curl-format.txt" -o /dev/null -s https://app.rybbit.io/api/script.js
# Create curl-format.txt:
# time_namelookup: %{time_namelookup}s
# time_connect: %{time_connect}s
# time_starttransfer: %{time_starttransfer}s
# time_total: %{time_total}sIf backend is slow, consider:
- Self-hosting Rybbit closer to your users
- Using a CDN proxy
- Caching more aggressively
Platform-Specific Issues
Next.js: Rewrites Not Working
Problem: Added rewrites to next.config.js but they don't work.
Solutions:
- Restart dev server:
# Stop server (Ctrl+C)
npm run dev- Check async rewrites function:
// ❌ Wrong - not async
rewrites() {
return [...];
}
// ✅ Correct - async
async rewrites() {
return [...];
}- Verify environment variable is loaded:
async rewrites() {
console.log('RYBBIT_HOST:', process.env.NEXT_PUBLIC_RYBBIT_HOST);
// Should log the URL
return [...];
}Nginx: 502 Bad Gateway
Problem: Nginx returns 502 error for analytics endpoints.
Solutions:
- Enable SNI for SSL:
proxy_ssl_server_name on;- Check DNS resolution:
nslookup app.rybbit.io- Check logs:
sudo tail -f /var/log/nginx/error.log- Test backend directly:
curl -v https://app.rybbit.io/api/script.jsVercel: 404 After Deployment
Problem: Works locally but 404 in production.
Solutions:
- Ensure
vercel.jsonis committed:
git add vercel.json
git commit -m "Add Rybbit proxy config"
git push-
Check build logs in Vercel dashboard for errors
-
Verify environment variables are set in Vercel project settings
Debugging Checklist
When troubleshooting, work through this checklist:
- Script loads successfully (200 status, correct Content-Type)
- Tracking endpoint is proxied (
/analytics/track) - POST requests preserve method and body
- Client IP is forwarded (
X-Forwarded-For,X-Real-IP) - User-Agent header is preserved
- CORS headers are preserved (check response headers)
- Request size limits allow tracking data (1MB minimum)
- Session replay endpoints are proxied (if using replay)
- Cache duration is appropriate (1 hour for scripts, 5 min for config)
- No CSRF protection blocking POST requests
- Environment variables are set correctly
- Configuration changes have been deployed
Getting Help
If you've tried everything and still have issues:
- Check browser console for JavaScript errors
- Check Network tab for failed requests (note status codes)
- Check server logs for proxy errors
- Test with curl to isolate browser vs server issues
- Verify directly against
https://app.rybbit.io/api/script.js
Gather this information before asking for help:
- Framework/platform you're using
- Proxy configuration code
- Network tab screenshot showing the issue
- Any error messages from logs or console
- Whether it worked before (what changed?)
Related Resources
- Generic Proxy Guide - Core concepts
- Tracking Script Documentation - Script configuration
- Framework-specific guides for detailed setup