+(function (global) {
+ var Module;
+
+ // Load up dependencies
+ if (typeof require === 'function') {
+ var Ne = require('neon');
+ Module = Ne.Module;
+ } else {
+ Module = global.Module;
+ }
+
+ var Cobalt = {};
+ Module(Cobalt, 'Formatter')({});
+
+ Cobalt.Formatter.EventTracker = Module(Cobalt.Formatter, 'EventTracker')({
+
+ // Main formatter entry point, validate type and send to proper format
+ // method
+ format : function (logObject) {
+ switch(this._validateFormat(logObject)){
+ case 'error':
+ return this._formatError(logObject);
+ break;
+ case 'event':
+ logObject._type = 'event';
+ return this._formatEvent(logObject);
+ break;
+ }
+ return undefined;
+ },
+
+ // Format error
+ _formatError : function (logObject) {
+ var errorObject;
+
+ errorObject = logObject.error;
+ errorObject._type = 'error';
+
+ if (typeof Client !== 'undefined') {
+ errorObject.site_id = Client.pageInfo.site.id;
+ }else if (global.data && global.data.site && global.data.site.id) {
+ errorObject.site_id = global.data.site.id;
+ }
+ errorObject.scoped_class_name = errorObject.meta.scopedClassName;
+ errorObject.user_agent = global.navigator.userAgent;
+
+ return errorObject;
+ },
+
+ // Format the event
+ _formatEvent : function (logObject) {
+ var eventToSend;
+
+ eventToSend = this._createStructure(logObject);
+
+ return eventToSend;
+ },
+
+ // Check for the fingerprint of an event or an error
+ _validateFormat : function (logObject) {
+ if (typeof logObject === 'object'){
+ // Check for error object (must have meta)
+ if (logObject.hasOwnProperty('error')) {
+ if (logObject.error.hasOwnProperty('meta')) {
+ return 'error';
+ }
+ // Check for event object (must have type)
+ } else if (logObject.hasOwnProperty('event')) {
+ if (logObject.event.hasOwnProperty('type')) {
+ return 'event';
+ }
+ }
+ }
+ return undefined;
+ },
+
+ // This was ported as-is, but It's weird that we're doing lithium logic in
+ // here. TODO: Please move this elsewhere. - ben
+ _pushToLithium : function (object) {
+ var lithiumEvent;
+
+ if (typeof Li !== 'undefined') {
+ if (Li.stack) {
+ lithiumEvent = {
+ type : object.event.type,
+ instanceName : (object.event.data) ? (object.event.data.name || object.event.data.id || '---') : '---',
+ time : global.Cobalt.now()
+ };
+
+ Li.events.push(lithiumEvent);
+ Li.stack.push(lithiumEvent);
+
+ // Another note: There was another push to Li.stack that checked if it
+ // was typeof === array. Which will never happen since array is typeof
+ // Object. But I could be wrong. So... yeah. That.
+
+ if (Li.events.length > 20) {
+ Li.stack.shift();
+ }
+ }
+ }
+ },
+
+ // Create the main structure, also push to lithium
+ _createStructure : function (logObject) {
+ var event = {};
+
+ this._pushToLithium(logObject);
+
+ event.site_id = global.Client ? Client.pageInfo.site.id : 'client not found';
+ event.event_type = logObject.event.type;
+
+ event.data = logObject.event.data || {};
+ event.data = this._process(event.data);
+ event.data.user_time_stamp = global.Cobalt.now();
+
+ event = this._addSiteData(event);
+ event = this._addTrackingData(event);
+
+ event._type = 'event';
+
+ return event;
+ },
+
+ // Add required data from siteInfo
+ _addSiteData : function (event) {
+ if (typeof siteInfo !== 'undefined') {
+ event.data.trial_period_days_left = siteInfo.trialPeriodDaysLeft;
+ event.data.billing_status = siteInfo.billingStatus;
+ event.data.is_admin_on_trial = siteInfo.isAdminOnTrial;
+ event.data.is_new_site = siteInfo.isNewSite;
+ event.data.is_for_play = siteInfo.forPlay;
+ event.data.page_path = siteInfo.currentPagePath;
+ }
+
+ return event;
+ },
+
+ // Add required tracking variables for ad campaigns and such
+ _addTrackingData : function (event) {
+ if (typeof siteInfo !== 'undefined' && siteInfo.trackingVariables) {
+ event.data.initial_referring_domain = siteInfo.trackingVariables.initial_referring_domain;
+ event.data.referrer = siteInfo.trackingVariables.referrer;
+ event.data.search_keyword = siteInfo.trackingVariables.search_keyword;
+ event.data.utm_campaign = siteInfo.trackingVariables.utm_campaign;
+ event.data.utm_content = siteInfo.trackingVariables.utm_content;
+ event.data.utm_medium = siteInfo.trackingVariables.utm_medium;
+ event.data.utm_source = siteInfo.trackingVariables.utm_source;
+ event.data.utm_term = siteInfo.trackingVariables.utm_term;
+ }
+
+ return event;
+ },
+
+ // Send data through processors to extract valuable metadata
+ _process : function (data) {
+ if( typeof data !== 'undefined' && typeof data.constructor !== 'undefined' && typeof data.constructor.className !== 'undefined' ){
+ switch( data.constructor.className ){
+ case 'App':
+ return { meta: this._processApp(data) };
+
+ case 'Entry':
+ return { meta: this._processEntry(data) };
+
+ case 'Dot':
+ return { meta: this._processDot(data) };
+
+ case 'SiteSkin':
+ return { meta: this._processSiteSkin(data) };
+
+ case 'RepositorySkin':
+ return { meta: this._processRepositorySkin(data) };
+
+ default :
+ //do nothing and create an snapshot for the object
+ var snapshot = {};
+
+ $.each(data, function(i, el){
+ if(typeof el === 'string' || typeof el === 'number' || typeof el === 'boolean'){
+ snapshot[i] = el;
+ }
+ });
+
+ return { meta: { status: 'No processor for '+data.constructor.className, snapshot: snapshot } };
+ }
+
+ }else{
+ // No process for you
+ return { meta: data };
+ }
+ },
+
+ _processApp : function (data) {
+ var eventData = {
+ displayName : data.record.displayName,
+ repositoryAppId : data.record.repositoryApp().id,
+ repositoryAppName : data.record.repositoryApp().name
+ };
+
+ return { app: eventData };
+ },
+
+ _processEntry : function (data) {
+ //get app data
+ var app = this.processApp( Client.page['app_' + data.appId] );
+
+ var entry = {
+ id : data.id,
+ fieldValues : {}
+ };
+
+ //parse and save fieldvalues
+ $.each(data.fieldValues, function(i, field){
+ entry.fieldValues[field.fieldName] = field.value;
+ });
+
+ return {app: app, entry : entry};
+ },
+
+ _processDot : function (data) {
+ var target = { type: data.ruleTree.type };
+
+ switch (target.type){
+ case 'app' :
+ target.app = this.processApp( Client.page['app_'+data.ruleTree.id.replace('app_style_','')] ).app;
+ break;
+ }
+
+ var dot = {
+ type: data.type,
+ name: data.name
+ };
+
+ return {target: target, dot : dot};
+ },
+
+ _processSiteSkin : function (data) {
+ return { siteSkin : {
+ skinName: skinData.name,
+ skinId: skinData.id
+ }
+ };
+ },
+
+ _processRepositorySkin : function (data) {
+ var skin = {
+ id : data.id,
+ name : data.name,
+ userName : data.userName,
+ acquireMode : data.acquireMode,
+ amountInCents : data.amountInCents,
+ featured : data.featured,
+ installCount : data.installCount,
+ popular : data.popular
+ };
+
+ return { repositorySkin: skin };
+ }
+ });
+
+ if (Cobalt.Formatter.EventTracker.__objectSpy) {
+ Cobalt.Formatter.EventTracker.__objectSpy.destroy();
+ }
+
+ if (typeof require === 'function') {
+ global.EventTracker = Cobalt.Formatter.EventTracker;
+ } else {
+ global.Cobalt.Formatter.EventTracker = Cobalt.Formatter.EventTracker;
+ }
+}(typeof window !== 'undefined' ? window : (typeof exports !== 'undefined' ? exports : self)));