Docs·Proxy guide
Proxy with Express
One route on your Express app serves Spreelytics from /sp/. It needs Node.js 18 or later, for fetch. This guide uses /sp/. Any path works if nothing else on your site uses it and it doesn't contain words like "analytics" or "tracking", which blockers look for.
Add the route
Add this to your app, before your other routes:
const SCRIPTS = "https://cdn.spreelytics.com/cdn/sdk/";
const API = "https://sdk.spreelytics.com/1.0/";
const FORWARD = ["content-type", "user-agent", "origin", "referer", "accept", "accept-language"];
const DROP = ["content-encoding", "content-length", "transfer-encoding", "connection"];
app.use("/sp", express.raw({ type: () => true, limit: "10mb" }), async (req, res) => {
const path = req.path.slice(1);
const query = req.originalUrl.includes("?") ? req.originalUrl.slice(req.originalUrl.indexOf("?")) : "";
const target = (path.startsWith("js/") ? SCRIPTS + path.slice(3) : API + path) + query;
const headers = {};
for (const name of FORWARD) {
if (req.get(name)) headers[name] = req.get(name);
}
// The visitor's IP address. Behind a load balancer or CDN, set app.set("trust proxy", true).
headers["x-forwarded-for"] = req.ip;
const upstream = await fetch(target, {
method: req.method,
headers,
body: Buffer.isBuffer(req.body) && req.body.length ? req.body : undefined,
});
res.status(upstream.status);
// fetch has already unzipped the body, so the encoding and length headers no longer apply.
upstream.headers.forEach((value, name) => {
if (!DROP.includes(name)) res.setHeader(name, value);
});
res.send(Buffer.from(await upstream.arrayBuffer()));
});
Point the script at your proxy
In your Spreelytics snippet, load the script through /sp/js/ and add api_host:
<script src="/sp/js/spreelytics-loader.js"></script>
<script>
Spreelytics.init({
client_key: "YOUR_CLIENT_KEY",
api_host: "https://www.example.com/sp",
});
</script>
Check it works
Open your site with the browser's Network tab open and filtered by /sp/. The script files and
requests like track/page should come from your own domain, with status 200. In Spreelytics,
Settings → Tracking script says "Last seen just now" and Realtime shows you in your own country.
- Wrong country, or
200and nothing arrives: the proxy isn't passing the visitor's IP address inX-Forwarded-For. See The visitor's IP address below. 401: theOriginandRefererheaders didn't arrive, or your domain isn't in Allowed domains.
The visitor's IP address
Express's req.ip is the connection's address. Behind a load balancer, Cloudflare or a host like Render or Heroku, add app.set("trust proxy", true) so it reads X-Forwarded-For, or every visitor arrives from the load balancer's address.
Related
- Proxy overview: the other ways to set it up.
- Filter traffic: which traffic Spreelytics drops.