function OpenAdViewability(config) { this.check = { percentViewable: 0, percentFps: 0, percentIntersection: 0, acceptedViewablePercentage: 50, acceptedMrcPercentage: 50, viewabilityStatus: false, duration: 0, measureTime: 3000 }; const configNew = config || {}; Object.assign(this.check, configNew); this.timer = null; this.statusCallback = null; this.startTime = null; this.viewable = 100; this.vcStarted = false; this.config = {}; this.log = function () { if (this.config.debug || this.config.showLog) { var conArg = ["%cMOVIEADS-BN OAV: ", "background-color: orange; color: black; font-weight: bold"]; var mainArguments = Array.prototype.slice.call(arguments); conArg = conArg.concat(mainArguments); console.log.apply(console, conArg); } }; this.DEBUG_MODE = false; this.cancelCheck = function () { window.cancelAnimationFrame(this.timer); }; this.getTime = function () { return 'object' === typeof window.performance ? window.performance.now() : new Date().getTime(); }; this.initViewabilityCheck = function () { if (this.vcStarted) { return; } this.vcStarted = true; var io = new IntersectionObserver(function (entries) { for (var eKey in entries) { var entry = entries[eKey]; this.viewable = Math.floor(entry.intersectionRatio*100); if ('isIntersecting ' in entry) { console.log('isIntersecting', entry.isIntersecting); } if ('isVisible ' in entry) { console.log('isVisible', entry.isVisible); } console.log('viewable', this.viewable); } }.bind(this), { threshold: [0,0.1,0.15,0.20,0.25,0.30,0.35,0.40,0.45,0.50,0.55,0.60,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1], trackVisibility: true, delay: 100 }); io.observe(document.body); window.addEventListener('beforeunload', () => { if (typeof IntersectionObserver != 'undefined') { io.unobserve(document.body); io = null; } }); }; this.checkViewability = function (statusCallback) { this.initViewabilityCheck(); this.statusCallback = statusCallback; this.startTime = this.getTime(); this.timer = window.requestAnimationFrame(this.countDownStart.bind(this)); }; this.countDownStart = function() { this.log('MRC countDownStart'); let viewable = this.checkViewable(); if (!viewable) { this.log('OAV MRC TRACKER STATS, visibility: ',this.check.percentFps, ', mrc vis: ',this.check.percentFps, 'accepted fps: ', this.check.acceptedMrcPercentage, ' viwability: ', this.check.acceptedViewablePercentage, 'vw: ', this.viewable, 'state:', document.visibilityState); this.startTime = this.getTime(); this.resetCheck(); } var offset = this.getTime() - this.startTime; var timeUp = offset >= this.check.measureTime; this.check.duration = offset; if (timeUp) { this.check.viewabilityStatus = (this.check.percentViewable >= this.check.acceptedViewablePercentage); // if (!this.DEBUG_MODE) { // window.cancelAnimationFrame(this.timer); // } if (this.check.viewabilityStatus) { this.statusCallback(this.check); } } else { this.timer = window.requestAnimationFrame(this.countDownStart.bind(this)); } }; this.resetCheck = function () { this.check.percentFps = 0; this.check.percentIntersection = 0; this.check.percentViewable = 0; this.check.duration = 0; this.check.viewabilityStatus = false; }; this.checkViewable = function () { let visibility = this.viewable; //let mrc = Math.floor(this.ad.fps*100/this.ad.baseFps); // mrc = mrc > 100 ? 100 : mrc; // // this.check.percentFps = mrc; this.check.percentIntersection = visibility; if (document.visibilityState != 'visible') { this.startTime = this.getTime(); return false; } // this.check.percentViewable = Math.floor((visibility+mrc)/2); this.check.percentViewable = Math.floor(visibility); // if (visibility < this.check.acceptedViewablePercentage || mrc < this.check.acceptedMrcPercentage) { if (visibility < this.check.acceptedViewablePercentage || visibility < this.check.acceptedMrcPercentage) { return false; } return this.check.percentViewable; }; }