@@ -325,8 +325,6 @@ export default async function detect( {
325325 /** @type {URLMetric } */
326326 const urlMetric = {
327327 url : currentUrl ,
328- slug : urlMetricsSlug ,
329- nonce : urlMetricsNonce ,
330328 viewport : {
331329 width : win . innerWidth ,
332330 height : win . innerHeight ,
@@ -365,9 +363,24 @@ export default async function detect( {
365363 urlMetric . elements . push ( elementMetrics ) ;
366364 }
367365
368- // TODO: Wait until the page is actually unloading.
366+ if ( isDebug ) {
367+ log ( 'Current URL metrics:' , urlMetric ) ;
368+ }
369+
370+ // Wait for the page to be hidden.
369371 await new Promise ( ( resolve ) => {
370- setTimeout ( resolve , 2000 ) ;
372+ win . addEventListener ( 'pagehide' , resolve , { once : true } ) ;
373+ win . addEventListener ( 'pageswap' , resolve , { once : true } ) ;
374+ doc . addEventListener (
375+ 'visibilitychange' ,
376+ ( ) => {
377+ if ( document . visibilityState === 'hidden' ) {
378+ // TODO: This will fire even when switching tabs.
379+ resolve ( ) ;
380+ }
381+ } ,
382+ { once : true }
383+ ) ;
371384 } ) ;
372385
373386 for ( const extension of extensions ) {
@@ -379,42 +392,22 @@ export default async function detect( {
379392 }
380393 }
381394
382- if ( isDebug ) {
383- log ( 'Current URL metrics:' , urlMetric ) ;
384- }
395+ // Even though the server may reject the REST API request, we still have to set the storage lock
396+ // because we can't look at the response when sending a beacon.
397+ setStorageLock ( getCurrentTime ( ) ) ;
385398
386- // Yield to main before sending data to server to further break up task.
387- await new Promise ( ( resolve ) => {
388- setTimeout ( resolve , 0 ) ;
399+ const body = Object . assign ( { } , urlMetric , {
400+ slug : urlMetricsSlug ,
401+ nonce : urlMetricsNonce ,
389402 } ) ;
390-
391- try {
392- const response = await fetch ( restApiEndpoint , {
393- method : 'POST' ,
394- headers : {
395- 'Content-Type' : 'application/json' ,
396- 'X-WP-Nonce' : restApiNonce ,
397- } ,
398- body : JSON . stringify ( urlMetric ) ,
399- } ) ;
400-
401- if ( response . status === 200 ) {
402- setStorageLock ( getCurrentTime ( ) ) ;
403- }
404-
405- if ( isDebug ) {
406- const body = await response . json ( ) ;
407- if ( response . status === 200 ) {
408- log ( 'Response:' , body ) ;
409- } else {
410- error ( 'Failure:' , body ) ;
411- }
412- }
413- } catch ( err ) {
414- if ( isDebug ) {
415- error ( err ) ;
416- }
417- }
403+ const url = new URL ( restApiEndpoint ) ;
404+ url . searchParams . set ( '_wpnonce' , restApiNonce ) ;
405+ navigator . sendBeacon (
406+ url ,
407+ new Blob ( [ JSON . stringify ( body ) ] , {
408+ type : 'application/json' ,
409+ } )
410+ ) ;
418411
419412 // Clean up.
420413 breadcrumbedElementsMap . clear ( ) ;
0 commit comments