Cách tốt nhất để phát hiện khi người dùng rời khỏi một trang web?


195

Cách tốt nhất để phát hiện nếu người dùng rời khỏi một trang web là gì?

Sự onunloadkiện JavaScript không hoạt động mọi lúc (yêu cầu HTTP mất nhiều thời gian hơn thời gian cần thiết để chấm dứt trình duyệt).

Tạo một cái có thể sẽ bị chặn bởi các trình duyệt hiện tại.

Câu trả lời:


219

Hãy thử onbeforeunloadsự kiện: Nó được kích hoạt ngay trước khi trang được tải. Nó cũng cho phép bạn hỏi lại nếu người dùng thực sự muốn rời đi. Xem bản demo onb Beforeunload Demo .

Ngoài ra, bạn có thể gửi yêu cầu Ajax khi anh ấy rời đi.


3
Sẽ tốt cho người dùng nếu bạn theo dõi nếu biểu mẫu thay đổi và chỉ nhắc nếu có - vì vậy nó không gây phiền nhiễu.
adam0101

3
Cũng lưu ý rằng các trình duyệt di động khác nhau bỏ qua kết quả của sự kiện (nghĩa là họ không yêu cầu người dùng xác nhận). Firefox có một ưu tiên ẩn trong about: config để làm tương tự. Về bản chất, điều này có nghĩa là người dùng luôn xác nhận rằng tài liệu có thể được tải.
MJB

2
Lưu ý rằng phương pháp này cũng gợi lên khi người dùng làm mới trang hoặc gửi biểu mẫu.
Zaytsev Dmitry

@Andreas Petersson, tôi có cùng thách thức với mục tiêu bỏ phiên người dùng. Làm thế nào để tôi có thể nắm bắt url được gõ để kiểm tra nếu đó thuộc về dự án?
Jcc.Sanabria

21

Mozilla Developer Network có một mô tả hay và ví dụ về onb Beforeunload .

Nếu bạn muốn cảnh báo người dùng trước khi rời trang nếu trang của bạn bị bẩn (tức là nếu người dùng đã nhập một số dữ liệu):

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
});

10

Đây là một giải pháp thay thế - vì trong hầu hết các trình duyệt, các điều khiển điều hướng (thanh điều hướng, tab, v.v.) được đặt phía trên khu vực nội dung trang, bạn có thể phát hiện con trỏ chuột rời khỏi trang qua đầu và hiển thị " trước khi bạn rời khỏi " hộp thoại. Nó hoàn toàn không gây khó chịu nó cho phép bạn tương tác với người dùng trước khi họ thực sự thực hiện hành động rời đi.

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

Nhược điểm là tất nhiên đó là dự đoán rằng người dùng thực sự có ý định rời đi, nhưng trong phần lớn các trường hợp, điều đó là chính xác.


Tôi đang tìm kiếm một cái gì đó giống như, tôi muốn hiển thị một cái gì đó không gây khó chịu cho người dùng của mình, trước khi rời khỏi trang của tôi, tôi đang tìm kiếm một cái gì đó giống như một sự kiện di chuột trên nút quay lại, bởi vì tôi cần phải kích hoạt sự kiện trước khi người dùng nhấp vào để quay lại. Tôi tin rằng cách tốt nhất là thực sự phát hiện chuột rời khỏi tài liệu cơ thể và thực hiện một số logic để xác định xem người dùng có tương tác với trang không.
Leonardo Souza Paiva

8

Đối với điều này tôi đang sử dụng:

window.onbeforeunload = function (e) {

}

Nó được bắn ngay trước khi trang được tải.


1
Opera 12 và các phiên bản cũ hơn không hỗ trợ điều này ... zachleat.com/web/ Kẻ
Cyrus

Làm thế nào là điều này tốt hơn so với hai câu trả lời trước đó đưa ra cùng một giải pháp , onbeforeunload?
Dan Dascalescu

5

Tôi biết câu hỏi này đã được trả lời, nhưng trong trường hợp bạn chỉ muốn kích hoạt một cái gì đó khi BROWSER thực sự bị đóng, và không chỉ khi tải trang xảy ra, bạn có thể sử dụng mã này:

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

Trong ví dụ của tôi, tôi đang xóa bộ nhớ cục bộ và cảnh báo người dùng bằng mouse y coords, chỉ khi đóng trình duyệt, điều này sẽ bị bỏ qua trên tất cả các tải trang từ trong chương trình.


window.event không xác định đối với tôi
Karl Glaser

Ví dụ của Merr chì là sai, window.event chỉ nên được sử dụng làm dự phòng cho các phiên bản IE cũ hơn, trong các trường hợp khác, enên sử dụng tham số sự kiện ( biến trong trường hợp này): stackoverflow.com/questions/9813445/ Sầu
Sk8erPeter

Sẽ không đi xa để nói rằng tôi sai. Các ví dụ của tôi hoạt động với tôi trong IE và Chrome rất tốt. Ví dụ của tôi là về trường hợp người dùng nhấp vào X (đóng) trên trình duyệt web. Cũng không phải là cách đẹp nhất có thể, nhưng nó hoạt động.
Lãnh đạo Merr

Từ 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

Một cách (hơi khó) để thực hiện là thay thế và liên kết dẫn ra khỏi trang web của bạn bằng một cuộc gọi AJAX đến phía máy chủ, cho biết người dùng đang rời đi, sau đó sử dụng cùng một khối javascript để đưa người dùng đến trang web bên ngoài. đã yêu cầu.

Tất nhiên điều này sẽ không hoạt động nếu người dùng chỉ cần đóng cửa sổ trình duyệt hoặc gõ vào một URL mới.

Để giải quyết vấn đề đó, bạn có khả năng cần sử dụng setTimeout () của Javascript trên trang, thực hiện cuộc gọi AJAX cứ sau vài giây (tùy thuộc vào tốc độ bạn muốn biết nếu người dùng rời đi).


4
Nếu bạn sử dụng phương pháp báo cáo tại nhà, không cần phải sửa đổi mọi liên kết trong trang.
Vinko Vrsalovic

3

Nhờ Nhân viên Dịch vụ , có thể triển khai một giải pháp tương tự như của Adam hoàn toàn ở phía khách hàng, được cấp trình duyệt hỗ trợ. Chỉ cần phá vỡ các yêu cầu nhịp tim:

// 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')
    )
  }
})

Ý bạn là ở đâu đó trong mã máy khách, cần phải có một setInterval(() => fetch('/heartbeat'), 5000)?
Dan Dascalescu

@DanDascalescu Đúng. Mã JS tạo ra một yêu cầu mạng đến / heartbeat và nhân viên dịch vụ chặn nó.
Jeffrey Sweeney

2

Trong trường hợp bạn cần thực hiện một số mã không đồng bộ (như gửi tin nhắn đến máy chủ mà người dùng không tập trung vào trang của bạn ngay bây giờ), sự kiện beforeunloadsẽ không dành thời gian cho mã async để chạy. Trong trường hợp không đồng bộ, tôi thấy rằng các sự kiện visibilitychangemouseleavecác sự kiện là các tùy chọn tốt nhất. Những sự kiện này kích hoạt khi người dùng thay đổi tab hoặc ẩn trình duyệt hoặc đưa trình duyệt ra khỏi phạm vi cửa sổ.

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
    }  
})


0

Vì giá trị của nó, đây là những gì tôi đã làm và có thể nó có thể giúp đỡ người khác mặc dù bài viết đã cũ.

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();
}

Mã não

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);

Cuộc gọi Ajax tới 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);
        }
    }
}

Cơ sở dữ liệu:

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;

Về cơ bản cứ sau 5 giây, js sẽ đăng lên một tệp php sẽ theo dõi người dùng và địa chỉ IP của người dùng. Người dùng hoạt động chỉ đơn giản là một bản ghi cơ sở dữ liệu có bản cập nhật cho dấu thời gian cơ sở dữ liệu trong vòng 5 giây. Người dùng cũ ngừng cập nhật vào cơ sở dữ liệu. Địa chỉ IP được sử dụng chỉ để đảm bảo rằng một người dùng là duy nhất nên 2 người trên trang web cùng lúc không đăng ký là 1 người dùng.

Có lẽ không phải là giải pháp hiệu quả nhất nhưng nó thực hiện công việc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.