analytics.tube
Proxy Guide

Nginx Proxy Setup

Configure Nginx reverse proxy to serve analytics-tube tracking and bypass ad blockers

Nginx is a powerful web server and reverse proxy that makes it easy to proxy analytics-tube tracking through your own domain. This guide shows how to configure Nginx to forward tracking requests to analytics-tube servers while caching static scripts for better performance.

Overview

Nginx's proxy_pass directive lets you forward requests from your domain to analytics-tube's servers. Combined with caching, this provides excellent performance and reliability for proxying analytics.

What you'll achieve:

  • Proxy all analytics-tube endpoints through your domain
  • Cache static scripts for better performance
  • Forward necessary headers for accurate tracking
  • Support all analytics-tube features (session replay, Web Vitals, custom events)

Prerequisites

  • Nginx installed (version 1.18 or later recommended)
  • SSL/TLS certificate configured (Let's Encrypt recommended)
  • Your analytics-tube instance URL:
    • Cloud hosted: https://app.analytics.tube
    • Self-hosted: Your instance URL
  • Your analytics-tube site ID (found in your dashboard)

Implementation

Configure Nginx Proxy

Add a new location block (or update existing configuration) in your Nginx site configuration:

Minimal configuration for basic tracking:

# /etc/nginx/sites-available/yourdomain.com
server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # Main tracking script
    location = /analytics/script.js {
        proxy_pass https://app.analytics.tube/api/script.js;
        proxy_set_header Host app.analytics.tube;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;

        proxy_cache_valid 200 1h;
    }

    # Event tracking
    location = /analytics/track {
        proxy_pass https://app.analytics.tube/api/track;
        proxy_set_header Host app.analytics.tube;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;
    }
}

For better performance with caching, define a cache zone:

# /etc/nginx/nginx.conf (http block)
http {
    # Define cache zone for analytics-tube
    proxy_cache_path /var/cache/nginx/analytics-tube
        levels=1:2
        keys_zone=analytics-tube_cache:10m
        max_size=100m
        inactive=60m
        use_temp_path=off;

    # ... rest of http config
}

Then in your site config:

# /etc/nginx/sites-available/yourdomain.com
server {
    # ... server config

    location = /analytics/script.js {
        proxy_pass https://app.analytics.tube/api/script.js;
        proxy_set_header Host app.analytics.tube;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;

        # Use the cache zone
        proxy_cache analytics-tube_cache;
        proxy_cache_valid 200 1h;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        add_header X-Cache-Status $upstream_cache_status;
    }

    # ... other locations
}

Important: The proxy_set_header X-Real-IP and X-Forwarded-For headers are critical for accurate geolocation and user identification. Without these, all traffic will appear to come from your Nginx server's IP.

Create Cache Directory (Optional)

If using a cache zone, create the cache directory:

sudo mkdir -p /var/cache/nginx/analytics-tube
sudo chown www-data:www-data /var/cache/nginx/analytics-tube

Test Nginx Configuration

Before reloading Nginx, test the configuration for syntax errors:

sudo nginx -t

You should see:

nginx: configuration file /etc/nginx/nginx.conf test is successful

Reload Nginx

Apply the changes by reloading Nginx:

sudo systemctl reload nginx

Or if you prefer:

sudo nginx -s reload

Update Your Tracking Script

Update your HTML to load the script from your proxied domain:

<!DOCTYPE html>
<html>
<head>
    <!-- ... other head elements -->
    <script src="/analytics/script.js" async data-site-id="YOUR_SITE_ID"></script>
</head>
<body>
    <!-- Your content -->
</body>
</html>

Replace YOUR_SITE_ID with your actual site ID from the analytics-tube dashboard.

Verify the Setup

Test your configuration:

  1. Check Nginx is running:

    sudo systemctl status nginx
  2. Test script loading:

    curl -I https://yourdomain.com/analytics/script.js

    You should see:

    HTTP/2 200
    content-type: application/javascript
    x-cache-status: MISS  # First request
  3. Test again to verify caching:

    curl -I https://yourdomain.com/analytics/script.js

    You should see:

    HTTP/2 200
    x-cache-status: HIT  # Cached!
  4. Open your website in a browser with Developer Tools and verify:

    • Script loads from /analytics/script.js (your domain)
    • Tracking requests go to /analytics/track (your domain)
    • Data appears in your analytics-tube dashboard after 1-2 minutes

How It Works

Nginx's proxy_pass directive transparently forwards requests to analytics-tube's servers:

  1. Browser requests https://yourdomain.com/analytics/script.js
  2. Nginx matches the location block and forwards to https://app.analytics.tube/api/script.js
  3. Nginx sets necessary headers (X-Real-IP, X-Forwarded-For) for accurate tracking
  4. Response is cached (if configured) and sent back to browser
  5. All subsequent tracking requests follow the same pattern

The analytics-tube script auto-detects it's being served from your domain and sends all tracking data to your domain's /analytics/* endpoints.

Performance Optimization

Caching Strategy

Configure different cache durations based on content type:

# Scripts - cache for 1 hour
location ~ ^/analytics/(script|replay|metrics)\.js$ {
    proxy_pass https://app.analytics.tube/api/$1.js;
    # ... proxy headers
    proxy_cache_valid 200 1h;
    proxy_cache_valid 404 1m;  # Cache 404s briefly
}

# Config - cache for 5 minutes (changes when you update dashboard settings)
location ~ ^/analytics/site/tracking-config/(.*)$ {
    proxy_pass https://app.analytics.tube/api/site/tracking-config/$1;
    # ... proxy headers
    proxy_cache_valid 200 5m;
}

# Tracking - never cache (each request is unique)
location ~ ^/analytics/(track|identify)$ {
    proxy_pass https://app.analytics.tube/api/$1;
    # ... proxy headers
    # No caching directives
}

Gzip Compression

Enable compression for JavaScript files:

# In http or server block
gzip on;
gzip_vary on;
gzip_types application/javascript text/javascript;
gzip_min_length 1000;

Connection Pooling

Keep connections to analytics-tube backend alive for better performance:

upstream analytics-tube_backend {
    server app.analytics.tube:443;
    keepalive 32;
}

location /analytics/ {
    proxy_pass https://analytics-tube_backend/api/;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    # ... other proxy headers
}

Proxy Buffering

For better performance with larger session replay uploads:

location ~ ^/analytics/session-replay/record/ {
    proxy_pass https://app.analytics.tube/api/session-replay/record/;
    # ... proxy headers

    proxy_buffering on;
    proxy_buffer_size 4k;
    proxy_buffers 8 4k;
    proxy_busy_buffers_size 8k;
    client_max_body_size 10M;
}

Security Considerations

Rate Limiting

Protect your proxy from abuse with rate limiting:

# In http block
http {
    limit_req_zone $binary_remote_addr zone=analytics_limit:10m rate=10r/s;

    # ... rest of config
}

# In server block
location = /analytics/track {
    limit_req zone=analytics_limit burst=20 nodelay;
    proxy_pass https://app.analytics.tube/api/track;
    # ... proxy headers
}

This limits to 10 requests per second per IP, with bursts up to 20.

Request Size Limits

Set appropriate limits for different endpoints:

# Default for most endpoints
client_max_body_size 1M;

# Larger limit for session replay
location ~ ^/analytics/session-replay/record/ {
    client_max_body_size 10M;
    # ... proxy config
}

Security Headers

Add security headers to your responses:

add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options DENY;
add_header Referrer-Policy strict-origin-when-cross-origin;

Troubleshooting

502 Bad Gateway

Problem: Nginx returns 502 error when accessing analytics endpoints.

Solution:

  1. Check analytics-tube backend is accessible:
    curl -I https://app.analytics.tube/api/script.js
  2. Verify proxy_ssl_server_name on is set
  3. Check Nginx error logs:
    sudo tail -f /var/log/nginx/error.log

Cache not working

Problem: X-Cache-Status always shows MISS.

Solution:

  1. Verify cache directory exists and is writable
  2. Check proxy_cache_path is defined in http block
  3. Ensure proxy_cache directive uses correct zone name
  4. Check cache key is consistent:
    proxy_cache_key "$scheme$request_method$host$request_uri";

Incorrect geolocation in analytics-tube

Problem: All visitors show same location (your server's location).

Solution: Ensure you're forwarding client IP headers:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

SSL errors in Nginx logs

Problem: Logs show SSL verification errors when connecting to analytics-tube.

Solution: Add proxy_ssl_server_name on to enable SNI:

location /analytics/ {
    proxy_pass https://app.analytics.tube/api/;
    proxy_ssl_server_name on;  # Enable SNI
    # ... other config
}

Advanced Configuration

Subdomain Proxy

Use a dedicated subdomain for analytics:

# /etc/nginx/sites-available/analytics.yourdomain.com
server {
    listen 443 ssl http2;
    server_name analytics.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/analytics.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/analytics.yourdomain.com/privkey.pem;

    # Proxy all requests to analytics-tube
    location / {
        proxy_pass https://app.analytics.tube/api/;
        proxy_set_header Host app.analytics.tube;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_ssl_server_name on;
    }
}

Then use:

<script src="https://analytics.yourdomain.com/script.js" data-site-id="123"></script>

Multiple analytics-tube Instances

If you need to proxy multiple analytics-tube instances:

location /analytics-prod/ {
    proxy_pass https://prod.analytics.tube/api/;
    # ... proxy config
}

location /analytics-staging/ {
    proxy_pass https://staging.analytics.tube/api/;
    # ... proxy config
}