Troubleshooting

When it does not work.

Concrete solutions to common installation and operations problems. Paste in whatever matches your symptom, or jump straight to the section from the menu below.

"Loading the script violates the Content Security Policy"

Symptom
You have pasted in the code but nothing happens. The browser console shows something like:
Loading the script 'https://sparlos.se/script.js' violates the
following Content Security Policy directive: "script-src 'self'".
Cause
Your site sends a Content-Security-Policy header that only allows scripts from your own domain name. The browser therefore refuses to load our tracker. This is something you as the site owner have turned on (or inherit through a hosting provider like Vercel, Netlify or Cloudflare Pages).
Solution

Recommended: add sparlos.se *.sparlos.se to your CSP.

A bare apex plus a wildcard subdomain future-proofs against us moving the tracker to a dedicated subdomain (for example cdn.sparlos.se or events.sparlos.se) without you having to touch your CSP again.

Option 1: Do you only have default-src?

One line is enough. default-src is the fallback for all fetch directives that are not explicitly set.

Content-Security-Policy:
  default-src 'self' sparlos.se *.sparlos.se;

Option 2: Do you have explicit script-src and connect-src?

Common on security-conscious sites (Vercel default, banks, healthcare). In that casedefault-src is overridden per directive and you have to add Spårlös to both.

Content-Security-Policy:
  script-src 'self' sparlos.se *.sparlos.se;
  connect-src 'self' sparlos.se *.sparlos.se;
  • script-src allows the <script> tag to load.
  • connect-src allows the tracker to POST events to /api/event. Without this the script loads but every pageview is blocked separately.
  • Do you use script-src-elem or connect-src-elem explicitly? Add Spårlös there too, they override script-src and connect-src in turn.

Where do you put the CSP header? In your web server config (nginx, Apache), in a middleware/route (Next.js, Express), or in a <meta http-equiv="Content-Security-Policy"> tag in the HTML head. It does not matter which method, the addressing is the same.

Do you prefer an explicit protocol (some security policies require it)? https://sparlos.se https://*.sparlos.se works identically on HTTPS sites. The bare-host version above inherits the protocol from the page, which is always HTTPS in production.

If you cannot follow the solution
If CSP is locked down by IT and you cannot change it: use our WordPress plugin (proxy mode serves the script via your own domain), or self-host the script on the same domain as your site (download script.js once, serve from https://your-site.com/script.js; connect-src to sparlos.se must still be allowed).

Adblockers block the tracker

Symptom
You yourself see no pageviews when you visit your site, but friends without an adblocker do. The browser console typically shows net::ERR_BLOCKED_BY_CLIENT on script.js or /api/event.
Cause
uBlock Origin, AdGuard, Brave Shields, Privacy Badger and NoScript match known analytics hostnames (including sparlos.se) on their blocklists. It is ironic since we are cookie-free, but those lists are conservative and match on domain name rather than behavior.
Solution

For WordPress sites: use our WordPress plugin with proxy mode on (the default). The script and the event endpoint are then served via your own domain, which adblockers cannot match without blocking your entire site.

For other frameworks: build your own reverse proxy:

# Next.js / Vercel: src/app/sparlos/script.js/route.ts
export async function GET() {
  const upstream = await fetch('https://sparlos.se/script.js');
  return new Response(await upstream.text(), {
    headers: {
      'content-type': 'application/javascript',
      'cache-control': 'public, max-age=3600',
    },
  });
}

Plus a parallel route for /sparlos/event that proxies the POST to https://sparlos.se/api/event with the visitor IP in the x-forwarded-for header (we need it for country lookup and discard it immediately after).

If you cannot follow the solution
Accept the loss. International research: roughly 30-40% of a tech audience runs an adblocker, 10-15% among a general audience. If your target group is NOT developers/tech, the loss is under 15%, which still beats GA4 plus a cookie banner that loses 30-60% on mobile.

The script loads but no data shows on the dashboard

Symptom
You have installed the script, it shows up in view-source, the browser loads it without errors, but the dashboard shows 0 pageviews.
Solution

Go through the list in this order:

  1. Check the site_id. Open view-source and find <script data-site="...">. The site ID must match the one shown on your site settings page in Spårlös. Common mistake: pasting in the wrong site code snippet.
  2. Wait 30 seconds and reload. The dashboard does not update in real time, it polls every 5 seconds. The first pageview should appear in the Live view within 30 seconds.
  3. Have you enabled DNT or GPC? We respect Do Not Track and Global Privacy Control both on the client and the server side. If YOU have it enabled in your browser, your visits are not counted. Test in another browser or turn off DNT/GPC temporarily to verify.
  4. Are you using a bot-like User-Agent? Our bot filter drops GPTBot, ClaudeBot, headless Chrome, Playwright and 50+ others. If you test with curl or an automation tool, the request is not counted.
  5. Click "Test installation" on the snippet. We have a button on the site settings page that actually goes out and fetches your homepage to verify that the code snippet is there AND that we have seen pageview events from your site_id in the last hour.
  6. CSP or adblocker? See the CSP and Adblockers sections above.
  7. Localhost? See Testing on localhost below. We bail by default on localhost and private IP addresses.
  8. Path blocklist? If you have configured a path blocklist in the site settings and your test page matches a pattern (for example /admin/*), the request is ignored silently.

Cloudflare WAF or rate limit blocks events

Symptom
The script loads, some events come through but not all. Or you see 403 Forbidden / 429 Too Many Requests in the Network tab for /api/event.
Cause
Cloudflare Bot Fight Mode, a WAF rule or a rate-limit rule is hitting the event request. The most common cause: a rule that blocks cross-origin POST requests, or an aggressive bot detection that tags the tracker as "challenge-required".
Solution
  • Allow-list sparlos.se as an origin in your WAF.
  • If you have a rate-limit rule on /api/event (why would you? it is our endpoint, not yours), remove it.
  • Bot Fight Mode: add a bypass rule for the Spårlös tracker User-Agent Sparlos-Uptime/1.0 (if you also use the uptime monitor against your own site).
  • Cloudflare Workers: if you have a worker that modifies requests, check that it does not strip the x-forwarded-for or cf-connecting-ip headers (we use them for country lookup).

The tracker does not work on localhost

Symptom
You develop locally against http://localhost:3000 or similar and no pageview comes through.
Cause
The tracker has a localhost guard that bails by default. It protects you from filling your production dashboard with development traffic that is not representative.
Solution
Add data-include-localhost="true" on the script tag during development:
<script defer
  data-site="YOUR_SITE_ID"
  data-include-localhost="true"
  src="https://sparlos.se/script.js">
</script>

Do not forget to remove the attribute before deploying to production. Otherwise you risk your team localhost test traffic counting against your monthly quota.

SPA with hash routing (/#/route) only counts the start page

Symptom
You run a SPA built with React Router HashRouter, Vue HashHistory or similar. The dashboard only shows / regardless of which page the visitor is on.
Cause
HashRouter URLs like /#/cart always have location.pathname === '/'. We have a safeguard that detects the #/ pattern and uses the hash as the pathname instead, but it only triggers on the hashchange event.
Solution

For modern SPAs (React Router v6+ with BrowserRouter, Vue Router 4 with createWebHistory, Next.js, SvelteKit, Nuxt) we hook in automatically via pushState/replaceState/popstate. You do not need to do anything.

For HashRouter or other exotic patterns: call manually on every navigation:

window.sparlos = window.sparlos || {};
// On every navigation in your SPA:
window.sparlos.pageview && window.sparlos.pageview();

For the cart-drawer pattern (a modal that changes the UX but not the URL), trigger a pageview anyway if you want to measure the interaction as a page. Or use goal tracking on a thank-you redirect URL.

WordPress: all pages show as /

Symptom
You have installed the WordPress plugin, the traffic shows on the dashboard, but ALL pageviews have the path / regardless of which page the visitor is actually on.
Cause
WordPress is configured with "Plain" permalinks (?p=123 URLs). In that case every page technically has the path / in the URL and our tracker has nothing else to go on.
Solution
WordPress admin → Settings → Permalinks → choose "Post name" or similar, click Save. Our plugin shows a yellow warning on its own settings page when we detect that you are running Plain permalinks, so it should be easy to find.

Spårlös shows fewer visitors than GA4

Symptom
You run Spårlös and GA4 in parallel and Spårlös shows 10-30% fewer unique visitors.
Cause
Not a bug. Three normal differences:
  • We filter out more bots. GA4 counts traffic from GPTBot, headless Chrome, scrapers and similar as real visitors. We remove them at ingest. Typical difference: 5-15% of raw traffic.
  • We do not link visitors across days. Our visitor hash rotates daily (privacy by design). If the same person visits your site on Monday and Tuesday, that is 2 unique visitors to us, 1 to GA4 (which stores a persistent visitor ID in a cookie).
  • We respect DNT and GPC. GA4 counts traffic from users who have Do Not Track enabled. We do not. Small effect (~5%) on a general audience, larger on tech.
Solution
This is nothing to fix. It is the difference between privacy-first counting and ad-tech counting. Consistency matters more than the "right" number. When you start measuring with Spårlös, that is the baseline you track trends against. No analytics tool gives exactly the same numbers, not even GA4 between two properties.

Does Spårlös set cookies on the visitor device?

Symptom
You see a cookie in your browser and think it is from us, or you need to confirm to your compliance person that we really do not set any cookie.
Cause
We set NO cookies on the visitor device. The only cookie Spårlös sets is the authentication cookie sparlos_session, and it is set ONLY when YOU log in to the dashboard on sparlos.se. It never lands on your visitors devices or your site domain.
Solution

Open devtools on your site: Application → Cookies → https://your-site.com. No cookies with "sparlos" or similar should be there.

Cookies you do see come from other sources: WordPress (wordpress_logged_in_*), Cloudflare (__cf_bm), Stripe (__stripe_mid on checkout pages), Google reCAPTCHA, Facebook Pixel, etc. Spårlös contributes zero.

Tracking subdomains and multiple sites

Symptom
You have blog.your-site.com and app.your-site.com as separate subdomains and want to track them either as ONE site or as SEPARATE ones.
Solution

As one site: use the SAME data-site="..." in the code snippet on all subdomains. Paths land in the same dashboard, and sorting shows where users land regardless of subdomain.

As separate sites: create one site each in Spårlös (with a unique site_id per subdomain) and use the respective ID. On Starter and up the number of sites is unlimited so this costs nothing extra.

Cross-subdomain visitor tracking does NOT happen regardless of which approach you choose. Our visitor hash includes the site_id, so the same visitor moving between blog.your-site.com and app.your-site.com is counted as two different unique visitors. That is intentional (privacy by design).

Still not solved?

Email [email protected] with a description of the symptom, which browser and version, and if possible a screenshot of the Network tab. We reply within 24 working hours.

Back to the documentation

Stop sending data to the US. Start today.

Get the same insights as from Google Analytics. Without a banner, without cookies, without legal headaches.

Troubleshooting · Spårlös installation and known issues | Spårlös