Skip to main content

First-party proxy

A first-party proxy lets your website load PureStats from your own domain instead of loading the script directly from purestats.io.

Use this when you want the browser Network panel, CSP and deployment checks to use your own origin, for example:

<script
defer
src="https://example.com/pf.min.js"
data-domain="example.com"
data-api="https://example.com/api/event"
></script>

Keep data-domain set to the canonical domain in PureStats. The data-api attribute tells the tracker to send events to your proxy. PureStats automatically derives the config endpoint from it and requests /api/tracker-config on the same origin.

Proxy paths

Proxy these paths from your website to PureStats:

Your pathUpstreamCache
/pf.min.jshttps://purestats.io/pf.min.jsYes, about 1 hour
/api/eventhttps://purestats.io/api/eventNo
/api/tracker-confighttps://purestats.io/api/tracker-configNo, or very short

Do not cache /api/event. It receives pageviews and custom events.

Nginx

Add the cache zone in the http block:

proxy_cache_path /var/cache/nginx/purestats levels=1:2 keys_zone=purestats_tracker:10m max_size=50m inactive=24h use_temp_path=off;

Add the locations to your site server block:

location = /pf.min.js {
proxy_pass https://purestats.io/pf.min.js;
proxy_ssl_server_name on;
proxy_set_header Host purestats.io;
proxy_cache purestats_tracker;
proxy_cache_valid 200 1h;
add_header Cache-Control "public, max-age=3600" always;
}

location = /api/event {
proxy_pass https://purestats.io/api/event;
proxy_ssl_server_name on;
proxy_set_header Host purestats.io;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location = /api/tracker-config {
proxy_pass https://purestats.io/api/tracker-config;
proxy_ssl_server_name on;
proxy_set_header Host purestats.io;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Apache

Enable mod_proxy, mod_proxy_http, mod_ssl and mod_headers, then add:

SSLProxyEngine On
ProxyPreserveHost Off

ProxyPass "/pf.min.js" "https://purestats.io/pf.min.js" retry=0
ProxyPassReverse "/pf.min.js" "https://purestats.io/pf.min.js"
ProxyPass "/api/event" "https://purestats.io/api/event" retry=0
ProxyPassReverse "/api/event" "https://purestats.io/api/event"
ProxyPass "/api/tracker-config" "https://purestats.io/api/tracker-config" retry=0
ProxyPassReverse "/api/tracker-config" "https://purestats.io/api/tracker-config"

<IfModule mod_headers.c>
<Location "/pf.min.js">
Header set Cache-Control "public, max-age=3600"
</Location>
</IfModule>

Cloudflare Worker

Create a Worker and route it to your domain for /pf.min.js, /api/event and /api/tracker-config.

export default {
async fetch(request) {
const url = new URL(request.url);
const allowed = ['/pf.min.js', '/api/event', '/api/tracker-config'];

if (!allowed.includes(url.pathname)) {
return fetch(request);
}

const upstreamUrl = new URL(url.pathname + url.search, 'https://purestats.io');
const upstreamRequest = new Request(upstreamUrl.toString(), request);

if (url.pathname === '/pf.min.js' && request.method === 'GET') {
const cache = caches.default;
const cached = await cache.match(request);
if (cached) return cached;

const response = await fetch(upstreamRequest);
const cachedResponse = new Response(response.body, response);
cachedResponse.headers.set('Cache-Control', 'public, max-age=3600');
await cache.put(request, cachedResponse.clone());
return cachedResponse;
}

return fetch(upstreamRequest);
}
};

Content Security Policy

If all PureStats requests go through your domain, a strict CSP can allow only your own origin:

script-src 'self';
connect-src 'self';
img-src 'self' data:;

If you keep the normal direct script and only proxy events, also allow https://purestats.io in script-src.

Verify

  1. Open https://example.com/pf.min.js and confirm it returns JavaScript.
  2. Install the first-party script snippet.
  3. Open your site and check the browser Network panel.
  4. Confirm /pf.min.js, /api/tracker-config and /api/event are requested on your own domain.
  5. Open PureStats Site Health and verify the first hit.

Troubleshooting

  • If the script loads but no pageviews appear, check that /api/event forwards POST bodies.
  • If settings do not apply, check that /api/tracker-config?domain=example.com reaches PureStats.
  • If CSP blocks requests, allow your own origin in script-src and connect-src.
  • If the proxy returns 404, make sure the route is configured before your app fallback route.
  • If the proxy returns 405, make sure POST is allowed for /api/event.
  • If the dashboard shows a domain mismatch, keep data-domain set to the canonical PureStats site domain and add every real hostname in Site Settings.