Обнаружение кликов в iframe с помощью JavaScript

129

Я понимаю, что невозможно сказать, что пользователь делает внутри, iframeесли это перекрестный домен. Я хотел бы отслеживать, щелкнул ли пользователь вообще в iframe. Я представляю сценарий, в котором есть невидимое divповерх, iframeа divзатем просто передается событие щелчка в iframe.

Возможно ли что-то подобное? Если да, то как мне это сделать? Это iframesреклама, поэтому я не могу контролировать используемые теги.

Расс Брэдберри
источник
4
Возможно, и существует кроссбраузерное решение: stackoverflow.com/a/32138108/1064513
Дмитрий Кочин

Ответы:

39

Возможно ли что-то подобное?

Нет. Все, что вы можете сделать, это обнаружить, что мышь входит в iframe, и потенциально (хотя и ненадежно), когда она возвращается (то есть пытается определить разницу между указателем, проходящим по рекламе в другом месте, и задержкой по объявлению).

Я представляю сценарий, в котором есть невидимый div поверх iframe, а div просто передаст событие щелчка в iframe.

Нет, невозможно подделать событие клика.

Перехватывая mousedown, вы предотвращаете попадание исходного клика в iframe. Если бы вы могли определить, когда была нажата кнопка мыши, вы могли бы попытаться убрать невидимый div с пути, чтобы щелчок прошел ... но также нет события, которое срабатывает непосредственно перед mousedown.

Вы можете попытаться угадать, например, посмотрев, остановился ли указатель, предполагая, что вот-вот произойдет щелчок. Но это абсолютно ненадежно, и если вы потерпите неудачу, вы просто потеряете клик.

bobince
источник
4
Да, это так. И есть кроссбраузерное решение: stackoverflow.com/a/32138108/1064513
Дмитрий Кочин
1
Я проверил эти ссылки и считаю, что ответ правильный. Вы можете обнаружить только щелчок внутри iframe, но не то, что было нажато.
user568021
Я голосую против только потому, что это не совсем так. Большая часть того, что вы говорите, правда, но есть обходные пути, как и наиболее популярный ответ в этой теме.
newms87 08
155

Конечно, это возможно. Это работает в Chrome, Firefox и IE 11 (и, возможно, в других).

focus();
var listener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('iframe')) {
        // clicked
    }
    window.removeEventListener('blur', listener);
});

JSFiddle


Предупреждение: обнаруживает только первый щелчок. Насколько я понимаю, это все, что вам нужно.

Пол Дрейпер
источник
1
@the_joric, это потому, что прошло 4 года после вопроса, и люди обычно не прокручивают первую пару ответов.
Пол Дрейпер,
3
Также следует отметить, что если вы меняете вкладки браузера, активируется focus ();
Linnay
7
Он НЕ работает в Firefox. JSFiddle содержит ошибку, скрывающую это: = вместо ===. Существует кроссбраузерное решение (даже в IE8): stackoverflow.com/a/32138108/1064513
Дмитрий Кочин
8
Событие размытия не срабатывает, если пользователь сначала не щелкает основной документ! Кроме того, это не может использоваться для обнаружения кликов по нескольким iframe, поскольку нет события, которое срабатывает при изменении фокуса с одного iframe на другой ( blurсобытие iframe не срабатывает).
Tomáš Kafka
1
почему существует зависимость от focus ();
Прасад Шинде
108

Основываясь на ответе Мохаммеда Радвана, я придумал следующее решение jQuery. По сути, он отслеживает, что люди в iFrame зависают. Затем, если окно размывается, это, скорее всего, означает, что пользователь щелкнул баннер iframe.

iframe следует поместить в div с идентификатором, чтобы убедиться, что вы знаете, на какой iframe нажал пользователь:

<div class='banner' bannerid='yyy'>
    <iframe src='http://somedomain.com/whatever.html'></iframe>
<div>

так:

$(document).ready( function() {
    var overiFrame = -1;
    $('iframe').hover( function() {
        overiFrame = $(this).closest('.banner').attr('bannerid');
    }, function() {
        overiFrame = -1
    });

... это сохраняет overiFrame на -1, когда не наведены iFrames, или 'bannerid', установленный в оборачивающем div, когда iframe зависает. Все, что вам нужно сделать, это проверить, установлен ли overiFrame, когда окно размывается, например: ...

    $(window).blur( function() {
        if( overiFrame != -1 )
            $.post('log.php', {id:overiFrame}); /* example, do your stats here */
    });
});

Очень элегантное решение с небольшим недостатком: если пользователь нажимает ALT-F4 при наведении указателя мыши на iFrame, он регистрирует это как щелчок. Это произошло только в FireFox, хотя IE, Chrome и Safari не зарегистрировали это.

Еще раз спасибо Мохаммед, очень полезное решение!

Патрик
источник
Я добавил +1 к этому ответу, хотя у него есть следующие проблемы: 1. Когда есть несколько окон iframe, вы нажимаете на один из них, а затем сразу на другой - второй щелчок не обнаруживается. 2. Множественные клики внутри iframe тоже не учитываются. 3. Некорректно работает на мобиле, потому что нельзя сделать событие "наведение" пальцем.
Sych
Приведенный выше сценарий используется мной для обнаружения кликов с моего сайта. Большинство рекламных сетей теперь размещают баннеры в рамке. Если вы щелкнете по одному, а затем быстро по другому, прежде чем уйти от первого щелчка, технически я хочу знать последний щелчок, который вы фактически оставили. Так что в моем случае это желаемое поведение. Он также отлично определяет клики по мобильным баннерам. Таким образом, наведение должно быть запущено прямо перед выполнением щелчка
Патрик
Не работает в случае элементов svg в содержимом iframe :( stackoverflow.com/questions/32589735/…
Сергей
@Serhiy, это потому, что вы на самом деле не выходите с исходной страницы при нажатии на iframe ...
Патрик
6
Этот ответ является лучшим из них, однако, если вы хотите получать каждый щелчок по iframe, вам нужно снять с него фокус после того, как пользователь щелкнул , чтобы отслеживать дальнейшие щелчки. Это должно быть добавлено в раздел $ (окно) .blur (): setTimeout(function(){ window.focus(); }, 0);. Теперь пользователь щелкает, переводит фокус в iframe, скрипт возвращает этот фокус и теперь может отслеживать дальнейшие изменения фокуса на основании будущих кликов.
HelpingHand 06
89

Это небольшое решение, которое работает во всех браузерах, даже в IE8:

var monitor = setInterval(function(){
    var elem = document.activeElement;
    if(elem && elem.tagName == 'IFRAME'){
        clearInterval(monitor);
        alert('clicked!');
    }
}, 100);

Вы можете проверить это здесь: http://jsfiddle.net/oqjgzsm0/

Дмитрий Кочин
источник
1
Что делать, если у вас несколько фреймов, и вы не знаете их идентификатор?
Шанкшера
1
единственное кроссбраузерное надежное решение, которое также работает в последней версии FF! Большое спасибо. Он заслуживает большего количества голосов
BrainOverflow
6
@shankshera Просто получите elem.id, это ваш идентификатор iframe :). См. Jsfiddle.net/oqjgzsm0/219
Томаш Кафка
1
Я использую это для отслеживания кликов по кнопкам социальных сетей. Но поскольку 3/4 из тех, что я использую, используют фреймы, мне нужно отслеживать клики в нескольких фреймах. Я обновил скрипку, чтобы это учесть: jsfiddle.net/oqjgzsm0/273 . Он устанавливает новый интервал, который проверяет, находится ли щелчок за пределами iframe, по которому последний щелкнул. Затем сбрасывает исходный интервал для повторной проверки кликов. Он не отслеживает несколько кликов в одном iframe без щелчка за его пределами.
brouxhaha 07
14
Помимо того факта, что использование непрерывного интервала цикла с такой скоростью - не очень хорошая идея, это будет обнаруживать ложные срабатывания, если пользователь установит фокус на iframe с помощью клавиш навигации по табуляции
Kaiido
36

Следующий код покажет вам, если пользователь щелкнет / наведет курсор или покинет iframe: -

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Detect IFrame Clicks</title>
<script type="text/javascript">
    $(document).ready(function() {
        var isOverIFrame = false;

        function processMouseOut() {
            log("IFrame mouse >> OUT << detected.");
            isOverIFrame = false;
            top.focus();
        }

        function processMouseOver() {
            log("IFrame mouse >> OVER << detected.");
            isOverIFrame = true;
        }

        function processIFrameClick() {
            if(isOverIFrame) {
                // replace with your function
                log("IFrame >> CLICK << detected. ");
            }
        }

        function log(message) {
            var console = document.getElementById("console");
            var text = console.value;
            text = text + message + "\n";
            console.value = text;
        }

        function attachOnloadEvent(func, obj) {
            if(typeof window.addEventListener != 'undefined') {
                window.addEventListener('load', func, false);
            } else if (typeof document.addEventListener != 'undefined') {
                document.addEventListener('load', func, false);
            } else if (typeof window.attachEvent != 'undefined') {
                window.attachEvent('onload', func);
            } else {
                if (typeof window.onload == 'function') {
                    var oldonload = onload;
                    window.onload = function() {
                        oldonload();
                        func();
                    };
                } else {
                    window.onload = func;
                }
            }
        }

        function init() {
            var element = document.getElementsByTagName("iframe");
            for (var i=0; i<element.length; i++) {
                element[i].onmouseover = processMouseOver;
                element[i].onmouseout = processMouseOut;
            }
            if (typeof window.attachEvent != 'undefined') {
                top.attachEvent('onblur', processIFrameClick);
            }
            else if (typeof window.addEventListener != 'undefined') {
                top.addEventListener('blur', processIFrameClick, false);
            }
        }

        attachOnloadEvent(init);
    });
</script>
</head>
<body>
<iframe src="www.google.com" width="100%" height="1300px"></iframe>
<br></br>
<br></br>
<form name="form" id="form" action=""><textarea name="console"
id="console" style="width: 100%; height: 300px;" cols="" rows=""></textarea>
<button name="clear" id="clear" type="reset">Clear</button>
</form>
</body>
</html>

Вам нужно заменить src в iframe своей собственной ссылкой. Надеюсь, это поможет. С уважением, Пн.

Мохаммед Радван
источник
1
Основываясь на быстром тестировании, данный пример (после исправления URL-адреса), похоже, работает в IE 8, несколько надежно в Chrome 14.0.835.186 m, но совсем не в Firefox 6.0.2.
Мэтью Флашен,
Отлично работает для Chrome, но не работает для Firefox v62, потому что при нажатии на iframe событие размытия не
генерируется
11

Только что нашел это решение ... Я попробовал, мне понравилось ..

Работает с междоменными фреймами iframe для компьютеров и мобильных устройств!

Не знаю, надежно ли это еще

window.addEventListener('blur',function(){
      if(document.activeElement.id == 'CrossDomainiframeId'){
        //do something :-)
      }
});

Удачного кодирования

Тони
источник
2
Тот же ответ (возможно, немного лучшая версия) был опубликован годом ранее здесь, на этой же странице: stackoverflow.com/a/23231136/470749
Райан,
5

Вы можете добиться этого, используя событие размытия в элементе окна.

Вот плагин jQuery для отслеживания щелчков по iframe (он запускает настраиваемую функцию обратного вызова при нажатии iframe): https://github.com/finalclap/iframeTracker-jquery

Используйте это так:

jQuery(document).ready(function($){
    $('.iframe_wrap iframe').iframeTracker({
        blurCallback: function(){
            // Do something when iframe is clicked (like firing an XHR request)
        }
    });
});
Винс
источник
5

см. http://jsfiddle.net/Lcy797h2/ для моего длинного решения, которое не работает надежно в IE

        $(window).on('blur',function(e) {    
            if($(this).data('mouseIn') != 'yes')return;
            $('iframe').filter(function(){
                return $(this).data('mouseIn') == 'yes';
            }).trigger('iframeclick');    
        });

        $(window).mouseenter(function(){
            $(this).data('mouseIn', 'yes');
        }).mouseleave(function(){
            $(this).data('mouseIn', 'no');
        });

        $('iframe').mouseenter(function(){
            $(this).data('mouseIn', 'yes');
            $(window).data('mouseIn', 'yes');
        }).mouseleave(function(){
            $(this).data('mouseIn', null);
        });

        $('iframe').on('iframeclick', function(){
            console.log('Clicked inside iframe');
            $('#result').text('Clicked inside iframe'); 
        });
        $(window).on('click', function(){
            console.log('Clicked inside window');
            $('#result').text('Clicked inside window'); 
        }).blur(function(){
            console.log('window blur');
        });

        $('<input type="text" style="position:absolute;opacity:0;height:0px;width:0px;"/>').appendTo(document.body).blur(function(){
                $(window).trigger('blur');
            }).focus();
DiverseAndRemote.com
источник
Это потрясающий программист .... чего я на самом деле хочу ... +1 к @Omar Jackman ... так полезно захватывать клики по рекламе на YouTube
saun4frsh
4

У меня это работает во всех браузерах (включая Firefox)

https://gist.github.com/jaydson/1780598

https://jsfiddle.net/sidanmor/v6m9exsw/

var myConfObj = {
  iframeMouseOver : false
}
window.addEventListener('blur',function(){
  if(myConfObj.iframeMouseOver){
    console.log('Wow! Iframe Click!');
  }
});

document.getElementById('idanmorblog').addEventListener('mouseover',function(){
   myConfObj.iframeMouseOver = true;
});
document.getElementById('idanmorblog').addEventListener('mouseout',function(){
    myConfObj.iframeMouseOver = false;
});
<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>

<iframe id="idanmorblog" src="https://sidanmor.com/" style="width:400px;height:600px" ></iframe>

sidanmor
источник
3

Мохаммед Радван, Ваше решение элегантно. Чтобы обнаружить щелчки iframe в Firefox и IE, вы можете использовать простой метод с document.activeElement и таймером, однако ... Я искал по всему Интернету метод обнаружения щелчков на iframe в Chrome и Safari. На грани отказа, я нахожу ваш ответ. Спасибо, сэр!

Несколько советов: я считаю, что ваше решение более надежно при прямом вызове функции init (), а не через attachOnloadEvent (). Конечно, для этого вы должны вызывать init () только после iframe html. Это будет выглядеть примерно так:

<script>
var isOverIFrame = false;
function processMouseOut() {
    isOverIFrame = false;
    top.focus();
}
function processMouseOver() { isOverIFrame = true; }
function processIFrameClick() {
    if(isOverIFrame) {
    //was clicked
    }
}

function init() {
    var element = document.getElementsByTagName("iframe");
    for (var i=0; i<element.length; i++) {
        element[i].onmouseover = processMouseOver;
        element[i].onmouseout = processMouseOut;
    }
    if (typeof window.attachEvent != 'undefined') {
        top.attachEvent('onblur', processIFrameClick);
    }
    else if (typeof window.addEventListener != 'undefined') {
        top.addEventListener('blur', processIFrameClick, false);
    }
}
</script>

<iframe src="http://google.com"></iframe>

<script>init();</script>
zone117x
источник
3

Вы можете сделать это, чтобы отобразить события в родительском документе:

$('iframe').load(function() {
    var eventlist = 'click dblclick \
                    blur focus focusin focusout \
                    keydown keypress keyup \
                    mousedown mouseenter mouseleave mousemove mouseover mouseout mouseup mousemove \
                    touchstart touchend touchcancel touchleave touchmove';

    var iframe = $('iframe').contents().find('html');

    // Bubble events to parent
    iframe.on(eventlist, function(event) {
        $('html').trigger(event);
    });
});

Просто расширьте список событий, добавив больше событий.

Танер Топал
источник
Я использовал событие «touchend», и оно сработало! Ваш ответ мне очень помог!
3

Я столкнулся с ситуацией, когда мне приходилось отслеживать клики по кнопке социальных сетей, выдаваемой через iframe. При нажатии кнопки открывается новое окно. Вот мое решение:

var iframeClick = function () {
    var isOverIframe = false,
    windowLostBlur = function () {
        if (isOverIframe === true) {
            // DO STUFF
            isOverIframe = false;
        }
    };
    jQuery(window).focus();
    jQuery('#iframe').mouseenter(function(){
        isOverIframe = true;
        console.log(isOverIframe);
    });
    jQuery('#iframe').mouseleave(function(){
        isOverIframe = false;
        console.log(isOverIframe);
    });
    jQuery(window).blur(function () {
        windowLostBlur();
    });
};
iframeClick();
pizzarob
источник
3

http://jsfiddle.net/QcAee/406/

Просто создайте невидимый слой над iframe, который возвращается при щелчке и поднимается при срабатывании события mouseleave !!
Нужен jQuery

это решение не распространяет первый щелчок внутри iframe!

$("#invisible_layer").on("click",function(){
		alert("click");
		$("#invisible_layer").css("z-index",-11);

});
$("iframe").on("mouseleave",function(){
		$("#invisible_layer").css("z-index",11);
});
iframe {
    width: 500px;
    height: 300px;
}
#invisible_layer{
  position: absolute;
  background-color:trasparent;
  width: 500px;
  height:300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message"></div>
<div id="invisible_layer">

</div>
<iframe id="iframe" src="//example.com"></iframe>

r1si
источник
1

Это определенно работает, если iframe находится из того же домена, что и ваш родительский сайт. Я не тестировал его для междоменных сайтов.

$(window.frames['YouriFrameId']).click(function(event){  /* do something here  */ });
$(window.frames['YouriFrameId']).mousedown(function(event){ /* do something here */ });
$(window.frames['YouriFrameId']).mouseup(function(event){ /* do something here */ });

Без jQuery вы могли бы попробовать что-то вроде этого, но я снова этого не пробовал.

window.frames['YouriFrameId'].onmousedown = function() { do something here }

Вы даже можете фильтровать свои результаты:

$(window.frames['YouriFrameId']).mousedown(function(event){   
  var eventId = $(event.target).attr('id');      
  if (eventId == 'the-id-you-want') {
   //  do something
  }
});
Джонатан Тонг
источник
1

Сочетание приведенного выше ответа с возможностью щелкать снова и снова, не нажимая за пределами iframe.

    var eventListener = window.addEventListener('blur', function() {
    if (document.activeElement === document.getElementById('contentIFrame')) {
        toFunction(); //function you want to call on click
        setTimeout(function(){ window.focus(); }, 0);
    }
    window.removeEventListener('blur', eventListener );
    });
Талха Асиф
источник
1

Мы можем поймать все щелчки. Идея состоит в том, чтобы сбрасывать фокус на элементе вне iFrame после каждого щелчка:

    <input type="text" style="position:fixed;top:-1000px;left:-1000px">
    <div id="message"></div>
    <iframe id="iframe" src="//example.com"></iframe>
    <script>
        focus();
        addEventListener('blur', function() {
            if(document.activeElement = document.getElementById('iframe')) {
                message.innerHTML += 'Clicked';
                setTimeout(function () {
                    document.querySelector("input").focus();
                    message.innerHTML += ' - Reset focus,';
                }, 1000);
            }  
        });
    </script>

JSFiddle

Александр Муравьев
источник
0

Я считаю, что вы можете сделать что-то вроде:

$('iframe').contents().click(function(){function to record click here });

используя jQuery для этого.

Дэниел Селлерс
источник
0

Как обнаружено там: обнаружение щелчка в iframe с помощью JavaScript

=> Мы можем использовать iframeTracker-jquery :

$('.carousel-inner .item').each(function(e) {
    var item = this;
    var iFrame = $(item).find('iframe');
    if (iFrame.length > 0) {
        iFrame.iframeTracker({
            blurCallback: function(){
                // Do something when iFrame is clicked (like firing an XHR request)
                onItemClick.bind(item)(); // calling regular click with right context
                console.log('IFrameClick => OK');
            }
        });
        console.log('IFrameTrackingRegistred => OK');
    }
})
Микаэль
источник
0

Основываясь на ответе Пола Дрейпера, я создал решение, которое работает постоянно, когда у вас есть фреймы, которые открывают другую вкладку в браузере. Когда вы вернетесь, страница останется активной для обнаружения щелчка по фреймворку, это очень распространенная ситуация:

          focus();
        $(window).blur(() => {
           let frame = document.activeElement;
           if (document.activeElement.tagName == "IFRAME") {
             // Do you action.. here  frame has the iframe clicked
              let frameid = frame.getAttribute('id')
              let frameurl = (frame.getAttribute('src'));
           }            
        });

        document.addEventListener("visibilitychange", function () {
            if (document.hidden) {

            } else {
                focus();
            }
        });

Код прост, событие размытия обнаруживает потерю фокуса при щелчке по iframe и проверяет, является ли активный элемент iframe (если у вас несколько iframe, вы можете знать, кто был выбран), эта ситуация часто возникает, когда у вас есть рекламные фреймы ,

Второе событие вызывает метод фокуса, когда вы возвращаетесь на страницу. используется событие изменения видимости.

freedeveloper
источник
0

Вот решение, использующее предлагаемые подходы с трюками с наведением + размытие и активными элементами, а не с любыми библиотеками, а только с чистыми js. Прекрасно работает для FF / Chrome. В основном подход такой же, как предложил @Mohammed Radwan, за исключением того, что я использую другой метод, предложенный @ zone117x, для отслеживания щелчка iframe для FF, потому что window.focus не работает без дополнительных пользовательских настроек :

Делает запрос на выведение окна вперед. Это может привести к сбою из-за пользовательских настроек, и не гарантируется, что окно будет передним до того, как этот метод вернется.

Вот составной метод:

function () {
    const state = {};

    (function (setup) {
        if (typeof window.addEventListener !== 'undefined') {
            window.addEventListener('load', setup, false);
        } else if (typeof document.addEventListener !== 'undefined') {
            document.addEventListener('load', setup, false);
        } else if (typeof window.attachEvent !== 'undefined') {
            window.attachEvent('onload', setup);
        } else {
            if (typeof window.onload === 'function') {
                const oldonload = onload;
                window.onload = function () {
                    oldonload();
                    setup();
                };
            } else {
                window.onload = setup;
            }
        }
    })(function () {
        state.isOverIFrame = false;
        state.firstBlur = false;
        state.hasFocusAcquired = false;

        findIFramesAndBindListeners();

        document.body.addEventListener('click', onClick);

        if (typeof window.attachEvent !== 'undefined') {
            top.attachEvent('onblur', function () {
                state.firstBlur = true;
                state.hasFocusAcquired = false;
                onIFrameClick()
            });
            top.attachEvent('onfocus', function () {
                state.hasFocusAcquired = true;
                console.log('attachEvent.focus');
            });
        } else if (typeof window.addEventListener !== 'undefined') {
            top.addEventListener('blur', function () {
                state.firstBlur = true;
                state.hasFocusAcquired = false;
                onIFrameClick();
            }, false);
            top.addEventListener('focus', function () {
                state.hasFocusAcquired = true;
                console.log('addEventListener.focus');
            });
        }

        setInterval(findIFramesAndBindListeners, 500);
    });

    function isFF() {
        return navigator.userAgent.search(/firefox/i) !== -1;
    }

    function isActiveElementChanged() {
        const prevActiveTag = document.activeElement.tagName.toUpperCase();
        document.activeElement.blur();
        const currActiveTag = document.activeElement.tagName.toUpperCase();
        return !prevActiveTag.includes('BODY') && currActiveTag.includes('BODY');
    }

    function onMouseOut() {
        if (!state.firstBlur && isFF() && isActiveElementChanged()) {
            console.log('firefox first click');
            onClick();
        } else {
            document.activeElement.blur();
            top.focus();
        }
        state.isOverIFrame = false;
        console.log(`onMouseOut`);
    }

    function onMouseOver() {
        state.isOverIFrame = true;
        console.log(`onMouseOver`);
    }

    function onIFrameClick() {
        console.log(`onIFrameClick`);
        if (state.isOverIFrame) {
            onClick();
        }
    }

    function onClick() {
        console.log(`onClick`);
    }

    function findIFramesAndBindListeners() {
        return Array.from(document.getElementsByTagName('iframe'))
            .forEach(function (element) {
                element.onmouseover = onMouseOver;
                element.onmouseout = onMouseOut;
            });
    }
}
Slesh
источник
0

Предположения -

  1. Ваш скрипт запускается за пределами iframe, НО НЕ во внешнем окне window.top. (Для внешнего окна достаточно других решений размытия)
  2. Открывается новая страница, заменяющая текущую страницу / новую страницу в новой вкладке, и управление переключается на новую вкладку.

Это работает для обеих sourceful и без исходных фреймов

var ifr = document.getElementById("my-iframe");
var isMouseIn;
ifr.addEventListener('mouseenter', () => {
    isMouseIn = true;
});
ifr.addEventListener('mouseleave', () => {
    isMouseIn = false;
});
window.document.addEventListener("visibilitychange", () => {
    if (isMouseIn && document.hidden) {
        console.log("Click Recorded By Visibility Change");
    }
});
window.addEventListener("beforeunload", (event) => {
    if (isMouseIn) {
        console.log("Click Recorded By Before Unload");
    }
});

Если открывается новая вкладка / та же страница выгружается, а указатель мыши находится внутри iframe, считается, что щелчок

Сахил Маниар
источник