Frameworks
Serve Seentics from your own domain
Load the tracker from a path on your site instead of seentics.com. Pick the mode that fits: serving the script is safe; sending events through your domain has a cost.
Why
Some privacy extensions and filter lists block requests to analytics hosts by name. A script loaded from yoursite.com/_seentics/… is a same-site request and is not matched by host. It also keeps the page's requests on your own origin, which helps with strict content-security policies.
Read the location caveat before proxying events
How the tracker finds its files
The tracker reads its own <script> element. Everything else is derived from it, and each part can be overridden:
- Extension files (heatmaps, automations, replay, the DOM recorder) are fetched from the same folder as the script, by replacing the file name in
src. They are content-hashed, so proxy the whole folder, not justseentics.min.js. - Events and configuration go to
data-api-hostplus/api/v1/tracker/…. Whendata-api-hostis not set, the host is the origin of the script. The exception isseentics.com, whose scripts always send tohttps://api.seentics.com. - So when you serve the script from your own domain without setting
data-api-host, events are sent to your domain at/api/v1/tracker/collect. Setdata-api-host(theapiHostoption in the framework packages) to keep sending events straight to Seentics.
Mode A: serve only the script (recommended)
Proxy the /trackers/ folder from https://seentics.com to a path on your site, and set apiHost to https://api.seentics.com. Events still go to Seentics from the visitor's browser, so the visitor's real address, location and consent region are intact. The script itself is no longer a third-party request.
<script defer
data-website-id="YOUR_WEBSITE_ID"
data-api-host="https://api.seentics.com"
src="/_seentics/trackers/seentics.min.js"></script>This does not hide the events request from a blocker that matches api.seentics.com. That is what Mode B is for.
Mode B: send events through your domain
Also proxy /api/v1/, and set data-api-host to your site plus the same prefix (https://yoursite.com/_seentics). Left unset, the tracker would use your site's root and miss the proxy. Nothing then leaves your origin.
What this does to location, on Seentics Cloud
Seentics reads the visitor's address from a header set by the network in front of it. When the request comes from your Vercel, Netlify or Cloudflare proxy, the address Seentics sees is the proxy's, not the visitor's. There is no way for a third-party proxy to tell Seentics Cloud the real address: Seentics only accepts one from its own dashboards, authenticated with a secret.
The tracker's source records the same problem: when its own dashboard forwarded events through a Cloudflare Pages Function, every visitor was located at one US address, EU visitors were recorded without the consent that the consent-region check asks for, and every country, region and city report was wrong. Expect the same from any proxy. This has not been measured for each host.
If you host Seentics yourself, this is not a problem as long as your proxy forwards the visitor's address and the server is configured to trust it (TRUST_PROXY=true and the header your proxy sets in CLIENT_IP_HEADER; see the deployment guide).
- Origin check. Seentics refuses events whose
Origin(or, if absent,Referer) host differs from the website's registered URL (www.is ignored). A browser sends your site as the origin, and a rewrite that forwards headers keeps it. If a proxy replaces the header you will see403 domain mismatchon/collect. Header forwarding has not been verified on each platform below; test with a real visit. - Path clashes. Proxying
/api/v1/at your site root would shadow your own API under that path. Use a prefix such as/_seentics/(below), withdata-api-hostset to your site plus that prefix.
Configs
Each example serves the script folder under /_seentics/trackers/ (Mode A). The lines marked Mode B add the API.
Next.js
const { withSeentics } = require('@seentics/next');
module.exports = withSeentics({}, { path: '/_seentics' });withSeentics adds the rewrites; proxiedProps() gives the matching component props (src and apiHost). If you prefer to write the rewrites yourself:
module.exports = {
async rewrites() {
return [
{ source: '/_seentics/trackers/:path*', destination: 'https://seentics.com/trackers/:path*' },
// Mode B only:
// { source: '/_seentics/api/v1/:path*', destination: 'https://api.seentics.com/api/v1/:path*' },
];
},
};Vercel (any framework)
{
"rewrites": [
{ "source": "/_seentics/trackers/:path*", "destination": "https://seentics.com/trackers/:path*" }
]
}Mode B: add { "source": "/_seentics/api/v1/:path*", "destination": "https://api.seentics.com/api/v1/:path*" }.
Netlify
[[redirects]]
from = "/_seentics/trackers/*"
to = "https://seentics.com/trackers/:splat"
status = 200
force = true
# Mode B only:
# [[redirects]]
# from = "/_seentics/api/v1/*"
# to = "https://api.seentics.com/api/v1/:splat"
# status = 200
# force = trueA status of 200 makes Netlify proxy the request instead of redirecting the browser.
Cloudflare
A Pages _redirects file cannot do this: its 200 rewrites only apply to paths on your own site, not to another domain. Use a Worker route (or a Pages Function) on your zone:
export default {
async fetch(request) {
const url = new URL(request.url);
if (!url.pathname.startsWith('/_seentics/trackers/')) return fetch(request); // not ours
const target = 'https://seentics.com/trackers/' + url.pathname.slice('/_seentics/trackers/'.length);
return fetch(target, { cf: { cacheEverything: true, cacheTtl: 3600 } });
},
};Route it to yoursite.com/_seentics/*. This is Mode A only. Do not use a Worker for the API: see the location caveat above, which applies to Workers as much as to other proxies.
nginx
location /_seentics/trackers/ {
proxy_pass https://seentics.com/trackers/;
proxy_set_header Host seentics.com;
proxy_ssl_server_name on;
proxy_cache_valid 200 1h;
}
# Mode B only:
# location /_seentics/api/v1/ {
# proxy_pass https://api.seentics.com/api/v1/;
# proxy_set_header Host api.seentics.com;
# proxy_ssl_server_name on;
# proxy_set_header Origin $http_origin;
# }Check it
- Open your site with the Network tab open.
seentics.min.jsshould come from/_seentics/trackers/, and the extension files that load after it from the same folder. - The
collectrequest goes toapi.seentics.com(Mode A) or to your domain (Mode B), and returns200. - In Seentics, visit from a different country than your server (a phone on mobile data is enough) and check the Countries report. A country that matches your host's data centre for every visit means the address is being lost.
Back to Frameworks.