Der beste Weg, um zu erkennen, wann ein Benutzer eine Webseite verlässt?

195

Was ist der beste Weg, um festzustellen, ob ein Benutzer eine Webseite verlässt?

Das onunloadJavaScript-Ereignis funktioniert nicht jedes Mal (die HTTP-Anforderung dauert länger als die zum Beenden des Browsers erforderliche Zeit).

Das Erstellen eines solchen wird wahrscheinlich von aktuellen Browsern blockiert.

ANaimi
quelle

Antworten:

219

Versuchen Sie das onbeforeunloadEreignis: Es wird ausgelöst, kurz bevor die Seite entladen wird. Sie können auch zurückfragen, ob der Benutzer wirklich gehen möchte. Sehen Sie sich die Demo an, bevor Sie die Demo herunterladen .

Alternativ können Sie eine Ajax- Anfrage senden, wenn er geht.

Andreas Petersson
quelle
3
Es wäre schön für den Benutzer, wenn Sie nachverfolgen würden, ob sich das Formular geändert hat, und nur dann auffordern würden, wenn dies der Fall ist - es ist also nicht ärgerlich.
Adam0101
3
Beachten Sie auch, dass verschiedene mobile Browser das Ergebnis des Ereignisses ignorieren (dh den Benutzer nicht um Bestätigung bitten). Firefox hat eine versteckte Präferenz in about: config, um dasselbe zu tun. Im Wesentlichen bedeutet dies, dass der Benutzer immer bestätigt, dass das Dokument möglicherweise entladen wird.
MJB
2
Beachten Sie, dass diese Methode auch aufgerufen wird, wenn Benutzer eine Seite aktualisieren oder ein Formular senden.
Zaytsev Dmitry
@Andreas Petersson, ich habe die gleiche Herausforderung mit dem Ziel, die Benutzersitzung zu beenden. Wie kann ich die eingegebene URL erfassen, um zu überprüfen, ob diese zum Projekt gehört?
Jcc.Sanabria
21

Mozilla Developer Network hat eine schöne Beschreibung und ein Beispiel für onbeforeunload .

Wenn Sie den Benutzer vor dem Verlassen der Seite warnen möchten, wenn Ihre Seite verschmutzt ist (dh wenn der Benutzer einige Daten eingegeben hat):

window.addEventListener('beforeunload', function(e) {
  var myPageIsDirty = ...; //you implement this logic...
  if(myPageIsDirty) {
    //following two lines will cause the browser to ask the user if they
    //want to leave. The text of this dialog is controlled by the browser.
    e.preventDefault(); //per the standard
    e.returnValue = ''; //required for Chrome
  }
  //else: user is allowed to leave without a warning dialog
});
DuckMaestro
quelle
10

Hier ist eine alternative Lösung: Da sich in den meisten Browsern die Navigationssteuerelemente (Navigationsleiste, Registerkarten usw.) über dem Seiteninhaltsbereich befinden, können Sie den Mauszeiger, der die Seite verlässt, oben erkennen und ein " Bevor Sie gehen " anzeigen. Dialog. Es ist völlig unauffällig und ermöglicht es Ihnen, mit dem Benutzer zu interagieren, bevor er die Aktion zum Verlassen tatsächlich ausführt.

$(document).bind("mouseleave", function(e) {
    if (e.pageY - $(window).scrollTop() <= 1) {    
        $('#BeforeYouLeaveDiv').show();
    }
});

Der Nachteil ist, dass es natürlich eine Vermutung ist, dass der Benutzer tatsächlich beabsichtigt zu gehen, aber in den allermeisten Fällen ist es richtig.

Rustyx
quelle
Ich sehe so aus, als ob ich meinem Benutzer etwas Unauffälliges zeigen möchte, bevor ich meine Seite verlasse. Ich sehe so etwas wie ein Hover-Ereignis auf der Schaltfläche "Zurück" aus, da ich das Ereignis auslösen muss, bevor der Benutzer klickt, um zurückzukehren. Ich glaube, dass der beste Weg darin besteht, das Maus-Verlassen-Body-Dokument wirklich zu erkennen und eine Logik zu erstellen, um festzustellen, ob der Benutzer mit der Seite interagiert hat.
Leonardo Souza Paiva
8

Dafür benutze ich:

window.onbeforeunload = function (e) {

}

Es wird kurz vor dem Entladen der Seite ausgelöst.

suhailvs
quelle
1
Opera 12 und ältere Versionen unterstützen dies nicht ... zachleat.com/web/…
Cyrus
Wie ist das besser als die beiden vorherigen Antworten, die die gleiche Lösung liefern onbeforeunload?
Dan Dascalescu
5

Ich weiß, dass diese Frage beantwortet wurde, aber falls Sie nur dann etwas auslösen möchten, wenn der eigentliche BROWSER geschlossen ist, und nicht nur, wenn eine Seitenladung auftritt, können Sie diesen Code verwenden:

window.onbeforeunload = function (e) {
        if ((window.event.clientY < 0)) {
            //window.localStorage.clear();
            //alert("Y coords: " + window.event.clientY)
        }
};

In meinem Beispiel lösche ich den lokalen Speicher und alarmiere den Benutzer mit den Maus- und Koordinaten. Nur wenn der Browser geschlossen ist, wird dies bei allen Seitenladevorgängen aus dem Programm ignoriert.

Merr Leader
quelle
window.event ist für mich undefiniert
Karl Glaser
Das Beispiel von Merr Leader ist falsch. Window.event sollte nur als Fallback verwendet werden, beispielsweise für ältere Versionen des IE. In anderen Fällen sollte der Ereignisparameter ( ein diesem Fall die Variable) verwendet werden: stackoverflow.com/questions/9813445/ …
Sk8erPeter
Ich würde nicht so weit gehen zu sagen, dass ich falsch liege. Meine Beispiele funktionieren für mich in IE und Chrome einwandfrei. Mein Beispiel war für das Szenario, dass der Benutzer im Webbrowser auf das X (Schließen) klickt. Vielleicht auch nicht der schönste Weg, aber es funktioniert.
Merr Leader
Von MDN: This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. developer.mozilla.org/en-US/docs/Web/API/Window/event
Robin Neal
3

Eine (etwas hackige) Möglichkeit, dies zu tun, besteht darin, durch einen AJAX-Aufruf auf die Serverseite zu ersetzen und Links zu erstellen, die von Ihrer Site wegführen. Dies zeigt an, dass der Benutzer die Site verlässt, und dann denselben Javascript-Block zu verwenden, um den Benutzer zu der externen Site zu führen, auf der er sich befindet habe angefordert.

Dies funktioniert natürlich nicht, wenn der Benutzer einfach das Browserfenster schließt oder eine neue URL eingibt.

Um dies zu umgehen, müssen Sie möglicherweise setTimeout () von Javascript auf der Seite verwenden und alle paar Sekunden einen AJAX-Aufruf durchführen (abhängig davon, wie schnell Sie wissen möchten, ob der Benutzer gegangen ist).

Steve M.
quelle
4
Wenn Sie den Report Home-Ansatz verwenden, müssen Sie nicht jeden Link auf der Seite ändern.
Vinko Vrsalovic
3

Dank Service Workers ist es möglich, eine ähnliche Lösung wie Adam rein clientseitig zu implementieren , sofern der Browser dies unterstützt. Umgehen Sie einfach Herzschlaganfragen:

// The delay should be longer than the heartbeat by a significant enough amount that there won't be false positives
const liveTimeoutDelay = 10000
let liveTimeout = null

global.self.addEventListener('fetch', event => {
  clearTimeout(liveTimeout)
  liveTimeout = setTimeout(() => {
    console.log('User left page')
    // handle page leave
  }, liveTimeoutDelay)
  // Forward any events except for hearbeat events
  if (event.request.url.endsWith('/heartbeat')) {
    event.respondWith(
      new global.Response('Still here')
    )
  }
})
Jeffrey Sweeney
quelle
Meinten Sie, dass es irgendwo im Client-Code einen geben muss setInterval(() => fetch('/heartbeat'), 5000)?
Dan Dascalescu
@ DanDascalescu Richtig. Der JS-Code sendet eine Netzwerkanforderung an / heartbeat, und der Servicemitarbeiter fängt sie ab.
Jeffrey Sweeney
2

In dem Fall, dass Sie asynchronen Code ausführen müssen (z. B. das Senden einer Nachricht an den Server, dass sich der Benutzer gerade nicht auf Ihre Seite konzentriert), gibt das Ereignis dem asynchronen Codebeforeunload keine Zeit zum Ausführen. Im Falle von Async fand ich, dass die visibilitychangeund mouseleaveEreignisse die besten Optionen sind. Diese Ereignisse werden ausgelöst, wenn der Benutzer die Registerkarte wechselt, den Browser ausblendet oder den Courser aus dem Fensterbereich entfernt.

document.addEventListener('mouseleave', e=>{
     //do some async code
})

document.addEventListener('visibilitychange', e=>{
     if (document.visibilityState === 'visible') {
   //report that user is in focus
    } else {
     //report that user is out of focus
    }  
})

Tal Yaron
quelle
0

Für was es wert ist, das habe ich getan und vielleicht kann es anderen helfen, obwohl der Artikel alt ist.

PHP:

session_start();

$_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR'];

if(isset($_SESSION['userID'])){
    if(!strpos($_SESSION['activeID'], '-')){
        $_SESSION['activeID'] = $_SESSION['userID'].'-'.$_SESSION['activeID'];
    }
}elseif(!isset($_SESSION['activeID'])){
    $_SESSION['activeID'] = time();
}

JS

window.setInterval(function(){
            var userid = '<?php echo $_SESSION['activeID']; ?>';
            var ipaddress = '<?php echo $_SESSION['ipaddress']; ?>';
            var action = 'data';

            $.ajax({
                url:'activeUser.php',
                method:'POST',
                data:{action:action,userid:userid,ipaddress:ipaddress},
                success:function(response){
                     //alert(response);                 
                }
            });
          }, 5000);

Ajax-Aufruf von activeUser.php

if(isset($_POST['action'])){
    if(isset($_POST['userid'])){
        $stamp = time();
        $activeid = $_POST['userid'];
        $ip = $_POST['ipaddress'];

        $query = "SELECT stamp FROM activeusers WHERE activeid = '".$activeid."' LIMIT 1";
        $results = RUNSIMPLEDB($query);

        if($results->num_rows > 0){
            $query = "UPDATE activeusers SET stamp = '$stamp' WHERE activeid = '".$activeid."' AND ip = '$ip' LIMIT 1";
            RUNSIMPLEDB($query);
        }else{
            $query = "INSERT INTO activeusers (activeid,stamp,ip)
                    VALUES ('".$activeid."','$stamp','$ip')";
            RUNSIMPLEDB($query);
        }
    }
}

Datenbank:

CREATE TABLE `activeusers` (
  `id` int(11) NOT NULL,
  `activeid` varchar(20) NOT NULL,
  `stamp` int(11) NOT NULL,
  `ip` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Grundsätzlich postet das js alle 5 Sekunden in einer PHP-Datei, die den Benutzer und die IP-Adresse des Benutzers verfolgt. Aktive Benutzer sind einfach ein Datenbankeintrag, bei dem der Datenbankzeitstempel innerhalb von 5 Sekunden aktualisiert wird. Alte Benutzer beenden die Aktualisierung der Datenbank. Die IP-Adresse wird nur verwendet, um sicherzustellen, dass ein Benutzer eindeutig ist, sodass sich 2 Personen auf der Site gleichzeitig nicht als 1 Benutzer registrieren.

Wahrscheinlich nicht die effizienteste Lösung, aber sie macht den Job.

Adam
quelle