skip to Main Content

This is my code:

<script>
    function sendFieldData() {
        var email = document.getElementById('EmailComprador').value;
        var telefone = document.getElementById('TelefoneComprador2').value;
        var nome = document.getElementById('NomeComprador2').value;
        var data = {
            CostumerEmail: email,
            CostumerName: nome,
            CostumerPhone: telefone,
        };
        if (email) {
            let curfetchUrl = `${window.location.pathname}?handler=SaveAbandonedCart`;
            fetch(curfetchUrl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
                },
                body: JSON.stringify(data)
            })
                .then(response => {
                    if (!response.ok) {
                        return response.text().then(text => { throw new Error(text); });
                    }
                    return response.json();
                })
                .then(responseData => {
                    console.log('salvo com sucesso', responseData);
                })
                .catch(error => {
                    console.error('erro:', error);
                });
        }
    }
    window.addEventListener('beforeunload', function (event) {
        setTimeout(sendFieldData, 0);
    });
</script>

At first it only calls the method on the IndexModel when I reload the page, but that’s not what I want. I want when the user clicks on close tab to trigger the event to the backend as well.

Obs.: I already used unload, it didn’t work.
I’m using Razor, Js and C#

3

Answers


  1. The issue is that the beforeunload event listener is not reliable. Sending analytics when the page closes has become so commonplace that an API was added to handle it: Beacon API

    Here’s your JavaScript with that adjustment. Note that I moved some logic around a bit so we can build the data object before sending the beacon.

    function getData() {
      var email = document.getElementById("EmailComprador").value;
      var telefone = document.getElementById("TelefoneComprador2").value;
      var nome = document.getElementById("NomeComprador2").value;
      return {
        CostumerEmail: email,
        CostumerName: nome,
        CostumerPhone: telefone,
      };
    }
    
    document.addEventListener("visibilitychange", function logData() {
      if (document.visibilityState === "hidden") {
        const curfetchUrl = `${window.location.pathname}?handler=SaveAbandonedCart`;
        const data = getData();
        if (data.CostumerEmail) {
          const requestSucceeded = navigator.sendBeacon(
            curfetchUrl,
            JSON.stringify(data)
          );
          if (requestSucceeded) {
            console.log("salvo com sucesso");
          } else {
            console.error("erro");
          }
        }
      }
    });
    

    If there are issues with using this API, like if you need to customize request properties or need to handle the response from the server, then this won’t be a good fit. Instead try your original code but add "keepalive: true" to the fetch call. You’ll also need to switch to using visibilitychange instead of beforeunload like in the first example.

    //...
        fetch(curfetchUrl, {
          method: "POST",
          keepalive: true, // here's the adjustment
          headers: {
            "Content-Type": "application/json",
            RequestVerificationToken: document.querySelector(
              'input[name="__RequestVerificationToken"]'
            ).value,
          },
          body: JSON.stringify(data),
        })
    //...
    
    Login or Signup to reply.
  2. Try using:

    window.onbeforeunload = function()
    {

    // Do something

    }

    Look at the green check mark code:
    Run JavaScript code on window close or page refresh?

    Login or Signup to reply.
  3. This issue might be due to the asynchronous nature of the call. First, try removing the setTimeout or, instead of using a fetch request, consider using navigator.sendBeacon.

    You can read more about it Navigator: sendBeacon() method

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search