plausible / plausible-tracker

Frontend library to interact with Plausible Analytics
https://github.com/plausible/plausible-tracker
MIT License
214 stars 46 forks source link

Using Navigator.sendBeacon for sending data #16

Open flaming-codes opened 2 years ago

flaming-codes commented 2 years ago

The current implementation of the plausible-tracker uses the common XMLHttpRequest for submitting analytics data. Yet with advancements in browser engines, a more specialized submit-method is available via the navigator, called sendBeacon, purpose-build for analytics requests.

MDN Documentation

Detailed Description

On platforms that support both a navigator as well the sendBeacon function, it would make sense to adopt this API for submitting analytics-data by progressively enhancing the request-module of plausible-tracker. A short summary of the advantages compared to XMLHttpRequest (taken from MDN):

B/c the submit-event gets queue and reliably sent by browser, using sendBeacon should have a zero-impact on transmitting analytics data while also guaranteeing that the data gets sent, eventually.

Using navigator.sendBeach would therefore ready plausible-tracker for best usage in modern browsers.

Context

Benefits explained before.

Possible Implementation

As a first draft, a simple if/else check for compat should be sufficient to determine the correct submit-function to use.

ukutaht commented 2 years ago

Thanks for the suggestion!

I wonder if anyone is already using Plausible with sendBeacon... it wouldn't be to difficult to prototype.

We're discussing with @RobertJoonas that he might give it a go over winter. Let's see. Sendbeacon is definitely interesting for analytics.

flaming-codes commented 2 years ago

I haven't looked into the implementation of other OSS privacy-focused trackers, but using sendBeacon might actually be a USP ("modern API, zero impact implementation, reliable eventual transmission"), as the others most probably rely on XMLHttpRequest/fetch. But that's just my 2 cents 😄Either way, keep up the good work, plausible is a very nice service!

Joelius300 commented 2 years ago

Heya

This looks great (and would solve #12 if I understand correctly, which would be lovely) ~but has at least one downside that comes to mind immediately. Tracker-blocking.~

I wanted to say that these beacon requests may be blocked by default by uBlock but it turns out that's not the case anymore. They are filtered like all other requests and only behind-the-scenes ones are blocked (not sure if that would apply here).

So instead I'll expand on the ad-block issues. Unfortunately, plausible scripts are blocked by default in uBlock through the EasyPrivacy list (it's kinda sad that you need to jump through hoops like that with privacy friendly tracking but nothing we can do about that). This can be avoided by using the npm package directly or hosting the script on a different domain under a different file-name.
Luckily none of the event requests made to actually send the tracking data appear to be blocked (if I understand uBlock correctly, they could easily do that) so this should also apply to the beacons that would be sent by sendBeacon (as they get passed through the same filters).

Tl;dr: I don't think sendBeacons would cause any issues with ad-blockers (uBlock at least) as long as behind-the-scene request are avoided but they could also be blocked just as easily as the current approach.

ukutaht commented 2 years ago

@Joelius300 Thanks for this. What are behind-the-scene requests?

Joelius300 commented 2 years ago

@Joelius300 Thanks for this. What are behind-the-scene requests?

It appears to be terminology by uBlock meaning the following.

[from the outdated part] Behind-the-scene network requests are network requests which uBlock cannot associate with a specific tab in your browser: these requests come from somewhere, but uBlock is missing information to report exactly from where.

[from the updated part] When this documentation was created, the behind-the-scene network requests uBlock Origin was able to see and filter, originated from many places, such as those from other extensions or from various browser operations (ex.: real-time search suggestions). Since then things have changed: uBO no longer can see network requests from other extensions, and behind-the-scene network requests are now quite less frequent. Furthermore, the webRequest API now provides more context to event listeners, such that it is often possible to still filter properly even when it's not possible to know from which exact tab a network request originates. [...] uBO 1.15.20, the behind-the-scene scope will no longer be on the Trusted sites list by default, meaning network requests from the behind-the-scene scope will be subject to filtering by default.

I'm referring to this Wiki page but as it says, it's partly outdated. If you're using uBlock, you can open the logger and switch to the "tabless" tab. I've found that reddit.com and blick.ch which appear to send behind-the-scene xhr requests (those appear to be filtered like any other requests). I've not seen any behind-the-scene beacon requests and as mentioned here those would still be blanket blocked it seems (again, rather old reference but I've not found any evidence against it).

mvolfik commented 2 years ago

Hi all! I'm one of the people who ran into issues with automatic outbound link tracking, and decided to do it manually with sendBeacon. However, that would require manually crafting the request and everything, so I had an idea: what does the core team think about adding an optional value useBeacon to the trackEvent(..., options) object? And the same flag could be also added to all the enableAuto[...] functions.

These flags would default to false (and could be marked as experimental for now), so it wouldn't affect existing customers, but it would allow testing this in the wild with a single implementation (that could possibly be later made the default), instead of everyone having to do this on their own?

I'd be happy to contribute a PR for this (in about three weeks though, need to study for my high school graduation exams now :laughing: ).

Edit: I realized that maybe the flag would be better in the main Plausible(), since if somebody is willing to risk the switch, they would probably do it for everything

A5rocks commented 2 years ago

I tried to add this in #45. However, I'm a bit unsure of which of these to do:

Currently I have the 2nd implemented, but the 1st is IMO better. I personally like people to have the right defaults and if they are (for instance, this is what I am trying to do) sending an event right when a certain outbound button is pressed, Navigator#sendBeacon is absolutely what they want for reasons listed on MDN.

Joelius300 commented 2 years ago

Currently I have the 2nd implemented, but the 1st is IMO better

Agreed. Unless we find that beacon request have a negative impact for example with ad-blockers, I think the default should absolutely use beacons.

raikasdev commented 2 months ago

Seems like uBlock Origin blocks all beacon requests :-1: