turn.js and Google Analytics - javascript

I'm trying to gather either an event or custom variable tracking on the turn.js plugin through Google Analytics. Right now it's set up for a custom variable. I'm trying to track time on page turns. In the plugin there is an event handler called 'turned'. This is an event that runs when the page has been turned. I have my analytics set up here, but they are collecting to google incorrectly. Any help with this is appreciated. I have the JS event below:
when: {
turned: function(event, page, view) {
_gaq.push(['_setCustomVar', 1, 'Page Spread Scope 1', 'page spread ' + view, 1 ]);
_gaq.push(['_trackPageview']);
}
}

Not sure what exact data you want but I think it is something like this.
Just wrote it right now, so haven't fully tested it. I did debug it and it seems to work fine.
It should record the page+pagenumber and it should record the time on that page with the new _trackTiming method
For your page turn this snippet:
<script>
$('#magazine').turn().bind("click", function(event){
pagenumber = $('#magazine').turn('page');
myTimer();
});
</script>
And then this in your head somewhere.
<script>
var startTime = new Date().getTime();
function myTimer(event) {
var endTime = new Date().getTime();
var timeSpent = endTime - startTime;
var hourInMillis = 1000 * 60 * 60;
if (0 < timeSpent && timeSpent < hourInMillis) {
_gaq.push(['_trackTiming', 'page-timer', 'time-on-page', timeSpent, pagenumber, 1]);
_gaq.push(['_trackPageview', 'turnedpage-' +pagenumber]);
}
return this;
}
//wiremedia.nl
</script>

Related

function not working properly when run on document ready

I have a form with 2 fields: date field #datefromtoday and number of days #daysfromtoday. I use a javascript function to:
1) Automatically listen to the datefromtoday and (if there is a date) display the number of days from today when the page is loaded
2) adjust the date from today when entering/modify the number of days.
Here is the code:
$(document).ready(function (){
function modifyDays(){ //definy function to modify days
var endDateToDays = $( "#datefromtoday" ).val();
var endDateToDays_obj = new Date(endDateToDays); // convert in object
var endDateToDays_ms = endDateToDays_obj.getTime(); // convert in ms
var todayDate = new Date(); //
var todayDate_ms = todayDate.getTime(); //
var daysFromToday = parseInt(Math.ceil( (endDateToDays_ms - todayDate_ms) / 1000 / 60 / 60 / 24 ) ) || ''; //if not number display nothing
document.getElementById("daysfromtoday").value = daysFromToday; //outuput
}
modifyDays(); //here is the problem. If I delete this line of code, everything works perfectly
$("#datefromtoday").on('change', function(){ //run function when modify delay date
modifyDays();
});
});
PROBLEM
the modifyDays function works like a charm on the on.change event, but
when is loaded on document ready, it interferes with datatables www.datatables.net and also with other scripts, and they don't work anymore...
I'm probably using the wrong code to call the function on page load.... any ideas? Thanks for your help!!!
If you think it is because of calling the main function, in the body element of the html page, add an onload attribute:
<body onload="loaded()">
and declare loaded as that main function:
var loaded = function (){
function modifyDays(){ //definy function to modify days
var endDateToDays = $( "#datefromtoday" ).val();
var endDateToDays_obj = new Date(endDateToDays); // convert in object
var endDateToDays_ms = endDateToDays_obj.getTime(); // convert in ms
var todayDate = new Date(); //
var todayDate_ms = todayDate.getTime(); //
var daysFromToday = parseInt(Math.ceil( (endDateToDays_ms - todayDate_ms) / 1000 / 60 / 60 / 24 ) ) || ''; //if not number display nothing
document.getElementById("daysfromtoday").value = daysFromToday; //outuput
}
modifyDays(); //here is the problem. If I delete this line of code, everything works perfectly
$("#datefromtoday").on('change', function(){ //run function when modify delay date
modifyDays();
});
};
Then it should work if the problem is how the function is called.
I don't think the problem is because of you are calling the function on page load. The error might be coming from inside the function modifyDays. Only dependency I see is #datefromtoday and #daysfromtoday. Check whether those nodes are there when the function execute on dom ready event.
If the timing of the function call is the problem, you can put the modifyDays(); call in a window.setTimeout(modifyDays, 5000); or something of the sort to delay it until the other scripts finish loading, so this snippet doesn't interrupt or interfere with them. You may want to put a placeholder in the html for the seconds when it isn't loaded yet if this works.

Updating Momentjs FromNow() in a div element

I'm having this div element that shows the time past since it got created. However it doesn't get updated and always remains on few seconds ago. It looks like this
var newMsg= "<div id="chat-time">'+ moment().fromNow()+'</div>";
$("#chat-list").html( newMsg);
How can I update this text. I know I can do it with sentInterval but I can't figure out how to do it properly.It just prints out seconds! I'm using this for a chatroom. So each message will have a timestamp in the formatof momentjs.fromNow().
Does setting timer for all these message create a problem? I'd appreciate a hint.
EDIT:I'm using this code as mentioned in below but it's not showing anything:
<div id="chat-time"></div>
var messageTimeStamp = new Date();
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-time").html(time);
}, 1000);
To make this work you need the element in the dom and the setInterval running without being included in any string concatenation
HTML
<div id="chat-time"></div>
JS
var $chatTime = $('#chat-time').text(moment().fromNow());
setInterval(function(){
var time = moment().fromNow();
$chatTime.txt( time );
}, 1000);
UPDATE 2
Given that you're using socket.io, you'd do something like this (demo: http://plnkr.co/edit/QuaMV6x1vNB0kYPaU6i1?p=preview):
// The messages the user can currently see.
var messages = [];
// You have something like this in your code, presumably.
socket.on('new message', function(data) {
addChatMessage(data);
});
function addChatMessage(data) {
// First add the message to the dome, with a unique id for the timestamp text.
var messageElementId = 'chat-message-' + data.messageId;
$("#chat-list").prepend($("<div>" + data.message + "<i> (sent: <span id='" + messageElementId + "'>just now</span>)</i></div>"));
// When you no longer display that message in the DOM it from clear this array. I'd render the DOM based on this list if I were you.
messages.push({
messageElementId: messageElementId,
timestamp: data.timestamp
});
}
// By updating all the messages at once you don't have memory leaks.
setInterval(function() {
messages.forEach(function(message) {
var time = moment(message.timestamp).fromNow();
$("#" + message.messageElementId).text(time);
});
}, 1000);
UPDATE 1
Given this is your code:
var newMsg= "<div id="chat-time">'+ moment().fromNow()+'</div>";
$("#chat-list").html(newMsg);
You would do this, instead:
var messageTimeStamp = new Date(); // You need to grab this from somewhere.
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-list").html(time);
}, 1000);
You need to use moment(TIMESTAMP_OF_MESSAGE) not moment() and do something like this:
$(function(){
$("body").append($('<div id="chat-time"></div>'));
var messageTimeStamp = new Date();
var i = 0;
setInterval(function(){
var time = moment(messageTimeStamp).fromNow();
$("#chat-time").html('moment().from(messageTimeStamp): ' + time + '; setInterval calls made ' + i++);
}, 1000);
});
Here's a demo.
http://plnkr.co/edit/QuaMV6x1vNB0kYPaU6i1?p=preview
I dont see any problem using setInterval (). AngularJS wrapper setInterval on $interval service module . Check out these urls: interval Angular and Wrapper SetInterval

countdown disappears after its parent div is loaded via .load jquery method

I have a countdown which is activated after the page is loaded:
$(document).ready(function() {
var rem_hour = $("#user-card-second-remaining").attr("rem_hour");
var rem_min = $("#user-card-second-remaining").attr("rem_min");
var rem_sec = $("#user-card-second-remaining").attr("rem_sec");
var currentDate = new Date();
var targetDate = new Date(currentDate.getTime() + rem_hour * 60 * 60000 + rem_min*60000 + rem_sec * 1000);
$("#user-card-second-remaining").countdown(targetDate, function(event) {
$(this).html(event.strftime('%H:%M:%S'));
});
});
Every minute, I load a div partially of this page, and #user-card-second-remaining is inside this loaded div.
function fn60sec() {
// runs every 60 sec and runs on init.
var pathname = window.location.pathname;
var card = pathname + " #user-card";
$( "#user-card-wrapper" ).load(card);
}
The problem is that when I loaded new #user-card-second-remaining div, countdown event disappears.
It seems, I think, I should refresh dom (not page) such that .countdown method could be bind into fresh #user-card-second-remaining div.
How can I do that?
When the DOM is updated, all jquery stuff attached to DOM elements are removed.
Well actually, the DOM element with the jquery styff is removed, and replaced with another event, brand new, without jquery stuff.
What you need to do, is add the jquery stuff again after you update the DOM, as you suggested.
function fn60sec() {
// runs every 60 sec and runs on init.
var pathname = window.location.pathname;
var card = pathname + " #user-card";
$( "#user-card-wrapper" ).load(card, function() {
var rem_hour = $("#user-card-second-remaining").attr("rem_hour");
var rem_min = $("#user-card-second-remaining").attr("rem_min");
var rem_sec = $("#user-card-second-remaining").attr("rem_sec");
var currentDate = new Date();
var targetDate = new Date(currentDate.getTime() + rem_hour * 60 * 60000 + rem_min*60000 + rem_sec * 1000);
$("#user-card-second-remaining").countdown(targetDate, function(event) {
$(this).html(event.strftime('%H:%M:%S'));
});
});
});
should do the trick.
What library/plugin is .countdown( from? You need to look at their documentation for a delegated event overload, or an alternative using an event name so you can use jquery .on('eventname',
Usually in this situation you use a pattern
$('#staticSelector').on('countdown', '#user-card-second-remaining', function() ...
and this listens on #staticSelector for events bubbling up from '#user-card-second-remaining'. So #staticSelector needs to be an element that always exists, but the '#user-card-second-remaining' can come and go as needed being refreshed inside your div that is being refreshed.
The section here on Direct and delegated events explains this:
http://api.jquery.com/on/

Monitor single page loading times in javascript

I've got an existing single page web application of which I can't change the code. Some users complain that the application is not performing very well.
I would like to monitor the loading time in this way:
Record the time stamp of a click on the page
Record the time stamp of when the rendering of the page has been completed, after ajax requests and some other javascript magic has been done
Calculate the difference between the two time stamps and post it back to the server.
I can easily do step 1 and 3 with jQuery, however I'm not sure what's the best way to approach step 2?
As this seems to be a quite obvious scenario, is there a standard tool set to perform this kind of monitoring?
This helps:
function onLoad() {
var now = new Date().getTime();
var page_load_time = now - performance.timing.navigationStart;
console.log("User-perceived page loading time: " + page_load_time);
}
You could use the global ajaxStop event jQuery offers.
var start = +(new Date());
$(document).ajaxStop(function() {
var diff = +(new Date()) - start;
// do logging
});
This won't include the code executed after the last AJAX call, but if things happening before the last call contain the expected bottleneck, then this will be quite useful.
this can be achieved in following way...
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="jquery.min.js"></script>
<script type="text/javascript">
var startTime, endTime, timeDifference;
function doIt() {
var startTime = new Date().getTime();
$.ajax({
type: 'post',
url: 'a.php',
success: function (resp) {
endTime = new Date().getTime();
timeDifference = endTime - startTime; //Time Difference is stored in milliseconds
}
})
}
</script>
</head>
<body>
<button style="position: absolute; top:60px" onclick="doIt()">start</button>
</body>
</html>
It's not a perfect solution, however the following code is working. It start the timer when a user clicks. The checkHTML function monitors the changes in the page content.
var timeLogging = new Array();
var timeStart;
$(document).click(function() {
initLogEvent();
});
function initLogEvent() {
caption = $(".v-captiontext:first").text();
timeStart = +(new Date());
timeLogging.push(new Array(0,0));
timeLogging[timeLogging.length - 1][0] = timeStart;
}
initLogEvent();
// Start a timer to check the changes in html
window.setInterval(checkHtml, 250);
// Start a timer to create the reports
window.setInterval(sendReport, 1000);
var html;
function checkHtml() {
current = $("body").html();
if (current != html) {
html = current;
var diff = +(new Date()) - timeStart;
timeLogging[timeLogging.length - 1][1] = diff;
}
}
function sendReport() {
if (timeLogging.length > 3) {
console.log(timeLogging);
// Do additional stuff with the collected data
for (i = 0; i <= timeLogging.length; i++) {
timeLogging.shift();
}
}
}
Are you keeping all you application's markup in the page, even when it is hidden? If so you are probably choking the browser's memory. I recommend learning to offload your markup in localStorage like Bing and Google pioneers a few years ago. I wrote a blog about it the day I discovered the technique and I have used it ever since.
http://love2dev.com/#!article/Use-Local-Storage-to-Make-Your-Single-Page-Web-Application-Rock

Javascript link tracking script + Safari

I'm trying to make a link tracking script. It should work like Google Analytics only it should make posts to our own server. I'm using jQuery for this. The code i have written so far is the following:
jQuery(document).ready(function() {
var opts;
jQuery.fn.trackAllLinks = function(settings) {
settings = jQuery.extend({}, jQuery.fn.trackAllLinks.defaults, settings);
opts = settings;
function track() {
href = jQuery(this).attr('href');
var trackImage = new Image(1, 1);
trackImage.src = opts.linkredirector + '?eurl=' + jQuery.URLEncode(href) + '&rnd=' + new Date().getTime() + '&title=trackerimage.gif';
trackImage.onload = function() {
trackImage.onload = null;
doNothing();
}
delay(300);
return true;
};
function delay(mseconds) {
var currentTime = new Date();
var endTime = currentTime.getTime() + mseconds;
while (currentTime.getTime() < endTime) {
currentTime = new Date();
}
}
function doNothing() {
}
if(jQuery(this).is("a")) {
jQuery(this).click(track);
}
jQuery(this).find("a").click(track);
};
jQuery.fn.trackAllLinks.defaults = {
linkredirector : '__url_to_post_on__'
};
});
It works fine in all browsers except Safari. When i'm using a mailto link or an anchor it works but when i'm linking to another page it doesn't work. I have been testing a lot of different implementations and i can't get it to work. Any of you have an idea what i'm missing? I have tried to understand how Google Analytics works and as far as i can see it does the same. When i use WireShark to monitor my network i see that the image of Google is being requested but that my image isn't.
greets,
Daan
This is random, but you might try adding a randomized parameter in the query string (both the name & value), like:
Math.random(0, 1000) + '=' + Math.random(0, 1000)
I've had to do that in the past to get Safari to register a dynamically loaded resource.
(I see you have &rnd= already, but maybe try randomizing the name, too?)

Categories

Resources