segmentio / analytics-next

Segment Analytics.js 2.0
https://segment.com/docs/connections/sources/catalog/libraries/website/javascript
MIT License
413 stars 138 forks source link

Beacon API support #1167

Closed erykpiast closed 1 month ago

erykpiast commented 1 month ago

Did you consider adding support for the Beacon API as a "transport layer" alternative to fetch/XHR? This native API is created with analytics in mind and helps increasing reliability of client-side data collection.

To quote MDN.

The Beacon API is used to send an asynchronous and non-blocking request to a web server. The request does not expect a response. Unlike requests made using XMLHttpRequest or the Fetch API, the browser guarantees to initiate beacon requests before the page is unloaded and to run them to completion.

Nowadays the browser support for Beacon API is excellent (96%+), from my perspective is a no-brainer.

To give you an example of what it could help with practically - checkout flows provided externally, e.g. by Stripe. Imagine you have a payment plan selection in your webapp, but the payment itself happens on a different domain. Measuring the conversion - a ratio of clicks on the "Checkout" button in your app and successful payment - it's quite difficult with regular async HTTP requests as they're interrupted when the page unloads. If you redirect to an external domain right in the button click handler and you don't wait for the analytics request to finish, the risk of missing an event is quite high. Delaying the redirection it is not ideal, as it degrades user experience. Beacon API would solve this issue ultimately.

I wonder if there are any concerns about having this as an option? I found this comment from @f2prateek mentioning Beacon API and some reasons to not introduce it. Apart from that, no serious take on it there and no mention whatsoever in this repository, which is quite surprising.

silesky commented 1 month ago

Hey @erykpiast,

Do you know if sendBeacon has improvements over keep-alive?

I wasn't around for the discussion, but IIRC sendBeacon is not used because, like keep-alive, it has body size limitations in browser that are potentially problematic, similar to why we don't use keep-alive for all requests. There is a 64kb limit for all fetch requests with keepalive. So when sending keepalive requests, we are competing with other in-flight keepalive requests, regardless of being Segment related requests or not. We only use keep-alive if 1. the page is 'unloading' and 2. the user is using batching, and I would think that sendBeacon would have the same conditions if it has the same limitations as keep-alive.

By default, segment is unbatched -- it will send events as soon as they enter the Segmentio plugin, so it was not obvious that the risk of losing a single event would outweigh the competing request gotcha, and it's not something that we could conditionally turn 'on' when the page unloads, because per ^, there's nothing to 'flush'.

So, no real reason sendBeacon couldn't be an option, but I'd be interested in exploring more of the pros/cons.