The MDN docs say that the visibilitychange
event
fires with a visibilityState of hidden when a user navigates to a new page, switches tabs, closes the tab, minimizes or closes the browser, or, on mobile, switches from the browser to a different app.
While I recall having experience with this being true, it looks like it isn't anymore (at least not on either Chrome or Firefox). I'm currently on desktop Chrome Version 121.0.6167.160
To reproduce, if I look at the end-of-session analytics example and basically copy-paste the function into the browser console like
document.onvisibilitychange = () => {
console.log(document.visibilityState);
};
then I'll see "hidden" and "visible" logged to the console as I switch between open tabs. However, if I then click a random link that takes me to another page, nothing is logged and so I'm left to assume that the visibilitychange event is not firing in this case (the preserve-log option is checked in the dev console).
And just as an ultra-sanity check, the same behavior happens if I replace the console log with an actual sendbeacon request.
It sounds unlikely that a browser bug was pushed since it's happening in both chrome and firefox, so what am I missing / not understanding here?
No it still fires, you must have messed up with your tests.
This is being tested in web-tests which are ran as part of the update workflow of every browser, at every code change, so you can be sure that it won't stop working.
Note that using the console may be unreliable because the page that controls the console is unloaded and thus may not be able to communicate with the console in time. Instead prefer using a popup window as a "console" and write to that popup from your main page in the visibilitychange event. This way, even when the main page is navigated away, the popup state is preserved and you can see if it received the changes set from the event or not. The web-test actually does the inverse, opening a popup and listening for the event in it instead, but the gist is the same.