Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions js/src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@ SnowPlow.hasLocalStorage = function () {
}
}

/*
* Checks whether localStorage is accessible
* reuses the "modernizr" string to keep global namespace tromping to a minimum.
* sets and removes an item to handle IOS5 private browsing.
* (http://git.io/jFB2Xw)
*/
SnowPlow.localStorageAccessible = function() {
var mod = 'modernizr';
if( !SnowPlow.hasLocalStorage() ) {
return false;
}
try {
SnowPlow.windowAlias.localStorage.setItem(mod,mod);
SnowPlow.windowAlias.localStorage.removeItem(mod);
return true;
} catch(e) {
return false;
}
}


/*
* Converts a date object to Unix timestamp with or without milliseconds
Expand Down
96 changes: 76 additions & 20 deletions js/src/tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,81 @@ SnowPlow.Tracker = function Tracker(argmap) {

// Ecommerce transaction data
// Will be committed, sent and emptied by a call to trackTrans.
ecommerceTransaction = ecommerceTransactionTemplate();
ecommerceTransaction = ecommerceTransactionTemplate(),

// Detect whether we have localStorage available
hasLocalStorage = SnowPlow.localStorageAccessible(),
executingQueue = false,
imageQueue;

if( hasLocalStorage ) {
// Catch any JSON parse errors that might be thrown
try {
imageQueue = JSON.parse(localStorage.getItem('snaqImageQueue'));
}
catch (e) {}

}
// Initialize to an empty array if we didn't get anything out of localStorage
if( typeof imageQueue == 'undefined' || imageQueue == null) {
imageQueue = [];
}

/*
* Queue an image beacon for submission to the collector.
* If we're not processing the queue, we'll start.
*/
function queueImage(request) {
imageQueue.push(request);
if( hasLocalStorage ) {
localStorage.setItem('snaqImageQueue',JSON.stringify(imageQueue));
}

if( !executingQueue ) {
executeQueue();
}
}

/*
* Run through the queue of image beacons, sending them one at a time.
* Stops processing when we run out of queued requests, or we get an error.
*/
function executeQueue() {
if( imageQueue.length < 1 ) {
executingQueue = false;
return;
}

executingQueue = true;
nextRequest = imageQueue[0];

/*
* Send image request to the SnowPlow Collector using GET.
* The Collector serves a transparent, single pixel (1x1) GIF
*/
var image = new Image(1, 1);

// Let's chec that we have a Url to ping
if (configCollectorUrl === null) {
throw "No SnowPlow collector configured, cannot track";
}

// Okay? Let's proceed.
image.onload = function() {
// We succeded, let's remove this request from the queue
imageQueue.shift();
if( hasLocalStorage ) {
localStorage.setItem('snaqImageQueue',JSON.stringify(imageQueue));
}
executeQueue();
}
image.onerror = function() {
executingQueue = false;
}
image.src = configCollectorUrl + nextRequest;
}



/**
* Determines how to build our collector URL,
Expand Down Expand Up @@ -304,32 +378,14 @@ SnowPlow.Tracker = function Tracker(argmap) {
return false;
}

/*
* Send image request to the SnowPlow Collector using GET.
* The Collector serves a transparent, single pixel (1x1) GIF
*/
function getImage(request) {

var image = new Image(1, 1);

// Let's chec that we have a Url to ping
if (configCollectorUrl === null) {
throw "No SnowPlow collector configured, cannot track";
}

// Okay? Let's proceed.
image.onload = function () { };
image.src = configCollectorUrl + request;
}

/*
* Send request
*/
function sendRequest(request, delay) {
var now = new Date();

if (!configDoNotTrack) {
getImage(request);
queueImage(request);
SnowPlow.expireDateTime = now.getTime() + delay;
}
}
Expand Down