Using new Image().src for click tracking - javascript

I am attempting to figure out why this click tracker isn't working. The code was written by another developer so I am not entirely sure if this ever did work.
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
From what I can gather is that when this function is called it 'creates a new image' to fire a php script asynchronously. According to Firebug, the request is made however it is 'aborted' ~30ms in. The odd thing is that it will 'sometimes' work as in 1 in every 10+ regardless of the browser.
I would much rather fix this so that it works instead of re-writing it as an ajax request.
Any help is appreciated.
Thanks in advance.
EDIT
Because of tvanfosson's post that got me thinking. I have included the line which calls the click tracker below.
<a onclick="trackSponsor(60, 15077); goToNextStep(1988, 15077, 0); return false;" href="#">view</a>
the goToNextStep() actually changes the page. I am under the impression that it would only be executed after trackSponsor() had finished.

It's actually pretty trivial to rewrite as a get request using jQuery. Rewriting it will certainly help the next developer understand what's happening and might fix your problem. I'd need to know more about the contents of the variables -- perhaps they need to be urlEncoded? -- before I could help you any more on it. You might try urlEncoding them and see what happens.
function trackSponsor(o, p) {
var url = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
$.get(url);
return false;
}
EDIT: you might want to check that another handler isn't redirecting the browser to a new location when the event triggering the tracking is invoked. This would abort any pending requests on the page -- and might allow a few to succeed based on the timing of the requests and if the results are delivered before the page is unloaded.

"(new Image()).src = url;" just asks for browser to hit the url.
You should delay for a 50-100ms in order to be sure that tracking info were sent to the server.
function delay(a) {
for (var b = +new Date, c = 1; 0 < c; c++) {
if (0 == c % 1E3) {
var e = +new Date;
if (b > e) break;
if (e - b > a) break;
}
}
}
function trackSponsor(o, p) {
(new Image()).src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
delay(100);
return false;
}

I poked around Google Analytics’ ga.js, which does use the new Image() method similar to your script.
The only difference that I could see was in how the object is created. Google's script assigns the object to a variable.
var d=new Image(1,1);d.src=f;
Maybe give that a shot?
function trackSponsor(o, p) {
var i = new Image(1,1);
i.src = PATH_BASE + 'click/' + p + '/' + o + "?_cache=" + (+(new Date()));
return false;
}
It shouldn't make a difference, but is worth a shot.

Maybe try this, for avoiding Garbage Collection to make your log not be lost.
var sendLog = (function () {
var _unique = (function () { /* 产生唯一标识*/
var time = (new Date()).getTime() + '_',
i = 0;
return function () {
return time + (i++);
}
}());
var run = function (url) {
var data = window['imgLogData'] || (window['imgLogData'] = {}),
img = new Image(),
uid = _unique();
data[uid] = img; /* 防止img被垃圾处理*/
img.onload = img.onerror = function () { /* 成功或失败后销毁对象*/
img.onload = img.onerror = null;
img = null;
delete data[uid];
};
img.src = url + '&_cache=' + uid; /* 发送统计内容*/
};
return run;
}());
sendLog('http://log_');

Related

Javascript : workers doesn't do anything onmessage

I'm trying to create a reminder at a certain date. For that i'm using web-workers with active waiting.
Main.js :
function reminder(message, api) {
var worker = new Worker("./worker.js");
var mesCore = message.body.substr(message.body.indexOf(" ") + 1);
worker.onmessage = function (e) {
api.sendMessage("Ding dong " + mesCore, message.threadID);
};
worker.postMessage(mesCore);
}
worker.js
const cron = require('node-cron');
// reach this line when create worker
onmessage = function(e) {
// never reach this line
console.log(e.data);
var origin = new Date(e.data);
cron.schedule("* * *", function() {
var now = new Date();
if (
origin.getFullYear() == now.getFullYear() &&
origin.getMonth() == now.getMonth() &&
origin.getDate() == now.getDate()
) {
postMessage('message');
return;
}
});
}
Unfortunately the worker never reach the onmessage content. I tried this.onmessage and self.onmessage but it doesn't work. I also tried with "addEventListener" but doesn't work either.
I'm doing this in javascript because the api that I'm using is in javascript so I have no choice.
Thank you if can't help me find a solution

$.getJSON with for loop, just working when debugging

**I really need help, because I´m not able to find a working solution or do it by my self. The problem is, that I can´t get the information. "data" should include 23 objects. The thing is, while debugging everything works well. Please help me!!! I am nearly on my end. and Callback or then.(function...) are not working for me... ;( **
function query_day2day(DateArray_){
var Fluid_id = 0;
var data_list = new Array();
//read out the select element
var e = document.getElementById("select_fluid");
var Fluid_id = e.options[e.selectedIndex].value;
//read in date
//var d = document.getElementById("datepicker");
//var date = d.value;
var dateArray = new Array();
dateArray = DateArray_;
//Bring the date array in the correct form to submit
for(i = 0; i<dateArray.length; i++)
{
var year = dateArray[i].substring(6, 10); //substring(start, end)
var month = dateArray[i].substring(0, 2);
var day = dateArray[i].substring(3, 5);
dateArray[i] = year + "-" + month + "-" + day;
//alert(dateArray[i]);
}
for(i = 0; i<dateArray.length; i++)
{
switch (Fluid_id) {
case '1':
$.getJSON(setAddress_Event() + 'liter_hour/' + Fluid_id + '/' + dateArray[i], function(data){
//data_callback(data, i); //I don´t understand this concept ;(
data_list[i] = data;
});
break;
case '2':
$.getJSON
Updated
function getData(setAddress_Event, liter_hour, Fluid_id, dateArray){
return $.getJSON(setAddress_Event + liter_hour + Fluid_id + "/" + dateArray).then(function(data){
return {
data_list:data
}
});
}
for(var j = 0; j<dateArray.length; j++)
{
getData(setAddress_Event(), "liter_hour/", Fluid_id, dateArray[j]).then(function(returndata){
//received data!
alert(j);
data_collection[j] = returndata;
});
}
alert(data_collection); //Hier ist data_list undefined und beim returnen wird es richtig übergeben.... ohne diesem alert wird falsch übergeben.... dreck
return data_collection;
Please help me, I need all data not just the last one. Debugging works, I don´t know what´s here the problem....
Debugg Snippet
This is because you are accessing the data before the Ajax requests for retrieving the JSON have sent back the responses. Be aware that when you execute
getData(setAddress_Event(), "liter_hour/", Fluid_id, dateArray[j]).then(function(returndata){
//received data!
alert(j);
data_collection[j] = returndata;
});
... the inner function is not executed. It is only passed on to getData, and your code continues immediately. Only when the execution reached the end of the script, will the Ajax requests one by one call your callback function, so they all execute after the main scripts ends.
Here is how you could deal with that (introducing a variable numPendingResults):
var numPendingResults = dateArray.length;
for(let j = 0; j<dateArray.length; j++) {
getData(setAddress_Event(), "liter_hour/", Fluid_id,
dateArray[j]).then(function(returndata){
//received data!
data_collection[j] = returndata;
numPendingResults--; // one less to wait for!
if (!numPendingResults) { // we have everything!
console.log(data_collection);
// anything you want to do with data_collection should be done here
// ...
// or call a function that will deal with it, from here.
}
});
}
You cannot return the data_collection. Instead you should call a function like described above. Possibly that function can be passed as argument by the outermost function. Or use the Promise system one step further. For you to decide...
Try something similar to this. You may need to loop through the elements in order to use them.
$.getJSON('/ReferenceData/PhoneType',
function (data) {
if (!isBound) {
dropDownToBind.append($('<option></option>').val(-1).html('- Select Type -'));
$.each(data, function (index, element) {
dropDownToBind.append($('<option></option>').val(element['Id']).html(element['Value']));
});
isBound = true;
}
});
// OR this
$.getJSON(url, params, function (data) {
if (data != null) {
zip_code_field.closest('.formCol').find('.ZipCity').val(data.City);
zip_code_field.closest('.formCol').find('.ZipState').val(data.State);
$.uniform.update();
}
});

Ajax for "load on scroll" script delivers 403

I'm building a blog on the hubspot cos. We want the blog posts to load on scroll. I found a script that states that it does this and is specifically for Hubspot.
That being said, I'm getting a 403 in the console when I activate the script by scrolling. I don't think this is a hubspot issue as much as an Ajax issue.
The script I am using:
www.uvm .edu/~enewbury/swoosh/
The script on our hubspot cdn:
http://cdn2.hubspot.net/hub/1739321/hub_generated/template_assets/1452520555218/custom/page/JS/Swoosh.min.js
The blog:
http://insights.signetaccel.com/blog
The only thing that sticks out to me is that the ajax request is cross domain, but this is a normal thing in hubspot between files and the company domain so if this script was built for use in hubspot I would think the owner would have accounted for this.
I've looked all of for an answer, and I've come up empty handed. It should be noted that a php proxy wouldn't work as server side programming is not an option with hubspot.
I would really appreciate some an answer or some tips on what to do here.
$(document).ready(function(){
$(".grid").swoosh();
});
(function(a) {
a.fn.swoosh = function(f, k) {
if (!f) {
f = "Loading..."
}
if (k == null) {
k = -1
}
var c = this;
var e = false;
var j = 2;
var d = window.location.href.toString().split("/");
var i = d[0] + "//" + d[2] + "/" + d[3] + "/";
var h = i + "page/";
var g = "";
var b = false;
if (f != "Loading...") {
c.parent().append('<div class="loading"><img src="' + f + '"></div>')
} else {
c.parent().append('<div class="loading">' + f + "</div>")
}
a(".loading").hide();
a(document).scroll(function() {
if (b || e || j == 0) {
return false
}
if (a(window).scrollTop() >= a(document).height() - a(window).height() - a(".footer-container-wrapper").height() - 150) {
b = true;
a(".loading").fadeIn(200);
g = h + j;
a.post(g, function(m) {
var l = a(m).find(".grid-item");
if (l.length) {
console.log(f);
a(".loading").fadeOut(200, function() {
l.appendTo(".grid")
});
j++;
a(".next-posts-link").attr("href", h + j)
} else {
e = true;
a(".next-posts-link").after('<div class="next-posts-link unactive">Next</div>');
a(".next-posts-link:not(.unactive)").remove();
a(".loading").fadeOut(200)
}
b = false;
setTimeout(function() {
twttr.widgets.load();
IN.parse();
FB.XFBML.parse();
gapi.plusone.go()
}, 350)
})
}
})
}
})(jQuery);
(function() {
return window.SIG_EXT = {};
})()
TL;DR -- You're getting a 403 because the script is using jQuery's .post instead of .get; an http POST to a HubSpot COS/blog page is not allowed. This appears in line 45 of the raw js example here: http://www.uvm.edu/~enewbury/swoosh/swoosh.js
Switch out the HTTP method for a GET, then continue debugging. The script is unofficial and, though intended to be generic, relies on specific body structure generated by HubSpot's COS/blog and classing of elements. More debugging may be required to get it working.
Details:
The way this script works is a bit kludgey. Its not fetching blog content from an API or other efficient resource -- instead, it grabs the full HTML of /page/2, /page/3, etc as you scroll, parsing out the blog post HTML from the response it retrieves, and injecting the posts it finds in the async fetch into the current page.
Using a POST rather than a GET to fetch this content is generating a 403 Forbidden.
There may be more issues as the script depends very much on certain elements being classed a specific way, but this fixes your immediate 403 issue.

onResourceReceived logs every resource twice?

I'm trying to use phantomjs to get some metrics about the likelihood of a race condition affecting a page, I have 2 script files, some functionality hosted on my site is dependant on some globals set by a file coming from a third party.
I thought that using onResourceReceived in phantomjs I could log when each file loads and then run that test a bunch of times to get an idea of how often this race condition will cause issues, an example of my code is below (it's not the actual code and I'm not affiliated with the BBC):
(function (p, wp) {
"use strict";
var page, start,
count = 0, max = 10,
webpage = require('webpage'),
url = "http://www.bbc.co.uk";
function process() {
if (max == count) {
console.log('done processing!');
p.exit();
} else {
count++;
start = new Date();
page = wp.create();
page.onResourceReceived = onResourceReceived;
page.open(url, onOpen);
}
}
function onResourceReceived(response) {
var match, t = new Date(),
url = response.url,
status = response.status;
t = t.valueOf() - start.valueOf();
if (!!(match = url.match(/locator\.css/))) {
console.log(match[0] + ': ' + t + 'msecs status: ' + status);
}
if (!!(match = url.match(/en-GB\.json/))) {
console.log(match[0] + ': ' + t + 'msecs status: ' + status);
}
};
function onOpen() {
console.log('Test ' + count + ' done!!!');
page.close();
process();
}
process();
}(phantom, require('webpage')));
This kinda runs how I expected except that each file is logged twice, why is this?
Sometimes the time differences are very different.
locator.css: 323msecs status: 200
locator.css: 323msecs status: 200
en-GB.json: 2199msecs status: 200
en-GB.json: 2200msecs status: 200
Test 1 done!!!
You need to check for response.stage property. stage will have start and end. start gives the first byte arrived time and end give you the when you got the complete response.
please add a check in your function.
function onResourceReceived(response) {
if(response.stage == 'end') return;
//rest of your code from above example.
};

Javascript - Images not cycling/rotating

I'm working on a script to rotate/cycle through images in javascript while respecting a limit on the amount of times it cycles through the images. What I have is below:
<a id="imageurl"><img id="Rotating1" border="0"></img></a>
<script language="JavaScript">
var delay = 3000; //6000 = change to next image after 6 seconds
var cycles = 2;
var currentCycle = 0;
function RotateImages(Start, delay)
{
var a = new Array("frown.gif","grim.gif","smile.gif", "bomb.gif");
var c = new Array("url1", "url2", "url3", "url4");
var b = document.getElementById('Rotating1');
var d = document.getElementById('imageurl');
var totalCycles = cycles * a.length;
// alert ("currentCycle: " + currentCycle);
// alert ("totalCycles: " + totalCycles);
if (Start>=a.length)
Start=0;
b.src = a[Start];
d.href = c[Start];
if (currentCycle < totalCycles) {
window.setTimeout("RotateImages(" + (Start+1) + ")", delay);
currentCycle++;
}
}
RotateImages(0, delay);
</script>
The script acts like it's working when I uncomment the alert boxes. When I comment them out, the rotation seems to stop. Any ideas on what is really going on and how to fix it?
Thanks!
perhaps you would like to change this line:
window.setTimeout("RotateImages(" + (Start+1) + ")", delay);
into:
window.setTimeout("RotateImages(" + (Start+1) + ", " + delay + ")", delay);
so that the next time RotateImages is called, it will keep the delay.
One fundamental issue to take into consideration is with setTimeout. The first parameter can be a reference to a function, whether it be an actual reference or a string reference, but you cant pass parameters along with it.
To do what you want, you need to pass a anonymous function to setTimeout. Also, Riyono is right that you should also pass the delay
setTimeout(function(){ RotateImages(Start++, delay) }, delay);
As far as your alert issue, I don't know what to tell you. But I know that the above will correct some issues.

Categories

Resources