Apache
Use mod_proxy and mod_headers to add proxy rules to your virtual host. Snow’s Settings → Proxy tab generates the ready-to-paste config for your site.
Required modules
Enable these Apache modules before adding the config:
a2enmod proxy proxy_http headers ssl
systemctl reload apache2On RPM-based systems (RHEL, Rocky, AlmaLinux), these modules are typically already loaded via LoadModule in the main config. Confirm with httpd -M | grep -E 'proxy|headers'.
Simple mode (recommended)
Proxy only the script. Events go directly from the visitor’s browser to the Snow API.
<VirtualHost *:443>
ServerName yourdomain.com
# ... your existing virtual host config ...
SSLProxyEngine on
SSLProxyCheckPeerName on
ProxyPass /sa/sa.js https://api.snowanalytics.app/sa.js
ProxyPassReverse /sa/sa.js https://api.snowanalytics.app/sa.js
<Location /sa/sa.js>
RequestHeader set Host "api.snowanalytics.app"
</Location>
</VirtualHost>Then update your embed to set data-api-url:
<script defer
src="https://yourdomain.com/sa/sa.js"
data-site="YOUR_SITE_ID"
data-api-url="https://api.snowanalytics.app/api/collect"
data-domain="yourdomain.com"></script>The data-api-url attribute tells sa.js to post events directly to the Snow API. Apache is not in the path for events, so the real visitor IP reaches Snow untouched.
Full mode (script and events)
Proxy both paths. You must forward the real visitor IP. Otherwise every visitor geolocates to your server’s city.
Enable Secure proxy in Settings → Proxy before adding the X-Snow-Proxy-Secret header. The secret is shown once when you enable it.
<VirtualHost *:443>
ServerName yourdomain.com
# ... your existing virtual host config ...
SSLProxyEngine on
SSLProxyCheckPeerName on
# Script proxy
ProxyPass /sa/sa.js https://api.snowanalytics.app/sa.js
ProxyPassReverse /sa/sa.js https://api.snowanalytics.app/sa.js
<Location /sa/sa.js>
RequestHeader set Host "api.snowanalytics.app"
</Location>
# Event proxy
ProxyPass /sa/api/collect https://api.snowanalytics.app/api/collect
ProxyPassReverse /sa/api/collect https://api.snowanalytics.app/api/collect
<Location /sa/api/collect>
RequestHeader set Host "api.snowanalytics.app"
# Forward the real visitor IP
RequestHeader set X-Snow-Client-IP "%{REMOTE_ADDR}s"
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
# Secure proxy secret (from Settings → Proxy)
RequestHeader set X-Snow-Proxy-Secret "YOUR_PROXY_SECRET"
# Do not forward visitor cookies or auth
RequestHeader unset Cookie
RequestHeader unset Authorization
</Location>
</VirtualHost>Then update your embed to point events through your domain:
<script defer
src="https://yourdomain.com/sa/sa.js"
data-site="YOUR_SITE_ID"
data-api-url="/sa/api/collect"
data-domain="yourdomain.com"></script>%{REMOTE_ADDR}s is the IP of the connection Apache actually receives. If Apache sits behind a load balancer, this may be the upstream proxy’s IP. In that case, use %{X-Forwarded-For}i (the inbound header) instead, but only if your upstream load balancer sets it from the real socket. See Forwarding the visitor IP for the full details.
Key directives explained
| Directive | Why it’s here |
|---|---|
SSLProxyEngine on | Enables TLS for outbound proxy connections to the Snow API. |
ProxyPass / ProxyPassReverse | Routes the path to the upstream Snow URL and rewrites redirects back. |
RequestHeader set Host | Sends the correct Host header upstream. Required for SNI. |
X-Snow-Client-IP | The real visitor IP, trusted by Snow when the secret matches. |
X-Snow-Proxy-Secret | Authenticates your proxy so Snow trusts X-Snow-Client-IP. |
RequestHeader unset Cookie | Strips visitor cookies. Do not forward them upstream. |
Verify
Generate some traffic, then check Analytics → Locations. A correct setup shows a realistic country distribution, not everything from one city. See Verify it’s working.