Skip to content

Instantly share code, notes, and snippets.

@daleyjem
Last active January 23, 2024 17:30
Show Gist options
  • Save daleyjem/465ce9e810231397f8ed to your computer and use it in GitHub Desktop.
Save daleyjem/465ce9e810231397f8ed to your computer and use it in GitHub Desktop.
A Veeva ClickStream helper class for page and event tracking. *Requires veeva-library.js
/**
* Veeva ClickStream tracking class.
*
* Author: Jeremy Daley
* Liscence: MIT
*/
ClickStream.prototype.virtualInterval = -1;
ClickStream.prototype.calls = []; // Queued calls
ClickStream.prototype.debug = false;
function ClickStream(debug){
if (debug !== undefined)
this.debug = debug;
}
/**
* This is an event call, with a zero duration. It's used for tracking
* things like clicks.
*
* @param {string} id Track Element Id
* @param {string} type Track Element Type
* @param {string} description Track Element Description
*/
ClickStream.prototype.trackEvent = function(id, type, description){
var self = this;
var obj = {
'Track_Element_Id_vod__c': id,
'Track_Element_Type_vod__c': type,
'Track_Element_Description_vod__c': description,
'Usage_Start_Time_vod__c': new Date(),
'Usage_Duration_vod__c': 1
};
if (self.debug)
console.log('trackEvent:', obj);
self.queue('create', 'Call_Clickstream_vod__c', null, obj, self.noop);
};
/**
* This is a page tracking call, that should be started at the load of a page. It uses a
* timer to continually update the duration on the page
*
* @param {string} id Track Element Id
* @param {string} type Track Element Type
* @param {string} description Track Element Description
*/
ClickStream.prototype.trackPage = function() {
var self = this;
var obj = {
'Track_Element_Type_vod__c': 'Page View',
'Usage_Start_Time_vod__c': new Date(),
'Usage_Duration_vod__c': 1
};
if (self.debug)
console.log('trackPage:', obj);
self.queue('create', 'Call_Clickstream_vod__c', null, obj, function(data){
var duration = 1;
// Every second, we need to update the Duration field for this record
window.setInterval(function(){
duration++;
obj['Usage_Duration_vod__c'] = duration;
self.queue('update', 'Call_Clickstream_vod__c', data.Call_Clickstream_vod__c.ID, obj, self.noop);
}, 1000);
});
};
/**
* Track a section within a key message, like for tabs
* @param {string} pageName The name of the virtual section
*/
ClickStream.prototype.trackVirtualPage = function(id, description){
// First clear the tracking of a previous virtual pageview
window.clearInterval( this.virtualInterval );
var self = this;
var obj = {
'Track_Element_Id_vod__c': id,
'Track_Element_Description_vod__c': description,
'Track_Element_Type_vod__c': 'In-Page View',
'Usage_Start_Time_vod__c': new Date(),
'Usage_Duration_vod__c': 1
};
if (self.debug)
console.log('trackVirtualPage:', obj);
self.queue('create', 'Call_Clickstream_vod__c', null, obj, function(data){
var duration = 1;
// Every second, we need to update the Duration field for this record
self.virtualInterval = window.setInterval(function(){
duration++;
obj['Usage_Duration_vod__c'] = duration;
self.queue('update', 'Call_Clickstream_vod__c', data.Call_Clickstream_vod__c.ID, obj, self.noop);
}, 1000);
});
};
/**
* Veeva can't take more than one action at a time, so we have to queue up each call
* @param {string} action Something like 'Call_Clickstream_vod__c'
* @param {string} type 'update' or 'create'
* @param {object} obj Tracking fields/values to send to Veeva
* @param {Function} callback
*/
ClickStream.prototype.queue = function(action, type, id, obj, callback){
var self = this;
var call = {
action: action,
type: type,
id: id,
obj: obj,
callback: callback
};
this.calls.push( call );
// If this is the first item in the queue, go ahead and call it right away
if (this.calls.length == 1)
makeCall( call );
function makeCall(call){
console.log(call);
switch( call.action ) {
case 'update':
com.veeva.clm.updateRecord(call.type, call.id, call.obj, queueCallback);
break;
case 'create':
com.veeva.clm.createRecord(call.type, call.obj, queueCallback);
break;
}
// If we're running in debug mode, we wanna make act like the records were successfully created/updated
if (self.debug === true)
queueCallback( {Call_Clickstream_vod__c: {ID: new Date().getTime()}} );
}
function queueCallback(data, _action){
// Call the original callback function
self.calls[0].callback( data );
// Remove the current item in the queue
self.calls.shift();
// If there's anything left in the queue, let's call it.
if (self.calls.length > 0)
makeCall( self.calls[0] );
}
}
/**
* A callback "ground".
*/
ClickStream.prototype.noop = function(data){
// Do nothing
};
@jvkiii
Copy link

jvkiii commented Mar 1, 2017

Looks great, very helpful. Have you had the situation where you need to use trackEvent on a button that clicks to another keymessage slide (com.veeva.clm.gotoSlide).? The reason I ask is that the trackEvent method doesn't currently have a callback parameter, and I'm not sure that the record would get successfully tracked before veeva reloads the html to the destination slide. In your experience, does it successfully track in this case or would you need a callback to then implement the gotoSlide method?

@GeertDev
Copy link

GeertDev commented May 2, 2017

Is it possible to add clickstreamtracking to a deep html5 using a js ? We've created long presentations (100 pages) and automatically generate deep or wide html5 files that can be used in Veeva or Pitcher and would like to add tracking to them in a efficient way...

@workjacinjiyan
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment