| 1 | (function (global) { |
| 2 | var Module; |
| 3 | |
| 4 | // Load up dependencies |
| 5 | if (typeof require === 'function') { |
| 6 | var Ne = require('neon'); |
| 7 | Module = Ne.Module; |
| 8 | } else { |
| 9 | Module = global.Module; |
| 10 | } |
| 11 | |
| 12 | var Cobalt = {}; |
| 13 | Module(Cobalt, 'Formatter')({}); |
| 14 | |
| 15 | Cobalt.Formatter.EventTracker = Module(Cobalt.Formatter, 'EventTracker')({ |
| 16 | |
| 17 | // Main formatter entry point, validate type and send to proper format |
| 18 | // method |
| 19 | format : function (logObject) { |
| 20 | switch(this._validateFormat(logObject)){ |
| 21 | case 'error': |
| 22 | return this._formatError(logObject); |
| 23 | break; |
| 24 | case 'event': |
| 25 | logObject._type = 'event'; |
| 26 | return this._formatEvent(logObject); |
| 27 | break; |
| 28 | } |
| 29 | return undefined; |
| 30 | }, |
| 31 | |
| 32 | // Format error |
| 33 | _formatError : function (logObject) { |
| 34 | var errorObject; |
| 35 | |
| 36 | errorObject = logObject.error; |
| 37 | errorObject._type = 'error'; |
| 38 | |
| 39 | if (typeof Client !== 'undefined') { |
| 40 | errorObject.site_id = Client.pageInfo.site.id; |
| 41 | }else if (global.data && global.data.site && global.data.site.id) { |
| 42 | errorObject.site_id = global.data.site.id; |
| 43 | } |
| 44 | errorObject.scoped_class_name = errorObject.meta.scopedClassName; |
| 45 | errorObject.user_agent = global.navigator.userAgent; |
| 46 | |
| 47 | return errorObject; |
| 48 | }, |
| 49 | |
| 50 | // Format the event |
| 51 | _formatEvent : function (logObject) { |
| 52 | var eventToSend; |
| 53 | |
| 54 | eventToSend = this._createStructure(logObject); |
| 55 | |
| 56 | return eventToSend; |
| 57 | }, |
| 58 | |
| 59 | // Check for the fingerprint of an event or an error |
| 60 | _validateFormat : function (logObject) { |
| 61 | if (typeof logObject === 'object'){ |
| 62 | // Check for error object (must have meta) |
| 63 | if (logObject.hasOwnProperty('error')) { |
| 64 | if (logObject.error.hasOwnProperty('meta')) { |
| 65 | return 'error'; |
| 66 | } |
| 67 | // Check for event object (must have type) |
| 68 | } else if (logObject.hasOwnProperty('event')) { |
| 69 | if (logObject.event.hasOwnProperty('type')) { |
| 70 | return 'event'; |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | return undefined; |
| 75 | }, |
| 76 | |
| 77 | // This was ported as-is, but It's weird that we're doing lithium logic in |
| 78 | // here. TODO: Please move this elsewhere. - ben |
| 79 | _pushToLithium : function (object) { |
| 80 | var lithiumEvent; |
| 81 | |
| 82 | if (typeof Li !== 'undefined') { |
| 83 | if (Li.stack) { |
| 84 | lithiumEvent = { |
| 85 | type : object.event.type, |
| 86 | instanceName : (object.event.data) ? (object.event.data.name || object.event.data.id || '---') : '---', |
| 87 | time : global.Cobalt.now() |
| 88 | }; |
| 89 | |
| 90 | Li.events.push(lithiumEvent); |
| 91 | Li.stack.push(lithiumEvent); |
| 92 | |
| 93 | // Another note: There was another push to Li.stack that checked if it |
| 94 | // was typeof === array. Which will never happen since array is typeof |
| 95 | // Object. But I could be wrong. So... yeah. That. |
| 96 | |
| 97 | if (Li.events.length > 20) { |
| 98 | Li.stack.shift(); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | }, |
| 103 | |
| 104 | // Create the main structure, also push to lithium |
| 105 | _createStructure : function (logObject) { |
| 106 | var event = {}; |
| 107 | |
| 108 | this._pushToLithium(logObject); |
| 109 | |
| 110 | event.site_id = global.Client ? Client.pageInfo.site.id : 'client not found'; |
| 111 | event.event_type = logObject.event.type; |
| 112 | |
| 113 | event.data = logObject.event.data || {}; |
| 114 | event.data = this._process(event.data); |
| 115 | event.data.user_time_stamp = global.Cobalt.now(); |
| 116 | |
| 117 | event = this._addSiteData(event); |
| 118 | event = this._addTrackingData(event); |
| 119 | |
| 120 | event._type = 'event'; |
| 121 | |
| 122 | return event; |
| 123 | }, |
| 124 | |
| 125 | // Add required data from siteInfo |
| 126 | _addSiteData : function (event) { |
| 127 | if (typeof siteInfo !== 'undefined') { |
| 128 | event.data.trial_period_days_left = siteInfo.trialPeriodDaysLeft; |
| 129 | event.data.billing_status = siteInfo.billingStatus; |
| 130 | event.data.is_admin_on_trial = siteInfo.isAdminOnTrial; |
| 131 | event.data.is_new_site = siteInfo.isNewSite; |
| 132 | event.data.is_for_play = siteInfo.forPlay; |
| 133 | event.data.page_path = siteInfo.currentPagePath; |
| 134 | } |
| 135 | |
| 136 | return event; |
| 137 | }, |
| 138 | |
| 139 | // Add required tracking variables for ad campaigns and such |
| 140 | _addTrackingData : function (event) { |
| 141 | if (typeof siteInfo !== 'undefined' && siteInfo.trackingVariables) { |
| 142 | event.data.initial_referring_domain = siteInfo.trackingVariables.initial_referring_domain; |
| 143 | event.data.referrer = siteInfo.trackingVariables.referrer; |
| 144 | event.data.search_keyword = siteInfo.trackingVariables.search_keyword; |
| 145 | event.data.utm_campaign = siteInfo.trackingVariables.utm_campaign; |
| 146 | event.data.utm_content = siteInfo.trackingVariables.utm_content; |
| 147 | event.data.utm_medium = siteInfo.trackingVariables.utm_medium; |
| 148 | event.data.utm_source = siteInfo.trackingVariables.utm_source; |
| 149 | event.data.utm_term = siteInfo.trackingVariables.utm_term; |
| 150 | } |
| 151 | |
| 152 | return event; |
| 153 | }, |
| 154 | |
| 155 | // Send data through processors to extract valuable metadata |
| 156 | _process : function (data) { |
| 157 | if( typeof data !== 'undefined' && typeof data.constructor !== 'undefined' && typeof data.constructor.className !== 'undefined' ){ |
| 158 | switch( data.constructor.className ){ |
| 159 | case 'App': |
| 160 | return { meta: this._processApp(data) }; |
| 161 | |
| 162 | case 'Entry': |
| 163 | return { meta: this._processEntry(data) }; |
| 164 | |
| 165 | case 'Dot': |
| 166 | return { meta: this._processDot(data) }; |
| 167 | |
| 168 | case 'SiteSkin': |
| 169 | return { meta: this._processSiteSkin(data) }; |
| 170 | |
| 171 | case 'RepositorySkin': |
| 172 | return { meta: this._processRepositorySkin(data) }; |
| 173 | |
| 174 | default : |
| 175 | //do nothing and create an snapshot for the object |
| 176 | var snapshot = {}; |
| 177 | |
| 178 | $.each(data, function(i, el){ |
| 179 | if(typeof el === 'string' || typeof el === 'number' || typeof el === 'boolean'){ |
| 180 | snapshot[i] = el; |
| 181 | } |
| 182 | }); |
| 183 | |
| 184 | return { meta: { status: 'No processor for '+data.constructor.className, snapshot: snapshot } }; |
| 185 | } |
| 186 | |
| 187 | }else{ |
| 188 | // No process for you |
| 189 | return { meta: data }; |
| 190 | } |
| 191 | }, |
| 192 | |
| 193 | _processApp : function (data) { |
| 194 | var eventData = { |
| 195 | displayName : data.record.displayName, |
| 196 | repositoryAppId : data.record.repositoryApp().id, |
| 197 | repositoryAppName : data.record.repositoryApp().name |
| 198 | }; |
| 199 | |
| 200 | return { app: eventData }; |
| 201 | }, |
| 202 | |
| 203 | _processEntry : function (data) { |
| 204 | //get app data |
| 205 | var app = this.processApp( Client.page['app_' + data.appId] ); |
| 206 | |
| 207 | var entry = { |
| 208 | id : data.id, |
| 209 | fieldValues : {} |
| 210 | }; |
| 211 | |
| 212 | //parse and save fieldvalues |
| 213 | $.each(data.fieldValues, function(i, field){ |
| 214 | entry.fieldValues[field.fieldName] = field.value; |
| 215 | }); |
| 216 | |
| 217 | return {app: app, entry : entry}; |
| 218 | }, |
| 219 | |
| 220 | _processDot : function (data) { |
| 221 | var target = { type: data.ruleTree.type }; |
| 222 | |
| 223 | switch (target.type){ |
| 224 | case 'app' : |
| 225 | target.app = this.processApp( Client.page['app_'+data.ruleTree.id.replace('app_style_','')] ).app; |
| 226 | break; |
| 227 | } |
| 228 | |
| 229 | var dot = { |
| 230 | type: data.type, |
| 231 | name: data.name |
| 232 | }; |
| 233 | |
| 234 | return {target: target, dot : dot}; |
| 235 | }, |
| 236 | |
| 237 | _processSiteSkin : function (data) { |
| 238 | return { siteSkin : { |
| 239 | skinName: skinData.name, |
| 240 | skinId: skinData.id |
| 241 | } |
| 242 | }; |
| 243 | }, |
| 244 | |
| 245 | _processRepositorySkin : function (data) { |
| 246 | var skin = { |
| 247 | id : data.id, |
| 248 | name : data.name, |
| 249 | userName : data.userName, |
| 250 | acquireMode : data.acquireMode, |
| 251 | amountInCents : data.amountInCents, |
| 252 | featured : data.featured, |
| 253 | installCount : data.installCount, |
| 254 | popular : data.popular |
| 255 | }; |
| 256 | |
| 257 | return { repositorySkin: skin }; |
| 258 | } |
| 259 | }); |
| 260 | |
| 261 | if (Cobalt.Formatter.EventTracker.__objectSpy) { |
| 262 | Cobalt.Formatter.EventTracker.__objectSpy.destroy(); |
| 263 | } |
| 264 | |
| 265 | if (typeof require === 'function') { |
| 266 | global.EventTracker = Cobalt.Formatter.EventTracker; |
| 267 | } else { |
| 268 | global.Cobalt.Formatter.EventTracker = Cobalt.Formatter.EventTracker; |
| 269 | } |
| 270 | }(typeof window !== 'undefined' ? window : (typeof exports !== 'undefined' ? exports : self))); |