diff --git a/kwc-tracking.html b/kwc-tracking.html
index 9d22244..b639208 100644
--- a/kwc-tracking.html
+++ b/kwc-tracking.html
@@ -48,6 +48,14 @@
* @type {String}
*/
path,
+ /**
+ * If the session hasn't started, then we won't have all the
+ * data available for the event. We can cache them in the
+ * `preInitEvents` queue, and then process once the session
+ * has started.
+ * @type {Array}
+ */
+ preInitEvents = [],
/**
* The user's device mode (Kano 2 app only)
* @type {Boolean}
@@ -175,12 +183,33 @@
});
}
/**
- * Trigger the `_clearQueueDispatch` and remove the listener
- * properly when unloading the page.
+ * Send what's left of the queue using a synchronous XMLHttpRequest
+ * to block transitions until the data has been sent.
+ * TODO: A blocking XMLHttpRequest could be very poor for user
+ * experience and should be carefully evaluated
+ * `navigator.sendBeacon` would be a good alternative, but sending
+ * JSON is currently blocked in Chrome due to CORS considerations
+ * (see here: https://bugs.chromium.org/p/chromium/issues/detail?id=490015).
+ * `sendBeacon` also does not allow custom headers such as
+ * Authorization, so we could not send through tokens to identify
+ * the user.
*/
function _handleUnload () {
- _clearQueueDispatch();
window.removeEventListener('unload', _handleUnload);
+ try {
+ let client = new XMLHttpRequest(),
+ url = `${config.API_URL}/track/${schema}`,
+ body = JSON.stringify({events: queue});
+ client.open('POST', url, false);
+ client.setRequestHeader('Content-type', 'application/json');
+ if (token) {
+ client.setRequestHeader('Authorization', token);
+ }
+ client.send(body);
+ } catch (e) {
+ _log(e);
+ }
+ queue = [];
}
/**
* Ensure that all the relevent information is set (including the
@@ -207,11 +236,11 @@
_getLocation().then(response => {
location = response;
localStorage.setItem(LOCATION_KEY, response);
- _startSession();
+ _startSession(preInitEvents);
});
} else {
location = storedLocation;
- _startSession();
+ _startSession(preInitEvents);
}
}
/**
@@ -221,7 +250,7 @@
function _queueEvent (payload) {
let sessionExpired = _sessionExpired(lastUpdate);
if (sessionExpired && sessionStarted) {
- return _restartSession(payload);
+ return _restartSession([payload]);
}
let body = {
app_id: config.APP_ID,
@@ -255,14 +284,14 @@
* @param {Object} restartEvent An event to add to the queue after
* restarting the session
*/
- function _restartSession (restartEvent) {
+ function _restartSession (restartEvents) {
let idString = window.navigator.userAgent + Date.now().toString(),
hashedId = md5(idString);
sessionId = hashedId;
sessionStorage.setItem(SESSION_KEY, hashedId);
sessionStarted = false;
previousSession = false;
- _startSession(restartEvent);
+ _startSession(restartEvents);
}
/** Set an interval to dispatch the event queue */
function _scheduleQueueDispatch () {
@@ -357,7 +386,7 @@
* restarted it (if provided) and schedule the queue processing
* @param {Object} startEvent
*/
- function _startSession (startEvent) {
+ function _startSession (startEvents) {
if (!previousSession) {
_queueEvent({
name: 'started_session',
@@ -365,8 +394,10 @@
user_location: location
}
});
- if (startEvent) {
- _queueEvent(startEvent);
+ if (startEvents && startEvents.length) {
+ startEvents.forEach(startEvent => {
+ _queueEvent(startEvent);
+ });
}
}
sessionStarted = true;
@@ -403,6 +434,15 @@
if (e.detail.token) {
payload.token = e.detail.token;
}
+ /**
+ * If the session hasn't started, then we won't have all the
+ * data available for the event. We can cache it in the
+ * `preInitEvents` queue, and then process once the session
+ * has started.
+ */
+ if (!sessionStarted) {
+ return preInitEvents.push(payload);
+ }
_queueEvent(payload);
}
/**
@@ -427,6 +467,15 @@
previous_page_path: previous
}
}
+ /**
+ * If the session hasn't started, then we won't have all the
+ * data available for the event. We can cache it in the
+ * `preInitEvents` queue, and then process once the session
+ * has started.
+ */
+ if (!sessionStarted) {
+ return preInitEvents.push(payload);
+ }
_queueEvent(payload);
}
/**
@@ -502,7 +551,7 @@
_clearQueueDispatch();
},
_handleUnload () {
- _clearQueueDispatch();
+ _handleUnload();
window.removeEventListener('beforeunload', this._handleUnload);
}
};