diff --git a/app/lib/Tracker.coffee b/app/lib/Tracker.coffee
index 6f585e473..a21a7820c 100644
--- a/app/lib/Tracker.coffee
+++ b/app/lib/Tracker.coffee
@@ -1,5 +1,7 @@
{me} = require 'lib/auth'
+debugAnalytics = false
+
module.exports = class Tracker
constructor: ->
if window.tracker
@@ -10,7 +12,7 @@ module.exports = class Tracker
@updateOlark()
identify: (traits) ->
- #console.log "Would identify", traits
+ console.log "Would identify", traits if debugAnalytics
return unless me and @isProduction and analytics?
# https://segment.io/docs/methods/identify
traits ?= {}
@@ -39,13 +41,13 @@ module.exports = class Tracker
trackPageView: ->
return unless @isProduction and analytics?
url = Backbone.history.getFragment()
- #console.log "Going to track visit for", "/#{url}"
+ console.log "Going to track visit for", "/#{url}" if debugAnalytics
analytics.pageview "/#{url}"
trackEvent: (event, properties, includeProviders=null) =>
- #console.log "Would track analytics event:", event, properties
+ console.log "Would track analytics event:", event, properties if debugAnalytics
return unless me and @isProduction and analytics?
- #console.log "Going to track analytics event:", event, properties
+ console.log "Going to track analytics event:", event, properties if debugAnalytics
properties = properties or {}
context = {}
if includeProviders
@@ -54,3 +56,9 @@ module.exports = class Tracker
context.providers[provider] = true
event.label = properties.label if properties.label
analytics?.track event, properties, context
+
+ trackTiming: (duration, category, variable, label, samplePercentage=5) ->
+ # https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingTiming
+ return console.warn "Duration #{duration} invalid for trackTiming call." unless duration >= 0 and duration < 60 * 60 * 1000
+ console.log "Would track timing event:", arguments if debugAnalytics
+ window._gaq?.push ['_trackTiming', category, variable, duration, label, samplePercentage]
diff --git a/app/styles/home.sass b/app/styles/home.sass
index e2ba1fdb0..2c49541c7 100644
--- a/app/styles/home.sass
+++ b/app/styles/home.sass
@@ -7,6 +7,9 @@
text-align: center
margin-top: 0
+ #front-screenshot
+ margin: 15px 0 40px 150px
+
#trailer-wrapper
position: relative
margin: 0 auto 40px
@@ -101,6 +104,8 @@
font-size: 30px
#trailer-wrapper
display: none
+ #front-screenshot
+ display: none
#mobile-trailer-wrapper
display: inline-block
diff --git a/app/templates/home.jade b/app/templates/home.jade
index dfd523f0c..0fa7022e5 100644
--- a/app/templates/home.jade
+++ b/app/templates/home.jade
@@ -4,21 +4,29 @@ block content
h1#site-slogan(data-i18n="home.slogan") Learn to Code JavaScript by Playing a Game
- //- if language is Chinese, we use youku, because China can't visit youtube.
- //- otherwise, we use youtube.
- if languageName == "zh-HANS"
- #trailer-wrapper
-
- img(src="/images/pages/home/video_border.png")
- #mobile-trailer-wrapper
-
- else
- #trailer-wrapper
-
- img(src="/images/pages/home/video_border.png")
- #mobile-trailer-wrapper
-
- hr
+ if frontPageContent == 'video'
+ //- if language is Chinese, we use youku, because China can't visit youtube.
+ //- otherwise, we use youtube.
+ if languageName == "zh-HANS"
+ #trailer-wrapper
+
+ img(src="/images/pages/home/video_border.png")
+ #mobile-trailer-wrapper
+
+ else
+ #trailer-wrapper
+
+ img(src="/images/pages/home/video_border.png")
+ #mobile-trailer-wrapper
+
+ hr
+
+ else if frontPageContent == 'screenshot'
+ #front-screenshot
+ img(src="/images/pages/home/front_screenshot_01.png", alt="")
+
+ else if frontPageContent == 'nothing'
+ p
.alert.alert-danger.lt-ie10
strong(data-i18n="home.no_ie") CodeCombat does not run in Internet Explorer 9 or older. Sorry!
diff --git a/app/views/home_view.coffee b/app/views/home_view.coffee
index d3f5494a9..60fe75439 100644
--- a/app/views/home_view.coffee
+++ b/app/views/home_view.coffee
@@ -4,6 +4,7 @@ WizardSprite = require 'lib/surface/WizardSprite'
ThangType = require 'models/ThangType'
Simulator = require 'lib/simulator/Simulator'
{me} = require '/lib/auth'
+application = require 'application'
module.exports = class HomeView extends View
id: 'home-view'
@@ -16,7 +17,7 @@ module.exports = class HomeView extends View
getRenderData: ->
c = super()
if $.browser
- majorVersion = parseInt($.browser.version.split('.')[0])
+ majorVersion = $.browser.versionNumber
c.isOldBrowser = true if $.browser.mozilla && majorVersion < 21
c.isOldBrowser = true if $.browser.chrome && majorVersion < 17
c.isOldBrowser = true if $.browser.safari && majorVersion < 536
@@ -24,6 +25,10 @@ module.exports = class HomeView extends View
console.warn 'no more jquery browser version...'
c.isEnglish = (me.get('preferredLanguage') or 'en').startsWith 'en'
c.languageName = me.get('preferredLanguage')
+ # A/B test: https://github.com/codecombat/codecombat/issues/769
+ c.frontPageContent = {0: "video", 1: "screenshot", 2: "nothing"}[me.get('testGroupNumber') % 3]
+ application.tracker.identify frontPageContent: c.frontPageContent
+ application.tracker.trackEvent 'Front Page Content', frontPageContent: c.frontPageContent
c
afterRender: ->
@@ -40,4 +45,4 @@ module.exports = class HomeView extends View
href = playLink.attr("href").split("/")
href[href.length-1] = lastLevel if href.length isnt 0
href = href.join("/")
- playLink.attr("href", href)
\ No newline at end of file
+ playLink.attr("href", href)
diff --git a/app/views/play/level/level_loading_view.coffee b/app/views/play/level/level_loading_view.coffee
index 8035c5d14..f242acec3 100644
--- a/app/views/play/level/level_loading_view.coffee
+++ b/app/views/play/level/level_loading_view.coffee
@@ -44,4 +44,4 @@ module.exports = class LevelLoadingView extends View
onUnveilEnded: =>
return if @destroyed
- Backbone.Mediator.publish 'onLoadingViewUnveiled', view: @
+ Backbone.Mediator.publish 'level:loading-view-unveiled', view: @
diff --git a/app/views/play/level_view.coffee b/app/views/play/level_view.coffee
index 63d4507eb..56a9607e2 100644
--- a/app/views/play/level_view.coffee
+++ b/app/views/play/level_view.coffee
@@ -77,7 +77,7 @@ module.exports = class PlayLevelView extends View
me.set 'hourOfCode', true
me.save()
$('body').append($("
"))
- window.tracker?.trackEvent 'Hour of Code Begin', {}
+ application.tracker?.trackEvent 'Hour of Code Begin', {}
@isEditorPreview = @getQueryVariable 'dev'
@sessionID = @getQueryVariable 'session'
@@ -94,6 +94,7 @@ module.exports = class PlayLevelView extends View
setTimeout f, 100
else
@load()
+ application.tracker?.trackEvent 'Started Level Load', level: @levelID, label: @levelID
onLevelLoadError: (e) ->
application.router.navigate "/play?not_found=#{@levelID}", {trigger: true}
@@ -107,6 +108,7 @@ module.exports = class PlayLevelView extends View
@load()
load: ->
+ @loadStartTime = new Date()
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @getQueryVariable('opponent'), team: @getQueryVariable("team")
@listenToOnce(@levelLoader, 'loaded-all', @onLevelLoaderLoaded)
@listenTo(@levelLoader, 'progress', @onLevelLoaderProgressChanged)
@@ -210,6 +212,11 @@ module.exports = class PlayLevelView extends View
onLoadingViewUnveiled: (e) ->
@removeSubView @loadingView
@loadingView = null
+ unless @isEditorPreview
+ @loadEndTime = new Date()
+ loadDuration = @loadEndTime - @loadStartTime
+ application.tracker?.trackEvent 'Finished Level Load', level: @levelID, label: @levelID, loadDuration: loadDuration
+ application.tracker?.trackTiming loadDuration, 'Level Load Time', @levelID, @levelID
onSupermodelLoadedOne: =>
@modelsLoaded ?= 0
@@ -273,12 +280,17 @@ module.exports = class PlayLevelView extends View
$('#level-done-button').show()
@showVictory() if e.showModal
setTimeout(@preloadNextLevel, 3000)
+ return if @victorySeen
+ @victorySeen = true
+ victoryTime = (new Date()) - @loadEndTime
+ if victoryTime > 10 * 1000 # Don't track it if we're reloading an already-beaten level
+ application.tracker?.trackEvent 'Saw Victory', level: @world.name, label: @world.name
+ application.tracker?.trackTiming victoryTime, 'Level Victory Time', @levelID, @levelID, 100
showVictory: ->
options = {level: @level, supermodel: @supermodel, session: @session}
docs = new VictoryModal(options)
@openModalView(docs)
- window.tracker?.trackEvent 'Saw Victory', level: @world.name, label: @world.name
if me.get('anonymous')
window.nextLevelURL = @getNextLevelID() # Signup will go here on completion instead of reloading.
@@ -286,7 +298,7 @@ module.exports = class PlayLevelView extends View
@tome.reloadAllCode()
Backbone.Mediator.publish 'level:restarted'
$('#level-done-button', @$el).hide()
- window.tracker?.trackEvent 'Confirmed Restart', level: @world.name, label: @world.name
+ application.tracker?.trackEvent 'Confirmed Restart', level: @world.name, label: @world.name
onNewWorld: (e) ->
@world = e.world
@@ -294,7 +306,7 @@ module.exports = class PlayLevelView extends View
onInfiniteLoop: (e) ->
return unless e.firstWorld
@openModalView new InfiniteLoopModal()
- window.tracker?.trackEvent 'Saw Initial Infinite Loop', level: @world.name, label: @world.name
+ application.tracker?.trackEvent 'Saw Initial Infinite Loop', level: @world.name, label: @world.name
onPlayNextLevel: ->
nextLevelID = @getNextLevelID()
diff --git a/app/views/play/spectate_view.coffee b/app/views/play/spectate_view.coffee
index 7a3058212..93db38908 100644
--- a/app/views/play/spectate_view.coffee
+++ b/app/views/play/spectate_view.coffee
@@ -208,8 +208,9 @@ module.exports = class SpectateLevelView extends View
@loadingView?.unveil()
onLoadingViewUnveiled: (e) ->
- @removeSubView @loadingView
- @loadingView = null
+ # Don't remove it; we want its decoration around on large screens.
+ #@removeSubView @loadingView
+ #@loadingView = null
onSupermodelLoadedOne: =>
@modelsLoaded ?= 0
diff --git a/bower.json b/bower.json
index 2c7d15146..24a139f6d 100644
--- a/bower.json
+++ b/bower.json
@@ -42,7 +42,8 @@
"jquery.tablesorter": "~2.15.13",
"treema": ">=0.0.1",
"bootstrap": "~3.1.1",
- "validated-backbone-mediator": "~0.1.3"
+ "validated-backbone-mediator": "~0.1.3",
+ "jquery.browser": "~0.0.6"
},
"overrides": {
"backbone": {
@@ -58,7 +59,11 @@
"main": "lib/underscore.string.js"
},
"jsondiffpatch": {
- "main": ["build/bundle-full.js", "build/formatters.js", "src/formatters/html.css"]
+ "main": [
+ "build/bundle-full.js",
+ "build/formatters.js",
+ "src/formatters/html.css"
+ ]
},
"jquery.tablesorter": {
"main": [