Start here

Script proxy

Serve the Sporetag script and its event endpoint from your own domain with a tiny Cloudflare Worker, so ad blockers drop fewer of your visits.

A script proxy serves the script and the event endpoint from your own domain. The browser only talks to your site, so blockers that match on our address let it through. Your numbers get closer to the real count.

The script proxy is on paid plans: Solo, Studio, Agency and Custom. Free does not include it.

How it works

  1. Your site loads the script from a path on your own domain, such as /st/s.js.
  2. A small proxy on your domain fetches https://sporetag.com/s.js and returns it.
  3. Events go to /st/api/e on your domain. The proxy forwards them to https://sporetag.com/api/e.

The site's Integrations tab has each snippet below with your domain and token filled in, ready to copy.

The visitor's address

Behind a proxy, the request that reaches Sporetag comes from your proxy's server. Without help, every visitor would look like the same address in the same country, and unique counts would be wrong.

So the proxy passes the visitor's real address in a header. Sporetag only believes that header when the proxy also sends your site's proxy token:

HeaderValue
x-sporetag-proxy-keyThe site's proxy token
x-sporetag-client-ipThe visitor's IP address
x-sporetag-client-countryOptional. Two letters, such as DE

Make the token in the site's Integrations tab, under Script proxy. Keep it in your proxy's settings. It never goes into a page, and the browser never sees it.

Why a token: anyone can type an X-Forwarded-For header, so Sporetag never reads it. Without a valid token, Sporetag uses the address Cloudflare saw, which a browser cannot fake. A proxy without the token still works. It just counts every visitor from the proxy's own address.

If the token leaks, press Make a new token and update your proxy. The old one stops working at once.

Cloudflare Worker

Create a Worker on a route of your site, such as shop.example.com/st/*. Add the token as a secret named PROXY_KEY (npx wrangler secret put PROXY_KEY).

JavaScript
// Sporetag script proxy. Route: <your domain>/st/*
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const path = url.pathname.replace(/^\/st/, '');
    if (path === '/s.js' || path === '/sa.js') {
      return fetch('https://sporetag.com' + path + url.search, { cf: { cacheTtl: 300 } });
    }
    if (path === '/api/e' && request.method === 'POST') {
      const headers = new Headers(request.headers);
      headers.set('x-sporetag-proxy-key', env.PROXY_KEY);
      headers.set('x-sporetag-client-ip', request.headers.get('cf-connecting-ip') || '');
      headers.set('x-sporetag-client-country', request.cf?.country || '');
      return fetch('https://sporetag.com/api/e', { method: 'POST', headers, body: request.body });
    }
    return new Response('Not found', { status: 404 });
  },
};

Next.js on Vercel

A plain rewrite in next.config.js works, but cannot add headers, so every visitor counts from Vercel's address. Use middleware instead. Set SPORETAG_PROXY_KEY in the project's environment variables.

TypeScript
// middleware.ts
import { NextResponse, type NextRequest } from 'next/server';

export const config = { matcher: '/st/:path*' };

export function middleware(req: NextRequest) {
  const path = req.nextUrl.pathname.replace(/^\/st/, '');
  const target = new URL(path + req.nextUrl.search, 'https://sporetag.com');
  const headers = new Headers(req.headers);
  if (path === '/api/e') {
    headers.set('x-sporetag-proxy-key', process.env.SPORETAG_PROXY_KEY ?? '');
    headers.set('x-sporetag-client-ip', (req.headers.get('x-forwarded-for') ?? '').split(',')[0].trim());
    headers.set('x-sporetag-client-country', req.headers.get('x-vercel-ip-country') ?? '');
  }
  return NextResponse.rewrite(target, { request: { headers } });
}

Vercel sets x-forwarded-for itself, so here it is safe to read.

nginx

Inside your server { } block:

nginx
location = /st/s.js  { proxy_pass https://sporetag.com/s.js;  proxy_set_header Host sporetag.com; proxy_ssl_server_name on; }
location = /st/sa.js { proxy_pass https://sporetag.com/sa.js$is_args$args; proxy_set_header Host sporetag.com; proxy_ssl_server_name on; }
location = /st/api/e {
  proxy_pass https://sporetag.com/api/e;
  proxy_set_header Host sporetag.com;
  proxy_ssl_server_name on;
  proxy_set_header x-sporetag-proxy-key "YOUR_PROXY_TOKEN";
  proxy_set_header x-sporetag-client-ip $remote_addr;
}

If nginx sits behind a load balancer, set $remote_addr from the real client with the real_ip module first.

The tag

Point the tag at your own path, and tell the script where to send events with data-api.

HTML
<script defer data-site="shop.example.com" data-api="/st/api/e" src="/st/s.js"></script>

In Attribution mode the tag loads sa.js instead:

HTML
<script defer data-site="shop.example.com" data-mode="attribution" data-api="/st/api/e" src="/st/sa.js?d=shop.example.com"></script>

Check it

Open your site, then the site's dashboard. The visit shows within a few seconds, with your own country. If every visit shows the same country, the token or the address header is missing.

Something missing or wrong? Email hello@sporetag.com.