Add GoogleAnalytics event tracking

This commit is contained in:
Andrew Miner
2016-05-11 21:39:43 -07:00
parent c441d75529
commit 16848772a3
21 changed files with 176 additions and 36 deletions
+11 -6
View File
@@ -18,15 +18,18 @@ global.π = Math.PI
global.ε = 0.0001
global.w = require 'when'
global.Backbone = Backbone = require 'backbone'
Backbone.$ = $
{Logger} = require 'crafting-guide-common'
global.logger = new Logger
Tracker = require './tracker'
global.tracker = new Tracker
marked = require 'marked'
marked.setOptions sanitize:true
global.Backbone = Backbone = require 'backbone'
Backbone.$ = $
########################################################################################################################
global.hostName = window.location.hostname
@@ -44,9 +47,10 @@ switch global.hostName
logger.level = Logger.VERBOSE
apiBaseUrl = 'http://api-staging.crafting-guide.com'
when 'crafting-guide.com'
global.env = 'production'
logger.level = Logger.INFO
apiBaseUrl = 'http://api.crafting-guide.com'
global.env = 'production'
logger.level = Logger.INFO
tracker.enabled = true
apiBaseUrl = 'http://api.crafting-guide.com'
else
throw new Error "cannot determine the environment of: #{window.location.hostname}"
@@ -75,4 +79,5 @@ site.loadDefaultModPack()
site.loadCurrentUser()
Backbone.history.start pushState:true
tracker.trackPageView()
logger.info -> "CraftingGuide is ready"
+16 -5
View File
@@ -49,15 +49,26 @@ module.exports = class BaseController extends Backbone.View
@off()
routeLinkClick: (event)->
event.preventDefault()
href = $(event.target).attr 'href'
href ?= $(event.currentTarget).attr 'href'
logger.info "Re-routing link to internal navigation: #{href}"
$link = $(event.target)
if not $link.attr('href')?
$link = $(event.currentTarget)
href = $link.attr 'href'
target = $link.attr 'target'
logger.info -> "Re-routing link to internal navigation: #{href}"
if href? and href.match /^http/
window.location.href = href
tracker.trackEvent c.tracking.category.navigate, 'external-link', href
.then -> window.location.href = href
return false
else if target?
tracker.trackEvent c.tracking.category.navigate, 'external-link', href
return true
else
tracker.trackEvent c.tracking.category.navigate, 'internal-link', href
@router.navigate href, trigger:true
return false
show: ($el)->
$el ?= @$el
@@ -40,6 +40,7 @@ module.exports = class InventoryController extends BaseController
@_isAcceptable = options.isAcceptable ?= null
@_secondButtonType = options.secondButtonType ?= null
@_shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
@_trackingContext = options.trackingContext ?= null
options.templateName = 'common/inventory'
super options
@@ -54,20 +55,26 @@ module.exports = class InventoryController extends BaseController
return unless @model?
return if @$clearButton.hasClass 'disabled'
tracker.trackEvent @_trackingContext, 'clear'
@model.clear()
@trigger c.event.clear, this
@trigger c.event.change, this
onFirstButtonClicked: (stackController)->
tracker.trackEvent @_trackingContext, 'remove-from', stackController?.model?.itemSlug
@trigger c.event.button.first, this, stackController?.model?.itemSlug
onItemSelectorButtonClicked: ->
return unless @model?
tracker.trackEvent @_trackingContext, 'launch-add-to'
@_selector.launch()
.then (itemSlug)=>
return unless itemSlug?
if not itemSlug?
tracker.trackEvent @_trackingContext, 'cancel-add-to'
return
tracker.trackEvent @_trackingContext, 'complete-add-to', itemSlug
@model.add itemSlug, 1
@trigger c.event.add, this, itemSlug
@trigger c.event.change, this
@@ -136,6 +143,7 @@ module.exports = class InventoryController extends BaseController
router: @_router
secondButtonType: @_secondButtonType
shouldEnableButton: @_shouldEnableButton
trackingContext: @_trackingContext
controller.on c.event.change, => @trigger c.event.change, this
controller.on c.event.button.first, (c)=> @onFirstButtonClicked(c)
controller.on c.event.button.second, (c)=> @onSecondButtonClicked(c)
@@ -29,10 +29,6 @@ module.exports = class ItemSelectorController extends BaseController
# Public Methods ###############################################################################
launch: (hint='')->
if @_session
@_session.resolve null
@_session = null
@model.hint = hint
if @rendered then @refresh()
@@ -141,6 +137,10 @@ module.exports = class ItemSelectorController extends BaseController
@$popup.detach()
@model.hint = ''
if @_session
@_session.resolve null
@_session = null
_disableWindowScrolling: ->
@_windowScrollPosition = $(window).scrollTop()
$('body').addClass('scrollDisabled').css('margin-top', -@_windowScrollPosition)
@@ -60,6 +60,7 @@ module.exports = class MarkdownSectionController extends BaseController
# Event Methods ################################################################################
onCancelClicked: (event)->
tracker.trackEvent c.tracking.category.markdown, 'cancel'
@model = @_originalModel
@resetToDefaultState()
@@ -70,6 +71,7 @@ module.exports = class MarkdownSectionController extends BaseController
onEditClicked: (event)->
return false unless @editable
tracker.trackEvent c.tracking.category.markdown, 'edit'
@_originalModel = @model
@state = @State.waiting
@_beginEditing()
@@ -87,15 +89,18 @@ module.exports = class MarkdownSectionController extends BaseController
return false
onPreviewClicked: (event)->
tracker.trackEvent c.tracking.category.markdown, 'preview'
@_updatePreview()
@state = @State.previewing
return false
onReturnClicked: (event)->
tracker.trackEvent c.tracking.category.markdown, 'return'
@state = @State.editing
return false
onSaveClicked: (event)->
tracker.trackEvent c.tracking.category.markdown, 'save'
@state = @State.waiting
@_endEditing()
.then =>
@@ -36,6 +36,7 @@ module.exports = class StackController extends BaseController
@_modPack = options.modPack
@_secondButtonType = options.secondButtonType ?= null
@_shouldEnableButton = options.shouldEnableButton ?= (model, button)-> true
@_trackingContext = options.trackingContext ?= null
@_modPack.on c.event.change, => @tryRefresh()
@@ -70,6 +71,8 @@ module.exports = class StackController extends BaseController
@trigger c.event.change + ':quantity', this, oldQuantity, newQuantity
@trigger c.event.change, this
tracker.trackEvent @_trackingContext, 'update-quantity', @model.itemSlug, @model.quantity
onQuantityFieldChanged: ->
return unless @_editable
@@ -59,6 +59,7 @@ module.exports = class CraftPageController extends PageController
$el = $el.parent()
if inventoryText?
tracker.trackEvent c.tracking.category.craft, 'add-sample', inventoryText
sampleInventory = new SimpleInventory
sampleInventory.parse inventoryText
@model.craftsman.want.addInventory sampleInventory
@@ -91,6 +92,7 @@ module.exports = class CraftPageController extends PageController
modPack: @_modPack
model: @model.craftsman.want
router: @_router
trackingContext: c.tracking.category.craftWant
@_wantInventoryController.on c.event.button.first, (c, s)=> @onRemoveFromWant(s)
@_wantInventoryController.on c.event.change, (c)=> @onWantInventoryChanged()
@@ -100,6 +102,7 @@ module.exports = class CraftPageController extends PageController
modPack: @_modPack
model: @model.craftsman.have
router: @_router
trackingContext: c.tracking.category.craftHave
@_haveInventoryController.on c.event.button.first, (controller, itemSlug)=>
@onRemoveFromHaveInventory itemSlug
@@ -110,6 +113,7 @@ module.exports = class CraftPageController extends PageController
modPack: @_modPack
model: null
router: @_router
trackingContext: c.tracking.category.craftNeed
@_needInventoryController.on c.event.button.first, (c, s)=> @onMoveNeedToHave(s)
@_workingSectionController = @addChild CraftsmanWorkingController, '.view__craftsman_working',
@@ -24,6 +24,7 @@ module.exports = class CraftsmanWorkingController extends BaseController
# Event Methods ################################################################################
onButtonClicked: ->
tracker.trackEvent c.tracking.category.craft, 'start'
@trigger c.event.click
@model.reset()
@model.work()
@@ -41,8 +41,13 @@ module.exports = class StepController extends BaseController
onCompleteButtonClicked: (event)->
return if @$completeButton.hasClass 'disabled'
tracker.trackEvent c.tracking.category.craft, 'mark-complete', null, @model.number
@onComplete this
onShowToolPlan: (event)->
tracker.trackEvent c.tracking.category.navigate, 'show-tool-plan', @$toolButton.attr 'target'
return true
# BaseController Overrides #####################################################################
onDidRender: ->
@@ -90,6 +95,7 @@ module.exports = class StepController extends BaseController
events: ->
return _.extend super,
'click .button.complete': 'onCompleteButtonClicked'
'click a.button.tool': 'onShowToolPlan'
# Private Methods ##############################################################################
+2 -2
View File
@@ -7,8 +7,8 @@
.view__feedback
.form-content
input(name="name", placeholder="name (optional)")
input(name="email", placeholder="email (optional)")
input(name="name", placeholder="name")
input(name="email", placeholder="email")
label(name="comment") Comment:
textarea(name="comment")
@@ -22,6 +22,7 @@ module.exports = class FeedbackController extends BaseController
# Public Methods ###############################################################################
enterFeedback: (message)->
tracker.trackEvent c.tracking.category.feedback, 'ask-a-question'
promise = w(true)
if not @isOpen then promise = @onToggle()
promise.then => @$commentField.val message
@@ -38,6 +39,7 @@ module.exports = class FeedbackController extends BaseController
email: @$emailField.val()
comment: @$commentField.val()
tracker.trackEvent c.tracking.category.feedback, 'send'
@model.send('feedback', message)
.then =>
@onToggle()
@@ -58,6 +60,7 @@ module.exports = class FeedbackController extends BaseController
@$screen.off 'click'
if @isOpen
tracker.trackEvent c.tracking.category.feedback, 'toggle-closed'
@$screen.css display:'none'
@$page.removeClass 'blur'
@$el.animate {left:-@_closeWidth}, duration:c.duration.fast, complete:=>
@@ -65,6 +68,7 @@ module.exports = class FeedbackController extends BaseController
@$('input, textarea').blur()
resolve()
else
tracker.trackEvent c.tracking.category.feedback, 'toggle-open'
@$page.addClass 'blur'
@$screen.on 'click', => @onToggle()
@$screen.css display:'block'
@@ -26,29 +26,38 @@ module.exports = class HeaderController extends BaseController
# Event Methods ################################################################################
onCraft: ->
tracker.trackEvent c.tracking.category.navigate, 'click-button', 'craft'
@router.navigate '/craft', trigger:true
return false
onBrowse: ->
tracker.trackEvent c.tracking.category.navigate, 'click-button', 'browse'
@router.navigate '/browse', trigger:true
return false
onLogin: ->
if global.site.user?
tracker.trackEvent c.tracking.category.account, 'logout'
global.site.logout()
else
tracker.trackEvent c.tracking.category.navigate, 'click-button', 'login'
@router.navigate '/login', trigger:true
return false
onNews: ->
tracker.trackEvent c.tracking.category.navigate, 'click-button', 'news'
@router.navigate '/news', trigger:true
return false
onSearch: (event, hint='')->
tracker.trackEvent c.tracking.category.search, 'launch'
@_selector.launch hint
.then (itemSlug)=>
return unless itemSlug?
if not itemSlug?
tracker.trackEvent c.tracking.category.search, 'cancel', itemSlug
return
tracker.trackEvent c.tracking.category.search, 'complete', itemSlug
itemDisplay = @_modPack.findItemDisplay itemSlug
@router.navigate itemDisplay.itemUrl, trigger:true
return false
@@ -121,7 +130,8 @@ module.exports = class HeaderController extends BaseController
@hide @$breadcrumbs
_refreshExtraNav: ->
extraNavContent = @model?.controller?.getExtraNav()
return unless _.isFunction @model?.controller?.getExtraNav
extraNavContent = @model.controller.getExtraNav()
if extraNavContent?
@$extraNav.empty()
@@ -50,6 +50,7 @@ module.exports = class ItemPageController extends PageController
# Event Methods ################################################################################
craftingPlanButtonClicked: ->
tracker.trackEvent c.tracking.category.craft, 'view-crafting-plan', @model.item.slug
display = @_modPack.findItemDisplay @model.item.slug
@_router.navigate display.craftingUrl, trigger:true
return false
@@ -29,11 +29,13 @@ module.exports = class MultiblockViewerController extends BaseController
onBackClicked: ->
return if @$backButton.hasClass 'disabled'
tracker.trackEvent c.tracking.category.multiblock, 'back'
@multiblockController.goBackLayer()
@refresh()
onNextClicked: ->
return if @$nextButton.hasClass 'disabled'
tracker.trackEvent c.tracking.category.multiblock, 'next'
@multiblockController.goNextLayer()
@refresh()
@@ -41,6 +43,7 @@ module.exports = class MultiblockViewerController extends BaseController
if itemDisplay?
@$captionText.html itemDisplay.itemName
@_imageLoader.load itemDisplay.iconUrl, @$captionIcon
tracker.trackEvent c.tracking.category.multiblock, 'hover', itemDisplay.slug
else
@$captionText.html ' '
@$captionIcon.attr 'src', '/images/empty.png'
@@ -36,15 +36,18 @@ module.exports = class LoginPageController extends PageController
# Event Methods ################################################################################
onExpandReadMore: (event)->
tracker.trackEvent c.tracking.category.account, 'click-read-more'
@$readMoreLink.css display: 'none'
@$readMoreContainer.css 'max-height':@$readMoreContent.height()
return false
onLoginButtonClicked: (event)->
@_redirectToGitHub()
tracker.trackEvent c.tracking.category.account, 'login'
.then => @_redirectToGitHub()
return false
onLogoutButtonClicked: (event)->
tracker.trackEvent c.tracking.category.account, 'logout'
global.site.logout()
return false
+3 -3
View File
@@ -27,9 +27,9 @@
and recipes from this mod.
.right
p Official Links:
a.homePage project page
a.documentation documentation
a.download download
a.homePage(target="home-page") project page
a.documentation(target="documentation") documentation
a.download(target="download") download
section.tutorials
h2 Tutorials
@@ -30,14 +30,17 @@ module.exports = class ModPageController extends BaseController
onToggleEnabled: ->
if @model.activeVersion is Mod.Version.None
tracker.trackEvent c.tracking.category.modPack, 'toggle-on', @model.slug
@model.activeVersion = Mod.Version.Latest
else
tracker.trackEvent c.tracking.category.modPack, 'toggle-off', @model.slug
@model.activeVersion = Mod.Version.None
return false
onVersionChanged: ->
@model.activeVersion = @$versionSelector.val()
tracker.trackEvent c.tracking.category.modPack, 'select-version', "#{@model.slug}@#{@model.activeVersion}"
return false
# Property Methods #############################################################################
@@ -94,7 +97,8 @@ module.exports = class ModPageController extends BaseController
events: ->
return _.extend super,
'change .version select': 'onVersionChanged'
'click .modpack': 'onToggleEnabled'
'click .modpack': 'onToggleEnabled'
'click .about .right a': 'routeLinkClick'
# Private Methods ##############################################################################
+1 -10
View File
@@ -31,7 +31,7 @@ module.exports = class Router extends Backbone.Router
navigate: ->
super
@_recordPageView()
tracker.trackPageView()
routes:
'': 'route__home'
@@ -161,12 +161,3 @@ module.exports = class Router extends Backbone.Router
_makeOptions: (options={})->
return _.extend options, @_siteController.controllerOptions
_recordPageView: ->
pathname = window.location.pathname
if global.env is 'production' and ga?
logger.info -> "Recording GA page view: #{pathname}"
ga 'send', 'pageview', pathname
else
logger.info -> "Suppressing GA page view: #{pathname}"
+1 -1
View File
@@ -1,5 +1,5 @@
#
# Crafting Guide - storage.coffee
# Crafting Guide - url_params.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
+67
View File
@@ -0,0 +1,67 @@
#
# Crafting Guide - tracker.coffee
#
# Copyright © 2014-2016 by Redwood Labs
# All rights reserved.
#
########################################################################################################################
module.exports = class Tracker
@::TIMEOUT = 5000
constructor: ->
@_enabled = false
# Public Methods ###############################################################################
trackEvent: (category, action, label='', value=0)->
return unless category?
@_trackEvent category, action, label, value
trackOutboundEvent: (category, action, label='', value=0)->
return unless category?
@_trackEvent category, action, label, value
trackPageView: (pathname)->
promise = w.promise (resolve, reject)=>
pathname ?= window.location.pathname
if @_enabled and ga?
logger.info -> "Recording GA page view: #{pathname}"
ga 'send', 'pageview', pathname, hitCallback: -> resolve true
else
logger.info -> "Suppressing GA page view: #{pathname}"
resolve true
promise.timeout @TIMEOUT
.catch (error)->
logger.error "Failed to send GA event!"
# Property Methods #############################################################################
Object.defineProperties @prototype,
enabled:
get: -> return @_enabled
set: (newEnabled)->
@_enabled = !! newEnabled
# Private Methods ##############################################################################
_trackEvent: (category, action, label='', value=0, options={})->
promise = w.promise (resolve, reject)=>
options.hitCallback = ->
resolve true
if @_enabled and ga?
logger.info -> "Recording GA event: #{category}, #{action}, '#{label}', #{value}"
ga 'send', 'event', category, action, label, value
else
logger.info -> "Suppressing GA event: #{category}, #{action}, '#{label}', #{value}"
resolve true
promise.timeout @TIMEOUT
.catch (error)->
logger.error -> "Failed to send GA event!: #{error}"