Proxy Setup Guide
Some visitors use adblockers that block third-party analytics scripts. When this happens, the Clickport tracker never loads and that visit is invisible to you. Depending on your audience, this can mean losing anywhere from 6% to 60% of your data.
Proxying the tracker through your own domain solves this. Instead of loading the script from clickport.io, visitors load it from your domain. Since it looks like a first-party request, adblockers let it through.
How it works
You need to proxy two things:
- The tracker script - a JavaScript file that visitors download once per page load
- The event endpoint - where the tracker sends pageviews and events via POST requests
Your proxy forwards these requests to Clickport's servers. Visitors never see clickport.io in their browser's network tab, so adblocker filter lists do not match.
analytics, tracking, stats, plausible, or clickport in your proxy paths. Generic names like /js/app.js or /collect work well.
Snippet configuration
Once your proxy is set up, update the Clickport snippet on your site. The tracker automatically sends events to the same origin it was loaded from, so if the script loads from your domain, events go to your domain too.
<!-- Load tracker from your proxy -->
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
If your script path and event path use different base URLs, you can override the event endpoint with cpConfig.api:
<script>
window.cpConfig = { api: '/collect' };
</script>
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
This tells the tracker to send events to /collect/api/event instead of deriving the path from the script source.
Cloudflare Workers
Cloudflare Workers is a good option if your site already uses Cloudflare. The free tier handles 100,000 requests per day, which is more than enough for most sites.
Step 1: Create a Worker
In your Cloudflare dashboard, go to Workers & Pages and create a new Worker. Give it a generic name (the random default is fine).
Step 2: Add the Worker code
Replace the default code with:
const SCRIPT_URL = 'https://clickport.io/tracker.js';
const SCRIPT_PATH = '/js/app.js';
const EVENT_PATH = '/api/event';
addEventListener('fetch', event => {
event.passThroughOnException();
event.respondWith(handleRequest(event));
});
async function handleRequest(event) {
const url = new URL(event.request.url);
if (url.pathname === SCRIPT_PATH) {
// Serve the tracker script (cached at the edge)
let response = await caches.default.match(event.request);
if (!response) {
response = await fetch(SCRIPT_URL);
event.waitUntil(caches.default.put(event.request, response.clone()));
}
return response;
}
if (url.pathname === EVENT_PATH) {
// Forward event beacons to Clickport
const request = new Request(event.request);
request.headers.delete('cookie');
return fetch('https://clickport.io/api/event', request);
}
return new Response(null, { status: 404 });
}
Step 3: Route the Worker to your domain
In your Worker's settings, go to Triggers → Routes and add a route for your domain:
*yoursite.com/js/* # matches the script path
*yoursite.com/api/* # matches the event path
Step 4: Update your snippet
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
Since the script loads from your own domain, the tracker automatically sends events to yoursite.com/api/event. No cpConfig override needed.
Vercel
If your site is deployed on Vercel, you can proxy the tracker using rewrite rules in vercel.json.
Step 1: Add rewrites to vercel.json
{
"rewrites": [
{
"source": "/js/app.js",
"destination": "https://clickport.io/tracker.js"
},
{
"source": "/collect/api/event",
"destination": "https://clickport.io/api/event"
}
]
}
Step 2: Update your snippet
<script>
window.cpConfig = { api: '/collect' };
</script>
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
The cpConfig.api override is needed here because the script path (/js/) and event path (/collect/) use different prefixes.
Netlify
On Netlify, you can proxy using a _redirects file in your publish directory.
Step 1: Add rewrite rules
Create or edit the _redirects file in your site's publish directory:
/js/app.js https://clickport.io/tracker.js 200
/collect/api/event https://clickport.io/api/event 200
The 200 status code is important. It tells Netlify to proxy the request (rewrite), not redirect. A 301 or 302 would send the browser to clickport.io directly, which defeats the purpose.
Step 2: Update your snippet
<script>
window.cpConfig = { api: '/collect' };
</script>
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
src to a CDN URL, breaking the proxy. If this happens, disable "Bundle JS" and "Minify JS" in your site's build settings, or use an absolute URL (https://yoursite.com/js/app.js) instead of a relative path.
Nginx
If you manage your own server with Nginx, add these location blocks to your server configuration.
proxy_cache_path /var/run/nginx-cache/cpcache levels=1:2
keys_zone=cpcache:10m inactive=30d max_size=100m;
server {
# ... your existing server config ...
location = /js/app.js {
proxy_pass https://clickport.io/tracker.js;
proxy_set_header Host clickport.io;
proxy_buffering on;
proxy_cache cpcache;
proxy_cache_valid 200 5m;
proxy_cache_use_stale updating error timeout http_500;
}
location = /collect/api/event {
proxy_pass https://clickport.io/api/event;
proxy_set_header Host clickport.io;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_http_version 1.1;
proxy_buffering on;
}
}
Update your snippet:
<script>
window.cpConfig = { api: '/collect' };
</script>
<script defer data-site="ck_your_key" data-domain="yoursite.com"
src="/js/app.js"></script>
/var/run/nginx-cache may not survive reboots. To make it persistent, create a systemd tmpfiles rule: echo "D /var/run/nginx-cache 0755 root root -" > /usr/lib/tmpfiles.d/nginx-cache.conf
Verify your setup
After setting up the proxy, open your site in a browser and check the Network tab in developer tools:
- Script request - Look for a GET request to your proxy path (e.g.
/js/app.js). It should return status200with JavaScript content. - Event request - Navigate to a page and look for a POST request to your event path (e.g.
/collect/api/event). It should return status200.
If both requests succeed through your domain, the proxy is working. Enable an adblocker and repeat the test to confirm requests still go through.
How the tracker resolves the endpoint
Understanding this helps you debug proxy issues. The tracker determines where to send events in this order:
- If
cpConfig.apiis set, use that as the base URL and append/api/event. - Otherwise, take the script's
srcattribute, strip/tracker.js(or whatever the filename is), and use that as the base URL.
This means that if the script loads from https://yoursite.com/js/app.js, the tracker sends events to https://yoursite.com/js/api/event by default. If that path does not match your proxy config, set cpConfig.api to the correct base path.
Important notes
- Forward the
X-Forwarded-Forheader. Clickport uses this header to determine the visitor's IP for geolocation. If your proxy does not forward it, all visitors will appear to come from your server's IP address. - The tracker sends events as
text/plain. This is intentional. Some proxies reject or transformapplication/jsonrequests. Make sure your proxy forwards the body as-is without parsing or modifying it. - Do not strip cookies. Clickport does not use cookies, but your proxy should forward the request body and headers without modification (except adding forwarding headers).
- Caching the script is recommended. The tracker script changes infrequently. Cache it for 5 minutes to reduce load on both your proxy and Clickport's servers.