Sometimes we need to do some reporting to record user behavior when they leave the page. Or send an Ajax request to the server to notify the server that the user has left, such as a check-out in a studio.

This article is divided into two parts to explain how to complete the reporting of exit behavior.

1. Event listening

Browsers have two events that can be used to listen for page closures, beforeUnload and Unload. Beforeunload is called when the document and resource are going to be shut down while the document is still visible and can be cancelled at this closing event. For example, writing the following will cause the user to have a popover reminding the user whether to close or refresh the page.

window.addEventListener("beforeunload".function (event) {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = ' ';
});
Copy the code

Unload occurs when the page is already being unloaded and the document is in a state of: 1. All resources still exist (images, iframe, etc.); 2. All resources of the user are invisible. 3. The interface interaction is invalid (window.open, alert, confirm, etc.); 4. Errors do not stop the uninstallation process.

Based on the above two methods can be implemented to close the page event listening, to be safe, you can listen to both events. The listener function is then handled so that the close event is called only once.

2. Send the request

With the above listen, the job is only half done. If we send the Ajax request directly in the listen, we will find that the request is abort by the browser and cannot be sent. When the page is uninstalled, the browser does not guarantee that the asynchronous request will be made successfully.

There are several ways we can solve this problem:

Scenario 1: Send a synchronous Ajax request

var oAjax = new XMLHttpRequest();

oAjax.open('POST', url + '/user/register'.false);//false indicates synchronous request

oAjax.setRequestHeader("Content-type"."application/x-www-form-urlencoded");

oAjax.onreadystatechange = function() {
    if (oAjax.readyState == 4 && oAjax.status == 200) {
        var data = JSON.parse(oAjax.responseText);
    } else {
        console.log(oAjax); }}; oAjax.send('a=1&b=2');
Copy the code

This works, but the user has to wait for the request to finish before closing the page. The user experience is not good.

Scenario 2: Send asynchronous requests and ignore Ajax abort on the server

Although asynchronous requests can be abort by the browser, it is also ok if the server can ignore the abort and still execute normally. For example, PHP has ignore_user_abort which ignores abort. This requires the transformation of the background, which is generally not feasible..

Option 3: Usenavigator.sendBeaconSending an asynchronous request

According to MDN:

This approach is primarily used to meet the needs of statistical and diagnostic code that typically tries to send data to a Web server before unloading a document. Sending data too early can result in missed opportunities to collect data. However, it has been difficult for developers to ensure that data is sent during document uninstallation. This is because the user agent typically ignores the asynchronous XMLHttpRequest generated in the unload event handler.

As you can see from the introduction, this method is used to make requests while the user is away. Perfect for this scenario. Here’s how it works:

navigator.sendBeacon(url [, data]);
Copy the code

SendBeacon supports sending data of type ArrayBufferView, Blob, DOMString, or FormData.

The following are several ways to send a request using sendBeacon. You can change the format of the header and content, because the communication with the server is usually fixed. If the header or content is changed, the server will not recognize it properly.

The advantage of using Blob to send is that you can define the format and header of the content. For example, you can set the content-type to Application/X-wwW-form-urlencoded.

blob = new Blob([`room_id=123`] and {type : 'application/x-www-form-urlencoded'});
navigator.sendBeacon("/cgi-bin/leave_room", blob);
Copy the code

(2) Use the FormData object, but the content-type is set to “multipart/form-data”.

var fd = new FormData();
fd.append('room_id'.123);
navigator.sendBeacon("/cgi-bin/leave_room", fd);
Copy the code

(3) Data can also be used with URLSearchParams objects. The content-type will be set to “text/plain; Charset = utf-8 “.

var params = new URLSearchParams({ room_id: 123 })
navigator.sendBeacon("/cgi-bin/leave_room", params);
Copy the code

Through attempts, we can find that it is convenient to send the message using BLOB, and the setting of the content is also flexible. If the sent message is not recognized in the background after packet capture, you can try to modify the string or header of the content to find an appropriate way to send the request.

Reference links:

  1. sendBeacon API not working temporarily due to security issue, any workaround?

  2. Sending AJAX Data when User Moves Away / Exits from Page

  3. Setting HTTP Headers in a Beacon Request


“IVWEB Technology Weekly” shock online, pay attention to the public number: IVWEB community, weekly timing push quality articles.

  • Weekly articles collection: weekly
  • Team open source project: Feflow