MOVED to main documentation page.
If a browser window is placed in the background, for instance because the user puts the focus on another page, the monetization stream should stop and the monetization state should be set to idle
. Users cannot read the page, so they should not be charged. Pages that stream audio ane an exception: they will continue to be monetized, since users continue to consume (part of) their content.
For potentially useful events see also Page Lifecycle API.
A window's position in foreground or background is determined by its visibilityState
— the extension listens to the visibilitychange
event that fires whenever visibilityState
switches. The state becomes hidden
when no pixel of that window is currently visible on the screen. Thus, the following actions will send a window to the background:
Or the page? To be tested with a browser window with massive chrome.
For Chrome it's window, and not page. If just the tabs interface is visible, this does not count as hidden.
If even a single pixel of the window remains visible the visibilityState
does not change and the page will continue to receive payments. This can lead to odd situations where users think they have sent a page to the background, but the monetization stream actually continues because a tiny sliver remains visible. The system is not perfect, but more fine-grained definitions of visible and invisible are extremely hard to implement, and will likely lead to many more false positives or negatives.
I made up this rule. I think we need something like it, though.
Browser windows that stream audio form an exception to these rules. They will continue to receive payments even if they are fully in the background, since users can still hear (part of) the content.
For detecting audio:
let globalPlayState = false; let playList = {}; window.addEventListener('play',logPlay,true) window.addEventListener('pause',logPlay,true) let ctr = 0; function logPlay(e) { let state = e.type === 'play'; let tg = e.target; let check = tg.dataset.audioCheck; if (!check) { check = 'audioCheck' + ctr; ctr++; tg.dataset.audioCheck = check; } playList[check] = state; globalPlayState = false; for (let i in playList) { globalPlayState = globalPlayState || playList[i]; } // globalPlayState is true when any audio is playing }
Not perfect; a video without audio is reported as playing; an audio or video element that's never added to the document does not fire the events, even though it may play audio. Not tested with Web Audio.
Also audible attribute of Chrome extensions. Possibly also useful.