
'Ontogeny recapitulates phylogeny'
is a concept that I learned in design school many years ago. The theory, by Ernst Haeckel, basically says that if various life forms share common development characteristics or stages, they are related. The design is similar, even if the evolution from a single cell ends up with a different outcome.
In design, it is important to look to nature for inspiration. Design is a process refinement towards something that is beautiful or meaningful. What is evolution but millions of years of refinement?
My first leg of this journey will be to find commonalities in the behavior of web users, even if they end up in different places. This will be difficult.
In order to do this, we need to find a way to record and compare user behavior across different websites. This can be done in a variety of ways. For our purposes, since we want to compare across a wide variety of websites, we will choose an analytics implementation with custom dimensions.
I found this wonderful post by Simo Ahavo called 13 Useful Custom Dimensions for Google Analytics. In it, he shows how to map client id, unique session ids, and hit timestamps to custom dimensions in Google Analytics (there are many other goodies in here). I have consolidated some of the code into a single function that can be used in Tag Manager as a custom JavaScript variable.
Variable Name: Set Custom Dimensions
function() {
// Set your custom dimension indexes here
var clientid_idx = 2
var timestamp_idx = 3
var sessionid_idx = 4
// Tracker model is included as parameter here
return function(tracker) {
// Logging to see what else is available
console.log('GTM Tracker Info')
console.log(tracker)
// Get local time as ISO string with offset at the end
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? '+' : '-';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
var ts = now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ 'T' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ '.' + pad(now.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
// Get unique random string based on time
var tn = now.getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function'){
tn += performance.now(); //use high-precision timer if available
}
var sid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (tn + Math.random() * 16) % 16 | 0;
tn = Math.floor(tn / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
// Sets the values to the tracker object.
tracker.set('dimension'+clientid_idx, tracker.get('clientId'));
tracker.set('dimension'+timestamp_idx, ts);
tracker.set('dimension'+sessionid_idx, sid);
}
}
Map the variables to your custom dimensions in Google Analytics
On your Google Analytics variable, set a field: customTask and map it to your custom function: {{Set Custom Dimensions}}
I am only giving a very brief overview of the steps here on purpose. I highly recommend spending some time on Simo’s blog to read about other data available, more implementation options, and to understand why and when to use custom dimension scopes.
After you have your dimensions set up, you can use Google Analytics debugger to verify that the data is being sent correctly.
Once this has been active for some time, you can move to your favorite tool for querying the Google Analytics API
Finally, we can begin viewing individual session time series.
For now, I will spend some time reviewing this data along with several papers I have found on web visit clustering. My initial inclination is that I need to convert the visits into normalized vectors with frequency and some type of label for either intent or outcome. We will cover this in the next post.
Thanks for reading.