Skip to content

Commit

Permalink
Merge pull request #2229 from cb1kenobi/timob-8965
Browse files Browse the repository at this point in the history
[TIMOB-8965] [TIMOB-8966] [TIMOB-8948] Analytics bug fixes and parity
  • Loading branch information
nebrius committed May 19, 2012
2 parents 06b9e1d + 7e9f795 commit 6c71eed
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 132 deletions.
14 changes: 8 additions & 6 deletions mobileweb/titanium/Ti.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ define(

var global = window,
cfg = require.config,
deployType = cfg.app.deployType,
deployType = App.deployType,
ver = cfg.ti.version,
is = require.is,
has = require.has,
Expand Down Expand Up @@ -394,9 +394,9 @@ define(
padding: 0
});

if (cfg.app.analytics) {
if (App.analytics) {
// enroll event
if (localStorage.getItem("mobileweb_enrollSent") === null) {
if (localStorage.getItem("ti:enrolled") === null) {
// setup enroll event
analytics.add("ti.enroll", "ti.enroll", {
app_name: App.name,
Expand All @@ -409,7 +409,7 @@ define(
platform: Platform.name,
model: Platform.model
});
localStorage.setItem("mobileweb_enrollSent", true)
localStorage.setItem("ti:enrolled", true)
}

// app start event
Expand All @@ -418,9 +418,11 @@ define(
deploytype: deployType,
os: Platform.osname,
osver: Platform.ostype,
version: cfg.tiVersion,
version: cfg.ti.version,
platform: Platform.name,
model: Platform.model,
un: null,
app_version: cfg.appVersion,
app_version: App.version,
nettype: null
});

Expand Down
277 changes: 151 additions & 126 deletions mobileweb/titanium/Ti/_/analytics.js
Original file line number Diff line number Diff line change
@@ -1,155 +1,180 @@
define(["Ti/_", "Ti/_/dom", "Ti/_/lang", "Ti/App", "Ti/Platform"], function(_, dom, lang, App, Platform) {
define(["Ti/_", "Ti/_/dom", "Ti/_/lang", "Ti/App", "Ti/Platform"],
function(_, dom, lang, App, Platform) {

var global = window,
sessionId = sessionStorage.getItem("ti:sessionId"),
is = require.is,
cfg = require.config,
analyticsEnabled = App.analytics,
analyticsStorageName = "ti:analyticsEvents",
analyticsEventSeq = 0,
analyticsLastSent = null,
analyticsUrl = "https://api.appcelerator.net/p/v2/mobile-web-track",
pending = {};
pending = {},
sendTimer,
sendDelay = 60000,
analytics = {
add: function(type, event, data, isUrgent) {
if (analyticsEnabled) {
// store event
var storage = getStorage();
now = new Date(),
tz = now.getTimezoneOffset(),
atz = Math.abs(tz),
formatZeros = function(v, n){
var d = (v+'').length;
return (d < n ? (new Array(++n - d)).join("0") : "") + v;
};

storage.push({
id: _.uuid(),
type: type,
evt: event,
ts: now.toISOString().replace('Z', (tz < 0 ? '-' : '+') + (atz < 100 ? "00" : (atz < 1000 ? "0" : "")) + atz),
data: data
});

setStorage(storage);
this.send(isUrgent);
}
},

send: function(isUrgent) {
if (analyticsEnabled) {
var rand = Math.floor(Math.random() * 1e6),
now = (new Date()).getTime(),
ids = [],
jsonStrs = [],
sessionId = sessionStorage.getItem("ti:sessionId"),
seqId = JSON.parse(sessionStorage.getItem("ti:analyticsSeqId")),
events = getStorage(),
i = 0,
len = events.length,
evt;

clearTimeout(sendTimer);

if (len && (isUrgent || analyticsLastSent === null || now - analyticsLastSent >= sendDelay)) {
sessionId || (sessionId = _.uuid());
seqId === null && (seqId = 0);

while (i < len) {
evt = events[i++];

ids.push(evt.id);
jsonStrs.push(JSON.stringify({
id: evt.id,
mid: Platform.id,
rdu: null,
type: evt.type,
aguid: App.guid,
event: evt.evt,
seq: seqId++,
ver: "2",
deploytype: App.deployType,
sid: sessionId,
ts: evt.ts,
data: /(Array|Object)/.test(is(evt.data)) ? JSON.stringify(evt.data) : evt.data
}));

if (evt.type === "ti.end") {
seqId = 0;
sessionId = _.uuid();
}
}

sessionStorage.setItem("ti:sessionId", sessionId);
sessionStorage.setItem("ti:analyticsSeqId", seqId);

pending[rand] = ids;
analyticsLastSent = now;

if (require.has("analytics-use-xhr")) {
var xhr = new XmlHttpRequest;
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
onSuccess({ data: eval('(' + xhr.responseText + ')') });
} catch (e) {}
}
};
xhr.open("POST", analyticsUrl, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(lang.urlEncode({ content: jsonStrs }));
} else {
var body = document.body,
iframeName = "analytics" + rand,
iframe = dom.create("iframe", {
id: iframeName,
name: iframeName,
style: {
display: "none"
}
}, body),
form = dom.create("form", {
action: analyticsUrl + "?callback=" + rand + "&output=html",
method: "POST",
style: {
display: "none"
},
target: iframeName
}, body);

dom.create("input", {
name: "content",
type: "hidden",
value: "[" + jsonStrs.join(",") + "]"
}, form);

// need to delay attaching of iframe events so they aren't prematurely called
setTimeout(function() {
function onIframeLoaded() {
setTimeout(function() {
dom.destroy(form);
dom.destroy(iframe);
}, 1);
}
iframe.onload = onIframeLoaded;
iframe.onerror = onIframeLoaded;
form.submit();
}, 25);
}
}

sessionId || sessionStorage.setItem("ti:sessionId", sessionId = _.uuid());
sendTimer = setTimeout(function() {
analytics.send(1);
}, sendDelay);
}
}
};

function getStorage() {
var s = localStorage.getItem(analyticsStorageName);
return s ? JSON.parse(s) : []
var s = localStorage.getItem("ti:analyticsEvents");
return s ? JSON.parse(s) : [];
}

function setStorage(data) {
localStorage.setItem(analyticsStorageName, JSON.stringify(data));
localStorage.setItem("ti:analyticsEvents", JSON.stringify(data));
}

function onSuccess(response) {
if (is(response.data, "Object") && response.data.success) {
var ids = pending[response.data.callback],
keepers = [];
keepers = [],
events = getStorage(),
i = 0,
len = events.length,
evt;

if (ids) {
getStorage().forEach(function(evt) {
while (i < len) {
evt = events[i++];
~ids.indexOf(evt.id) || keepers.push(evt);
});
}
setStorage(keepers);
}
}
}

require.on(global, "message", onSuccess);

return _.analytics = {

add: function(type, event, data, isUrgent) {
if (analyticsEnabled) {
// store event
var storage = getStorage();
now = new Date(),
tz = now.getTimezoneOffset(),
atz = Math.abs(tz),
formatZeros = function(v, n){
var d = (v+'').length;
return (d < n ? (new Array(++n - d)).join("0") : "") + v;
};

storage.push({
id: _.uuid(),
type: type,
evt: event,
ts: now.toISOString().replace('Z', (tz < 0 ? '-' : '+') + (atz < 100 ? "00" : (atz < 1000 ? "0" : "")) + atz),
data: data
});

setStorage(storage);
this.send(isUrgent);
}
},

send: function(isUrgent) {
if (analyticsEnabled) {
var rand = Math.floor(Math.random() * 1e6),
now = (new Date()).getTime(),
ids = [],
jsonStrs = [];

if (!isUrgent && analyticsLastSent !== null && now - analyticsLastSent < 60000 /* 1 minute */) {
return;
}

analyticsLastSent = now;

getStorage().forEach(function(evt) {
ids.push(evt.id);
jsonStrs.push(JSON.stringify({
id: evt.id,
mid: Platform.id,
rdu: null,
type: evt.type,
aguid: App.guid,
event: evt.evt,
seq: analyticsEventSeq++,
ver: "2",
deploytype: cfg.app.deployType,
sid: sessionId,
ts: evt.ts,
data: /(Array|Object)/.test(is(evt.data)) ? JSON.stringify(evt.data) : evt.data
}));
});

pending[rand] = ids;

if (require.has("analytics-use-xhr")) {
var xhr = new XmlHttpRequest;
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
onSuccess({ data: eval('(' + xhr.responseText + ')') });
} catch (e) {}
}
};
xhr.open("POST", analyticsUrl, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(lang.urlEncode({ content: jsonStrs }));
} else {
var body = document.body,
iframeName = "analytics" + rand,
iframe = dom.create("iframe", {
id: iframeName,
name: iframeName,
style: {
display: "none"
}
}, body),
form = dom.create("form", {
action: analyticsUrl + "?callback=" + rand + "&output=html",
method: "POST",
style: {
display: "none"
},
target: iframeName
}, body);

dom.create("input", {
name: "content",
type: "hidden",
value: "[" + jsonStrs.join(",") + "]"
}, form);

// need to delay attaching of iframe events so they aren't prematurely called
setTimeout(function() {
function onIframeLoaded() {
setTimeout(function() {
dom.destroy(form);
dom.destroy(iframe);
}, 1);
}
iframe.onload = onIframeLoaded;
iframe.onerror = onIframeLoaded;
form.submit();
}, 25);
}
}
}

};
return analytics;

});

0 comments on commit 6c71eed

Please sign in to comment.