var ready = (function(){ var readyList, DOMContentLoaded, class2type = {}; class2type["[object Boolean]"] = "boolean"; class2type["[object Number]"] = "number"; class2type["[object String]"] = "string"; class2type["[object Function]"] = "function"; class2type["[object Array]"] = "array"; class2type["[object Date]"] = "date"; class2type["[object RegExp]"] = "regexp"; class2type["[object Object]"] = "object"; var ReadyObj = { // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { ReadyObj.readyWait++; } else { ReadyObj.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( ReadyObj.ready, 1 ); } // Remember that the DOM is ready ReadyObj.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --ReadyObj.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ ReadyObj ] ); // Trigger any bound ready events //if ( ReadyObj.fn.trigger ) { // ReadyObj( document ).trigger( "ready" ).unbind( "ready" ); //} } }, bindReady: function() { if ( readyList ) { return; } readyList = ReadyObj._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( ReadyObj.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", ReadyObj.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", ReadyObj.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, _Deferred: function() { var // callbacks list callbacks = [], // stored [ context , args ] fired, // to avoid firing when already doing so firing, // flag to know if the deferred has been cancelled cancelled, // the deferred itself deferred = { // done( f1, f2, ...) done: function() { if ( !cancelled ) { var args = arguments, i, length, elem, type, _fired; if ( fired ) { _fired = fired; fired = 0; } for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = ReadyObj.type( elem ); if ( type === "array" ) { deferred.done.apply( deferred, elem ); } else if ( type === "function" ) { callbacks.push( elem ); } } if ( _fired ) { deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); } } return this; }, // resolve with given context and args resolveWith: function( context, args ) { if ( !cancelled && !fired && !firing ) { // make sure args are available (#8421) args = args || []; firing = 1; try { while( callbacks[ 0 ] ) { callbacks.shift().apply( context, args );//shifts a callback, and applies it to document } } finally { fired = [ context, args ]; firing = 0; } } return this; }, // resolve with this as context and given arguments resolve: function() { deferred.resolveWith( this, arguments ); return this; }, // Has this deferred been resolved? isResolved: function() { return !!( firing || fired ); }, // Cancel cancel: function() { cancelled = 1; callbacks = []; return this; } }; return deferred; }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ Object.prototype.toString.call(obj) ] || "object"; } } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( ReadyObj.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions ReadyObj.ready(); } // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); ReadyObj.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); ReadyObj.ready(); } }; } function ready( fn ) { // Attach the listeners ReadyObj.bindReady(); var type = ReadyObj.type( fn ); // Add the callback readyList.done( fn );//readyList is result of _Deferred() } return ready; })(); var fixel = { // the various urls corresponding to each supported event urls: { view: 'https://fueledup.com/fixel/view.gif', conversion: 'https://fueledup.com/fixel/conversion.gif', log: 'https://fueledup.com/fixel/log.gif', success: 'https://fueledup.com/fixel/success.gif' }, // the number of items in our event queue count: 0, // the UNIX timestamp at which the queue is invalid and any page redirect should commence w/o blocking expires: null, __dw: [], // any dependencies associated w/ a given offer dependencies: { scripts: null, procedure: function() { try { console.log('Procedure firing'); null } catch ( e ) { console.warn(e.message); } } }, loadDependencies: function() { if ( Array.isArray(fixel.dependencies.scripts) ) { for ( var i = 0; i < fixel.dependencies.scripts.length; i++ ) { var script = document.createElement( 'script' ); script.setAttribute( 'src', fixel.dependencies.scripts[i] ); script.onload = function( e ) { console.log('Loaded script:', e ); } document.head.appendChild(script); } } }, appendUrlParams: function( url, key, value ) { var delimiter = url.indexOf('?') != -1 ? '&' : '?'; return url + delimiter + key + '=' + value; }, buildQueryString: function( url, params ) { for (key in params) { url = fixel.appendUrlParams(url, key, params[key]); } return url; }, injectElement: function( src ) { var element = new Image(); var now = new Date(); ++fixel.count; fixel.expires = now.getTime() + 1000; element.onload = function (event) { console.log('loaded'); --fixel.count; } element.src = src; console.log('inject'); return true; }, success: function() { var url = fixel.appendUrlParams(fixel.urls.success, 'unique', Math.floor((Math.random() * 99999) + 1) ); // need be both defined and truthy // logs any __dw events set on the affiliate site prior to rendering of the included script in the DOM if (typeof __split !== 'undefined' && __split) { url = fixel.appendUrlParams(url, 'split', encodeURIComponent(__split)); } fixel.injectElement(url); }, view: function() { var url = fixel.appendUrlParams(fixel.urls.view, 'unique', Math.floor((Math.random() * 99999) + 1) ); // append the current url as a fallback for HTTP_REFERER if (window.location.href) { url = fixel.appendUrlParams(url, 'ref', encodeURIComponent(window.location.href)); } if (window.location.search) { var qp = window.location.search.substring(1).split('&').map(function(kv) { return kv.split('='); }).filter(function(qp) { return Array.isArray(qp) && qp.length == 2 && qp[1] !== ''; }); if (Array.isArray(qp)) { for (var i = 0; i < qp.length; i++) { url = fixel.appendUrlParams(url, 'fu_' + qp[i][0], qp[i][1]); } } } // append fb conversion api parameters url = fixel.appendUrlParams(url, 'fbp', encodeURIComponent((document.cookie.match(/^(?:.*;)?\s*_fbp\s*=\s*([^;]+)(?:.*)?$/)||[,null])[1])); url = fixel.appendUrlParams(url, 'fbc', encodeURIComponent((document.cookie.match(/^(?:.*;)?\s*_fbc\s*=\s*([^;]+)(?:.*)?$/)||[,null])[1])); // need be both defined and truthy // logs any __dw events set on the affiliate site prior to rendering of the included script in the DOM if (typeof __dw !== 'undefined' && __dw) { url = fixel.appendUrlParams(url, 'dw', encodeURIComponent(JSON.stringify(__dw))); } if (typeof __split !== 'undefined' && __split) { url = fixel.appendUrlParams(url, 'split', encodeURIComponent(__split)); } fixel.injectElement(url); setTimeout(fixel.dependencies.procedure, 1500); }, conversion: function( oid, cid, cd ) { var url = fixel.buildQueryString(fixel.urls.conversion, { 'oid': oid, 'cid': cid, 'cd': cd }); url = fixel.appendUrlParams(url, 'unique', Math.floor((Math.random() * 99999) + 1) ); fixel.injectElement(url); console.log('conversion'); }, log: function(k, v) { if (k && v) { var url = fixel.appendUrlParams(fixel.urls.log, 'unique', Math.floor((Math.random() * 99999) + 1)); fixel.__dw.push({ key: k, value: v }); url = fixel.appendUrlParams(url, 'dw', encodeURIComponent(JSON.stringify(fixel.__dw))); fixel.injectElement(url); // reset fixel.__dw fixel.__dw = []; console.log('log'); } }, unloadHandler: function (e) { var start = new Date(); fixel.expires = fixel.expires || (start.getTime() + 100); do { var now = new Date(); if (fixel.count == 0) { break; } } while (now.getTime() < fixel.expires) } }; ready(function(){ console.log('fixel ready'); window.addEventListener('pagehide', fixel.unloadHandler); window.addEventListener('beforeunload', fixel.unloadHandler); window.addEventListener('unload', fixel.unloadHandler); fixel.loadDependencies(); fixel.view(); });