Seentics

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

Choose Mode A unless you host Seentics yourself. Mode B hides your visitors' addresses from Seentics Cloud, which breaks country and city reports and the consent region check. Details below.

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 just seentics.min.js.
  • Events and configuration go to data-api-host plus /api/v1/tracker/…. When data-api-host is not set, the host is the origin of the script. The exception is seentics.com, whose scripts always send to https://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. Set data-api-host (the apiHost option 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.

the tag
<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 see 403 domain mismatch on /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), with data-api-host set 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

next.config.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:

next.config.js
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)

vercel.json
{
  "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

netlify.toml
[[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 = true

A 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:

worker.js
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

nginx.conf
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.js should come from /_seentics/trackers/, and the extension files that load after it from the same folder.
  • The collect request goes to api.seentics.com (Mode A) or to your domain (Mode B), and returns 200.
  • 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.