diff --git a/cms/envs/aws.py b/cms/envs/aws.py
index be7816d21f..edf67badfe 100644
--- a/cms/envs/aws.py
+++ b/cms/envs/aws.py
@@ -46,6 +46,9 @@ SESSION_COOKIE_DOMAIN = ENV_TOKENS.get('SESSION_COOKIE_DOMAIN')
for feature, value in ENV_TOKENS.get('MITX_FEATURES', {}).items():
MITX_FEATURES[feature] = value
+# load segment.io key, provide a dummy if it does not exist
+SEGMENT_IO_KEY = ENV_TOKENS.get('SEGMENT_IO_KEY', '***REMOVED***')
+
LOGGING = get_logger_config(LOG_DIR,
logging_env=ENV_TOKENS['LOGGING_ENV'],
syslog_addr=(ENV_TOKENS['SYSLOG_SERVER'], 514),
diff --git a/cms/envs/common.py b/cms/envs/common.py
index a56e56025f..37cfeea7a1 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -36,6 +36,7 @@ MITX_FEATURES = {
'STUB_VIDEO_FOR_TESTING': False, # do not display video when running automated acceptance tests
'STAFF_EMAIL': '', # email address for staff (eg to request course creation)
'STUDIO_NPS_SURVEY': True,
+ 'SEGMENT_IO': True,
}
ENABLE_JASMINE = False
diff --git a/cms/envs/dev.py b/cms/envs/dev.py
index ae78b93f06..dbf9c5574c 100644
--- a/cms/envs/dev.py
+++ b/cms/envs/dev.py
@@ -150,3 +150,6 @@ DEBUG_TOOLBAR_MONGO_STACKTRACES = True
# disable NPS survey in dev mode
MITX_FEATURES['STUDIO_NPS_SURVEY'] = False
+
+# segment-io key for dev
+SEGMENT_IO_KEY = 'mty8edrrsg'
diff --git a/cms/envs/test.py b/cms/envs/test.py
index 59664bfd40..820b2cbe23 100644
--- a/cms/envs/test.py
+++ b/cms/envs/test.py
@@ -118,3 +118,6 @@ PASSWORD_HASHERS = (
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
)
+
+# dummy segment-io key
+SEGMENT_IO_KEY = '***REMOVED***'
diff --git a/cms/static/coffee/src/views/module_edit.coffee b/cms/static/coffee/src/views/module_edit.coffee
index 9f7e3a5e60..3cb3b1703f 100644
--- a/cms/static/coffee/src/views/module_edit.coffee
+++ b/cms/static/coffee/src/views/module_edit.coffee
@@ -15,7 +15,7 @@ class CMS.Views.ModuleEdit extends Backbone.View
$component_editor: => @$el.find('.component-editor')
loadDisplay: ->
- XModule.loadModule(@$el.find('.xmodule_display'))
+ XModule.loadModule(@$el.find('.xmodule_display'))
loadEdit: ->
if not @module
@@ -55,6 +55,11 @@ class CMS.Views.ModuleEdit extends Backbone.View
clickSaveButton: (event) =>
event.preventDefault()
data = @module.save()
+
+ analytics.track "Saved Module",
+ course: course_location_analytics
+ id: _this.model.id
+
data.metadata = _.extend(data.metadata || {}, @metadata())
@hideModal()
@model.save(data).done( =>
diff --git a/cms/static/coffee/src/views/tabs.coffee b/cms/static/coffee/src/views/tabs.coffee
index 9fbe4e5789..1034fc988e 100644
--- a/cms/static/coffee/src/views/tabs.coffee
+++ b/cms/static/coffee/src/views/tabs.coffee
@@ -28,6 +28,10 @@ class CMS.Views.TabsEdit extends Backbone.View
@$('.component').each((idx, element) =>
tabs.push($(element).data('id'))
)
+
+ analytics.track "Reordered Static Pages",
+ course: course_location_analytics
+
$.ajax({
type:'POST',
url: '/reorder_static_tabs',
@@ -56,10 +60,18 @@ class CMS.Views.TabsEdit extends Backbone.View
'i4x://edx/templates/static_tab/Empty'
)
+ analytics.track "Added Static Page",
+ course: course_location_analytics
+
deleteTab: (event) =>
if not confirm 'Are you sure you want to delete this component? This action cannot be undone.'
return
$component = $(event.currentTarget).parents('.component')
+
+ analytics.track "Deleted Static Page",
+ course: course_location_analytics
+ id: $component.data('id')
+
$.post('/delete_item', {
id: $component.data('id')
}, =>
diff --git a/cms/static/coffee/src/views/unit.coffee b/cms/static/coffee/src/views/unit.coffee
index 42127b2800..e23477ccfa 100644
--- a/cms/static/coffee/src/views/unit.coffee
+++ b/cms/static/coffee/src/views/unit.coffee
@@ -35,6 +35,10 @@ class CMS.Views.UnitEdit extends Backbone.View
@$('.components').sortable(
handle: '.drag-handle'
update: (event, ui) =>
+ analytics.track "Reordered Components",
+ course: course_location_analytics
+ id: unit_location_analytics
+
payload = children : @components()
options = success : => @model.unset('children')
@model.save(payload, options)
@@ -89,6 +93,11 @@ class CMS.Views.UnitEdit extends Backbone.View
$(event.currentTarget).data('location')
)
+ analytics.track "Added a Component",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+ type: $(event.currentTarget).data('location')
+
@closeNewComponent(event)
components: => @$('.component').map((idx, el) -> $(el).data('id')).get()
@@ -111,6 +120,11 @@ class CMS.Views.UnitEdit extends Backbone.View
$.post('/delete_item', {
id: $component.data('id')
}, =>
+ analytics.track "Deleted a Component",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+ id: $component.data('id')
+
$component.remove()
# b/c we don't vigilantly keep children up to date
# get rid of it before it hurts someone
@@ -129,6 +143,10 @@ class CMS.Views.UnitEdit extends Backbone.View
id: @$el.data('id')
delete_children: true
}, =>
+ analytics.track "Deleted Draft",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+
window.location.reload()
)
@@ -138,6 +156,10 @@ class CMS.Views.UnitEdit extends Backbone.View
$.post('/create_draft', {
id: @$el.data('id')
}, =>
+ analytics.track "Created Draft",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+
@model.set('state', 'draft')
)
@@ -148,20 +170,31 @@ class CMS.Views.UnitEdit extends Backbone.View
$.post('/publish_draft', {
id: @$el.data('id')
}, =>
+ analytics.track "Published Draft",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+
@model.set('state', 'public')
)
setVisibility: (event) ->
if @$('.visibility-select').val() == 'private'
target_url = '/unpublish_unit'
+ visibility = "private"
else
target_url = '/publish_draft'
+ visibility = "public"
@wait(true)
$.post(target_url, {
id: @$el.data('id')
}, =>
+ analytics.track "Set Unit Visibility",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+ visibility: visibility
+
@model.set('state', @$('.visibility-select').val())
)
@@ -193,6 +226,11 @@ class CMS.Views.UnitEdit.NameEdit extends Backbone.View
@model.save(metadata: metadata)
# Update name shown in the right-hand side location summary.
$('.unit-location .editing .unit-name').html(metadata.display_name)
+ analytics.track "Edited Unit Name",
+ course: course_location_analytics
+ unit_id: unit_location_analytics
+ display_name: metadata.display_name
+
class CMS.Views.UnitEdit.LocationState extends Backbone.View
initialize: =>
diff --git a/cms/static/js/base.js b/cms/static/js/base.js
index 6ea918cc36..7b930a176b 100644
--- a/cms/static/js/base.js
+++ b/cms/static/js/base.js
@@ -331,6 +331,12 @@ function createNewUnit(e) {
var parent = $(this).data('parent');
var template = $(this).data('template');
+ analytics.track('Created a Unit', {
+ 'course': course_location_analytics,
+ 'parent_location': parent
+ });
+
+
$.post('/clone_item',
{'parent_location': parent,
'template': template,
@@ -363,6 +369,12 @@ function _deleteItem($el) {
var id = $el.data('id');
+ analytics.track('Deleted an Item', {
+ 'course': course_location_analytics,
+ 'id': id
+ });
+
+
$.post('/delete_item',
{'id': id, 'delete_children': true, 'delete_all_versions': true},
function (data) {
@@ -426,6 +438,11 @@ function displayFinishedUpload(xhr) {
var html = Mustache.to_html(template, resp);
$('table > tbody').prepend(html);
+ analytics.track('Uploaded a File', {
+ 'course': course_location_analytics,
+ 'asset_url': resp.url
+ });
+
}
function markAsLoaded() {
@@ -555,6 +572,11 @@ function saveNewSection(e) {
var template = $saveButton.data('template');
var display_name = $(this).find('.new-section-name').val();
+ analytics.track('Created a Section', {
+ 'course': course_location_analytics,
+ 'display_name': display_name
+ });
+
$.post('/clone_item', {
'parent_location': parent,
'template': template,
@@ -600,6 +622,12 @@ function saveNewCourse(e) {
return;
}
+ analytics.track('Created a Course', {
+ 'org': org,
+ 'number': number,
+ 'display_name': display_name
+ });
+
$.post('/create_new_course', {
'template': template,
'org': org,
@@ -646,9 +674,14 @@ function saveNewSubsection(e) {
var parent = $(this).find('.new-subsection-name-save').data('parent');
var template = $(this).find('.new-subsection-name-save').data('template');
-
var display_name = $(this).find('.new-subsection-name-input').val();
+ analytics.track('Created a Subsection', {
+ 'course': course_location_analytics,
+ 'display_name': display_name
+ });
+
+
$.post('/clone_item', {
'parent_location': parent,
'template': template,
@@ -702,6 +735,13 @@ function saveEditSectionName(e) {
return;
}
+ analytics.track('Edited Section Name', {
+ 'course': course_location_analytics,
+ 'display_name': display_name,
+ 'id': id
+ });
+
+
var $_this = $(this);
// call into server to commit the new order
$.ajax({
@@ -741,6 +781,12 @@ function saveSetSectionScheduleDate(e) {
var id = $modal.attr('data-id');
+ analytics.track('Edited Section Release Date', {
+ 'course': course_location_analytics,
+ 'id': id,
+ 'start': start
+ });
+
// call into server to commit the new order
$.ajax({
url: "/save_item",
diff --git a/cms/static/js/views/checklists_view.js b/cms/static/js/views/checklists_view.js
index e553c7a2ca..85c0f5242b 100644
--- a/cms/static/js/views/checklists_view.js
+++ b/cms/static/js/views/checklists_view.js
@@ -77,11 +77,18 @@ CMS.Views.Checklists = Backbone.View.extend({
var task_index = $checkbox.data('task');
var model = this.collection.at(checklist_index);
model.attributes.items[task_index].is_checked = $task.hasClass(completed);
+
model.save({},
{
success : function() {
var updatedTemplate = self.renderTemplate(model, checklist_index);
self.$el.find('#course-checklist'+checklist_index).first().replaceWith(updatedTemplate);
+
+ analytics.track('Toggled a Checklist Task', {
+ 'course': course_location_analytics,
+ 'task': model.attributes.items[task_index].short_description,
+ 'state': model.attributes.items[task_index].is_checked
+ });
},
error : CMS.ServerError
});
diff --git a/cms/static/js/views/course_info_edit.js b/cms/static/js/views/course_info_edit.js
index ce959fd443..a6d42e1927 100644
--- a/cms/static/js/views/course_info_edit.js
+++ b/cms/static/js/views/course_info_edit.js
@@ -107,6 +107,11 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
// push change to display, hide the editor, submit the change
targetModel.save({}, {error : CMS.ServerError});
this.closeEditor(this);
+
+ analytics.track('Saved Course Update', {
+ 'course': course_location_analytics,
+ 'date': this.dateEntry(event).val()
+ });
},
onCancel: function(event) {
@@ -147,6 +152,11 @@ CMS.Views.ClassInfoUpdateView = Backbone.View.extend({
return;
}
+ analytics.track('Deleted Course Update', {
+ 'course': course_location_analytics,
+ 'date': this.dateEntry(event).val()
+ });
+
var targetModel = this.eventModel(event);
this.modelDom(event).remove();
var cacheThis = this;
@@ -284,6 +294,11 @@ CMS.Views.ClassInfoHandoutsView = Backbone.View.extend({
this.model.save({}, {error: CMS.ServerError});
this.$form.hide();
this.closeEditor(this);
+
+ analytics.track('Saved Course Handouts', {
+ 'course': course_location_analytics
+ });
+
},
onCancel: function(event) {
diff --git a/cms/static/js/views/settings/advanced_view.js b/cms/static/js/views/settings/advanced_view.js
index e3ff098efb..52c5ed78d0 100644
--- a/cms/static/js/views/settings/advanced_view.js
+++ b/cms/static/js/views/settings/advanced_view.js
@@ -137,6 +137,10 @@ CMS.Views.Settings.Advanced = CMS.Views.ValidatingView.extend({
success : function() {
self.render();
self.showMessage(self.successful_changes);
+ analytics.track('Saved Advanced Settings', {
+ 'course': course_location_analytics
+ });
+
},
error : CMS.ServerError
});
diff --git a/cms/templates/base.html b/cms/templates/base.html
index 15f4c556bb..e4f5befd63 100644
--- a/cms/templates/base.html
+++ b/cms/templates/base.html
@@ -23,6 +23,8 @@
+ <%include file="widgets/segment-io.html" />
+
<%block name="header_extras">%block>
diff --git a/cms/templates/unit.html b/cms/templates/unit.html
index e1a020dfca..1b9e49620b 100644
--- a/cms/templates/unit.html
+++ b/cms/templates/unit.html
@@ -28,6 +28,7 @@
});
});
+ var unit_location_analytics = '${unit_location}';
%block>
diff --git a/cms/templates/widgets/segment-io.html b/cms/templates/widgets/segment-io.html
new file mode 100644
index 0000000000..f623c47542
--- /dev/null
+++ b/cms/templates/widgets/segment-io.html
@@ -0,0 +1,32 @@
+% if settings.MITX_FEATURES.get('SEGMENT_IO'):
+
+
+
+% else:
+
+
+
+% endif