NGINX's proxy_pass directive is one of the most battle-tested ways to route pixel requests through your own infrastructure. Two location blocks are all that is needed to forward /js/script.js and /api/event to Admaxxer while keeping your domain as the public-facing host.
ngx_http_proxy_module (included in all standard builds).Open your NGINX server block config (typically /etc/nginx/sites-available/yourdomain.conf or /etc/nginx/conf.d/yourdomain.conf) and add inside the server { } block:
server {
listen 443 ssl http2;
server_name yourdomain.com;
# ... your existing SSL config, root, etc. ...
# Admaxxer pixel proxy
location = /js/script.js {
proxy_pass https://admaxxer.com/js/script.js;
proxy_ssl_server_name on;
proxy_set_header Host admaxxer.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_cache_bypass 1;
add_header Cache-Control "public, max-age=3600";
}
location ^~ /api/event {
proxy_pass https://admaxxer.com/api/event;
proxy_ssl_server_name on;
proxy_set_header Host admaxxer.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 10s;
}
}
Key directives explained:
proxy_ssl_server_name on — enables SNI for the upstream TLS handshake. Required when proxying to an HTTPS upstream.proxy_set_header Host admaxxer.com — sends the correct Host header to the upstream. Without this, the request may fail SNI verification.location = /js/script.js — the = modifier is an exact match; it takes priority over longer prefix matches.location ^~ /api/event — the ^~ modifier matches any path starting with /api/event and prevents regex locations from overriding it.sudo nginx -t
sudo systemctl reload nginx
Always run nginx -t before reloading. A syntax error in the config will prevent the reload and leave the old config running.
In Admaxxer go to Connections › Install, enable Custom proxy domain, and enter your domain. Copy the regenerated snippet into your site's <head>.
# Script
curl -I https://yourdomain.com/js/script.js
# Expect: HTTP/2 200 content-type: application/javascript
# Event endpoint
curl -X POST https://yourdomain.com/api/event \
-H 'Content-Type: application/json' \
-d '{"name":"pageview","url":"https://yourdomain.com/"}'
# Expect: HTTP/2 200 or 204
If NGINX cannot resolve admaxxer.com at startup (e.g., in a container environment), add a resolver directive:
resolver 8.8.8.8 1.1.1.1 valid=60s;
resolver_timeout 5s;
Add this inside the server { } block or in the http { } block in nginx.conf.
The pixel script changes infrequently. You can cache it in NGINX's proxy cache to reduce upstream requests:
# In http { } block (nginx.conf)
proxy_cache_path /tmp/nginx-cache levels=1:2 keys_zone=admaxxer_cache:1m max_size=10m;
# In location = /js/script.js
proxy_cache admaxxer_cache;
proxy_cache_valid 200 1h;
proxy_cache_use_stale error timeout updating;
admaxxer.com. Check outbound firewall rules: curl -I https://admaxxer.com/js/script.js from the server. Also verify proxy_ssl_server_name on is present.proxy_ssl_verify off; temporarily to diagnose (do not use in production). Permanent fix: ensure proxy_ssl_server_name on and that the server's CA bundle is up to date.nginx -T | grep location to list all active location blocks. Make sure there is no conflicting catch-all location earlier in the file./api/event route. If the proxy location is overridden by a file-system route, adjust the location order or remove the conflicting route.Remove or comment out the two location blocks, run nginx -t, and reload NGINX. Disable the custom proxy domain in Admaxxer to revert the snippet.
Cloudflare · Vercel · Next.js · Nuxt · Netlify · WordPress · Apache
See also: Connections › Install for the base snippet.