/** * Common utility functions. */ (function(context,$) { "use strict"; context.JK = context.JK || {}; var rest = context.JK.Rest(); var logger = context.JK.logger; // types var registrationTypes = { native : "Native", facebook : "Facebook" }; var sessionCreationTypes = { create : "Create", join : "Join" }; var sessionQualityTypes = { good : "Good", poor : "Poor" }; var invitationTypes = { email : "Email", facebook : "Facebook", google : "Google" }; var friendConnectTypes = { request : "Request", accept : "Accept" }; var recordingActions = { make : "Make", share : "Share" }; var recordingShareTypes = { facebook : "Facebook", syndicationWidget : "SyndWidget", syndicationUrl: "SyndURL" }; var recordingPlayActions = { website : "Website", client : "Client", facebook : "Facebook", syndicationWidget : "SyndWidget", syndicationUrl: "SyndURL" }; var sessionPlayActions = { website : "Website", client : "Client", facebook : "Facebook", syndicationWidget : "SyndWidget", syndicationUrl: "SyndURL" }; var userLabels = { registeredUser : "RegisteredUser", visitor: "Visitor" }; var bandActions = { create : "Create", join : "Join", session : "Session", recording : "Recording" }; var jkSocialTargets = { musician : 'Musician', band : 'Band', fan : 'Fan', recording : 'Recording', session : 'Session', facebook: 'facebook', twitter: 'twitter', google: 'google', }; var audioTestFailReasons = { latency : 'Latency', ioVariance : 'ioVariance', ioTarget : 'ioTarget' } var audioTestDataReasons = { pass : 'Pass', latencyFail : 'LatencyFail', ioVarianceFail : 'ioVarianceFail', ioTargetFail : 'ioTargetFail' } var jamClassReasons = { testDrive: 'TestDrive' } var networkTestFailReasons = { stun : 'STUN', bandwidth : 'Bandwidth', packetRate : 'PacketRate', jitter : 'Jitter', jamerror : 'ServiceError', noNetwork : 'NoNetwork' } var categories = { register : "Register", download : "DownloadClient", audioTest : "AudioTest", audioTestData : 'AudioTestData', trackConfig : "AudioTrackConfig", networkTest : "NetworkTest", sessionCount : "SessionCount", sessionMusicians : "SessionMusicians", sessionQuality : "SessionQuality", invite : "Invite", findSession : "FindSession", friendConnect : "Connect", recording : "Recording", recordingPlay : "RecordingPlay", sessionPlay : "SessionPlay", band : "Band", jkLike : 'jkLike', jkFollow : 'jkFollow', jkFavorite : 'jkFavorite', jkComment : 'jkComment', fileDownload: "DownloadFile", jamclass: 'JamClass' }; // JamTrack categories and actions: var jamTrackAvailabilityTypes = { worldwide: 'JamTrackGlobal', usa: 'JamTrackUSA' } var jamTrackActions = { isPublic: 'PublicPerformance', isPrivate: 'PrivateUse' } var jamTrackSessionLabels = { nonSession: 'NonSession', inSession: 'InSession' } var fileDownloads = { jamtrack_csv: 'JamTrackCSV', jamtrack_pdf: 'JamTrackPDF' } function translatePlatformForGA(platform) { assertOneOf(platform, context.JK.OS); if(platform == context.JK.OS.WIN32) { return "Windows"; } if(platform == context.JK.OS.OSX) { return "Mac"; } if(platform == context.JK.OS.UNIX) { return "Unix"; } } function assertBoolean(value) { if(typeof value != 'boolean') { throw "value is not a boolean: " + JSON.stringify(value); } } function assertNumber(value) { if(typeof value != 'number') { throw "value is not a number: " + JSON.stringify(value); } } function assertOneOf(enumValue, enums){ var found = false; for (var key in enums) { if (enumValue == enums[key]) { found = true; break; } } if(!found) { throw "unable to find enum: " + enumValue + " in: " + JSON.stringify(enums); } } function trackFileDownload(type) { assertOneOf(type, fileDownloads) context.ga('send', 'event', categories.fileDownload, type) } function trackRegister(asMusician, registrationType) { assertBoolean(asMusician); assertOneOf(registrationType, registrationTypes); var action = asMusician ? "Musician" : "Fan"; context.ga('send', 'event', categories.register, action, registrationType); } function trackTestDrivePurchase(count) { context.ga('send', 'event', categories.jamclass, jamClassReasons.testDrive, count); } function trackDownload(platform) { var normalizedPlatform = translatePlatformForGA(platform); context.ga('send', 'event', categories.download, normalizedPlatform); } function trackFTUECompletion(state, platform) { var normalizedPlatform = translatePlatformForGA(platform); context.ga('send', 'event', categories.audioTest, state, normalizedPlatform); } function trackSessionCount(musicianAccess, fanAccess, invitationCount) { assertBoolean(musicianAccess); assertBoolean(fanAccess); assertNumber(invitationCount); var gaMusicianAccess = musicianAccess ? "MusicianPublic" : "MusicianPrivate"; var gaFanAccess = fanAccess ? "FanPublic" : "FanPrivate"; context.ga('send', 'event', categories.sessionCount, gaMusicianAccess, gaFanAccess, invitationCount); } function trackSessionMusicians(joinOrCreate) { assertOneOf(joinOrCreate, sessionCreationTypes); context.ga('send', 'event', categories.sessionMusicians, joinOrCreate); } function trackSessionQuality(goodOrPoor) { assertOneOf(goodOrPoor, sessionQualityTypes); context.ga('send', 'event', categories.sessionQuality, goodOrPoor); } function trackServiceInvitations(invitationType, numInvited) { assertOneOf(invitationType, invitationTypes); assertNumber(numInvited); context.ga('send', 'event', categories.invite, invitationType, numInvited); } function trackFindSessions(numSessionsFound) { assertNumber(numSessionsFound); var sessionCountRollup = "n/a"; if(numSessionsFound === 0) { sessionCountRollup = "0"; } else if(numSessionsFound >= 1 && numSessionsFound <= 5) { sessionCountRollup = "1-5"; } else if(numSessionsFound >= 6 && numSessionsFound <= 10) { sessionCountRollup = "6-10"; } else { sessionCountRollup = "10+"; } context.ga('send', 'event', categories.findSession, sessionCountRollup, numSessionsFound); } function trackJamTrackPlaySession(sessionId, inSession) { rest.getSession(sessionId).done(function(session) { if (session && session.jam_track ) { rest.getJamTracks({id:session.jam_track.id}).done(function(response) { if (response.jamtracks && response.jamtracks.length!=0) { var jamtrack = response.jamtracks[0] trackJamTrackPlay( jamtrack.sales_region!=context.JK.AVAILABILITY_US, session.participants.length > 1, inSession); }// if })// rest.getJamTracks }// if })// rest.getSession } function trackJamTrackPlay(isGlobal, isPublic, inSession) { assertBoolean(isGlobal) assertBoolean(isPublic) assertBoolean(inSession) context.ga( 'send', 'event', (isGlobal) ? jamTrackAvailabilityTypes.worldwide : jamTrackAvailabilityTypes.usa, (isPublic) ? jamTrackActions.isPublic : jamTrackActions.isPrivate, (inSession) ? jamTrackSessionLabels.inSession : jamTrackSessionLabels.nonSession ) logger.debug("Tracked Jam Track Play") } function trackTiming(timing) { if(!timing) {return} try { var computed = { dns: timing.domainLookupEnd - timing.domainLookupStart, connect: timing.connectEnd - timing.connectStart, ttfb: timing.responseStart - timing.connectEnd, basePage: timing.responseEnd - timing.responseStart, frontEnd: timing.loadEventStart - timing.responseEnd, domContentLoadedEvent: timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart, windowLoadEvent: timing.loadEventEnd - timing.loadEventStart, domInteractive: timing.domInteractive - timing.domLoading, domComplete: timing.domComplete - timing.domLoading, domCompleteToOnload: timing.loadEventStart - timing.domComplete }; logger.debug("page load time: " + computed.frontEnd) context._.each(computed, function (value, key) { if (value > 0 && value < 60000) { context.ga("send", "timing", "NavigationTiming", key, value, null, {'page' : '/' + window.location.pathname}); } }) //context.stats.write('web.timing.navigation', computed) } catch(e) { logger.error("loading times failed in ga.js", e) } } // if you want to pass in no title, either omit it from the arg list when u invoke virtualPageView, or pass in undefined, NOT null function virtualPageView(page, title) { context.ga('send', 'pageview', { 'page': page, 'title': title }); } function trackFriendConnect(friendConnectType) { assertOneOf(friendConnectType, friendConnectTypes); context.ga('send', 'event', categories.friendConnect, friendConnectType); } // when someone keeps a recording function trackMakeRecording() { context.ga('send', 'event', categories.recording, recordingActions.make); } // when someone shares a recording function trackShareRecording(shareType) { assertOneOf(shareType, recordingShareTypes); context.ga('send', 'event', categories.recording, recordingActions.share, shareType); } function _defaultPlayAction() { return !window.jamClient || ((typeof(FakeJamClient)!='undefined') && window.jamClient === FakeJamClient) ? 'Website' : 'Client'; } // when someone plays a recording function trackRecordingPlay(recording, recordingAction) { if (!recordingAction) { recordingAction = _defaultPlayAction(); } assertOneOf(recordingAction, recordingPlayActions); var label = JK.currentUserId ? userLabels.registeredUser : userLabels.visitor; context.ga('send', 'event', categories.recordingPlay, recordingAction, label); if (recording.jam_track) { rest.getJamTracks({id:recording.jam_track_id}).done(function(response) { if (response.jamtracks && response.jamtracks.length==1) { var jamtrack = response.jamtracks[0] trackJamTrackPlay(jamtrack.sales_region!=context.JK.AVAILABILITY_US, recording.fan_access, false); } }) } } // when someone plays a live session broadcast function trackSessionPlay(session, recordingAction) { logger.debug("Tracking session play: ", session) if (!recordingAction) { recordingAction = _defaultPlayAction(); } assertOneOf(recordingAction, sessionPlayActions); var label = JK.currentUserId ? userLabels.registeredUser : userLabels.visitor; context.ga('send', 'event', categories.sessionPlay, recordingAction, label); } function trackBand(bandAction) { assertOneOf(bandAction, bandActions); context.ga('send', 'event', categories.band, bandAction); } function trackJKSocial(category, target, data) { assertOneOf(category, categories); assertOneOf(target, jkSocialTargets); context.ga('send', 'event', category, target, data); } function trackNetworkTest(platform, numUsers) { var normalizedPlatform = translatePlatformForGA(platform); context.ga('send', 'event', categories.networkTest, 'Passed', normalizedPlatform, numUsers); } function trackNetworkTestFailure(reason, data) { assertOneOf(reason, networkTestFailReasons); context.ga('send', 'event', categories.networkTest, 'Failed', reason, data); } function trackAudioTestCompletion(platform) { var normalizedPlatform = translatePlatformForGA(platform); context.ga('send', 'event', categories.audioTest, 'Passed', normalizedPlatform); } function trackAudioTestFailure(platform, reason, data) { assertOneOf(reason, audioTestFailReasons); var normalizedPlatform = translatePlatformForGA(platform); if(normalizedPlatform == "Windows") { var action = "FailedWin"; } else if(normalizedPlatform == "Mac") { var action = "FailedMac"; } else { var action = "FailedLinux"; } context.ga('send', 'event', categories.audioTest, action, reason, data); } function trackConfigureTracksCompletion(platform) { var normalizedPlatform = translatePlatformForGA(platform); context.ga('send', 'event', categories.trackConfig, 'Passed', normalizedPlatform); } function trackAudioTestData(uniqueDeviceName, reason, data) { assertOneOf(reason, audioTestDataReasons); context.ga('send', 'event', categories.audioTestData, uniqueDeviceName, reason, data); } var GA = {}; GA.Categories = categories; GA.SessionCreationTypes = sessionCreationTypes; GA.SessionQualityTypes = sessionQualityTypes; GA.InvitationTypes = invitationTypes; GA.FriendConnectTypes = friendConnectTypes; GA.RecordingActions = recordingActions; GA.BandActions = bandActions; GA.JKSocialTargets = jkSocialTargets; GA.AudioTestFailReasons = audioTestFailReasons; GA.AudioTestDataReasons = audioTestDataReasons; GA.NetworkTestFailReasons = networkTestFailReasons; GA.FileDownloadTypes = fileDownloads; GA.trackRegister = trackRegister; GA.trackDownload = trackDownload; GA.trackFTUECompletion = trackFTUECompletion; GA.trackNetworkTest = trackNetworkTest; GA.trackNetworkTestFailure = trackNetworkTestFailure; GA.trackAudioTestCompletion = trackAudioTestCompletion; GA.trackAudioTestFailure = trackAudioTestFailure; GA.trackAudioTestData = trackAudioTestData; GA.trackConfigureTracksCompletion = trackConfigureTracksCompletion; GA.trackSessionCount = trackSessionCount; GA.trackSessionMusicians = trackSessionMusicians; GA.trackSessionQuality = trackSessionQuality; GA.trackServiceInvitations = trackServiceInvitations; GA.trackFindSessions = trackFindSessions; GA.trackJamTrackPlay = trackJamTrackPlay; GA.trackJamTrackPlaySession = trackJamTrackPlaySession; GA.trackFriendConnect = trackFriendConnect; GA.trackMakeRecording = trackMakeRecording; GA.trackShareRecording = trackShareRecording; GA.trackRecordingPlay = trackRecordingPlay; GA.trackSessionPlay = trackSessionPlay; GA.trackBand = trackBand; GA.trackJKSocial = trackJKSocial; GA.virtualPageView = virtualPageView; GA.trackTiming = trackTiming; GA.trackFileDownload = trackFileDownload; GA.trackTestDrivePurchase = trackTestDrivePurchase; context.JK.GA = GA; })(window,jQuery);