Skip to content
fusionaly_ GitHub

Data Integrity

How Fusionaly keeps fake events and bot traffic out of your analytics, and what no analytics tool can stop

Fusionaly filters fake events and bot traffic on your server. The code is open source, so you can check how it works.

Event
→ Rate limit more than 70 requests a minute from one IP: 429
→ Origin check not from one of your websites: 403
→ Excluded IPs from your own IP addresses: not stored
→ Queue ingested_events
→ Bot filter from a known bot or crawler: skipped
→ Dashboard

The first three checks run when the event arrives. The bot filter runs later, when the event processor reads the queue.

Fusionaly allows 70 requests a minute from one IP address. Above that, it answers 429. One visitor sends about one request for each page view or custom event, so a real visitor stays far below the limit.

The limit stops a runaway script, or one machine that floods the events endpoint. It does not stop an attack from many IP addresses.

Visitors who share one IP address, for example on an office network or a mobile network, also share the limit. When the endpoint answers 429, the SDK waits and sends the event again. See Retries.

Every event must come from a website you added to Fusionaly. Fusionaly reads the Origin header, or the Referer header when Origin is missing. It rejects the event with a 403 when neither header names one of your websites, or a subdomain of one when subdomain tracking is on.

Browsers set these headers themselves. A script on another website cannot send events as your website from a visitor’s browser.

Add your own IP addresses in Administration → Ingestion. Fusionaly does not store events from them, so your own visits do not count.

Fusionaly checks the User-Agent of each event against a list of known bots and crawlers, for example Googlebot and bingbot. It also skips headless browsers, such as HeadlessChrome, when the User-Agent or the Sec-CH-UA header names them.

The event processor runs this check after the event is in the queue. A bot event stays in the queue table until the queue cleanup deletes it, but it never reaches the dashboard.

The list catches bots that say what they are. A bot that copies the User-Agent of a real browser passes the check. For stronger protection, put Cloudflare in front of your instance. Cloudflare’s bot detection catches bots that the User-Agent check misses. Behind Cloudflare, Fusionaly still finds the visitor’s real IP address, so the rate limit and the excluded IP addresses still work.

The events endpoint is public, as it is for every analytics tool. A program outside a browser can set any header it likes. So it can send fake events with the User-Agent of a real browser and the Origin of your website. The server cannot tell these events from real ones. The rate limit keeps the number from one IP address small.

Fusionaly does not check the Sec-Fetch-Site header on events. Some real browsers do not send it: Safari before 16.4, older in-app browsers and WebViews, and some privacy extensions. A script can set it anyway. So the check stopped real visitors, not fake events.

  • Auditable: read the code on GitHub.
  • Changeable: the rate limit and the bot list are in the code, not in the settings. To change them, change the code and build your own image.
  • Local: all checks run on your server. Fusionaly sends your analytics data to no other service. Its only outbound call is a weekly GeoLite2 download from MaxMind, after you add a MaxMind license key.