Commit 95a435ab by Will Daly

Include course ID in analytics events for logistration

parent a13f4f2f
......@@ -343,6 +343,20 @@ def shim_student_view(view_func, check_logged_in=False):
if "course_id" in request.POST:
del request.POST["course_id"]
# Include the course ID if it's specified in the analytics info
# so it can be included in analytics events.
if "analytics" in request.POST:
try:
analytics = json.loads(request.POST["analytics"])
if "enroll_course_id" in analytics:
request.POST["course_id"] = analytics.get("enroll_course_id")
except (ValueError, TypeError):
LOGGER.error(
u"Could not parse analytics object sent to user API: {analytics}".format(
analytics=analytics
)
)
# Backwards compatibility: the student view expects both
# terms of service and honor code values. Since we're combining
# these into a single checkbox, the only value we may get
......
......@@ -150,6 +150,17 @@ class StudentViewShimTest(TestCase):
self.assertNotIn("enrollment_action", self.captured_request.POST)
self.assertNotIn("course_id", self.captured_request.POST)
def test_include_analytics_info(self):
view = self._shimmed_view(HttpResponse())
request = HttpRequest()
request.POST["analytics"] = json.dumps({
"enroll_course_id": "edX/DemoX/Fall"
})
view(request)
# Expect that the analytics course ID was passed to the view
self.assertEqual(self.captured_request.POST.get("course_id"), "edX/DemoX/Fall")
def test_third_party_auth_login_failure(self):
view = self._shimmed_view(
HttpResponse(status=403),
......
......@@ -133,6 +133,13 @@ class LoginSessionView(APIView):
def post(self, request):
"""Log in a user.
You must send all required form fields with the request.
You can optionally send an `analytics` param with a JSON-encoded
object with additional info to include in the login analytics event.
Currently, the only supported field is "enroll_course_id" to indicate
that the user logged in while enrolling in a particular course.
Arguments:
request (HttpRequest)
......@@ -148,7 +155,7 @@ class LoginSessionView(APIView):
Example Usage:
POST /user_api/v1/login_session
with POST params `email` and `password`
with POST params `email`, `password`, and `remember`.
200 OK
......@@ -246,6 +253,13 @@ class RegistrationView(APIView):
def post(self, request):
"""Create the user's account.
You must send all required form fields with the request.
You can optionally send an `analytics` param with a JSON-encoded
object with additional info to include in the registration analytics event.
Currently, the only supported field is "enroll_course_id" to indicate
that the user registered while enrolling in a particular course.
Arguments:
request (HTTPRequest)
......
......@@ -6,8 +6,8 @@ define([
'js/student_account/models/LoginModel',
'js/student_account/views/LoginView'
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView) {
describe('edx.student.account.LoginView', function() {
'use strict';
describe('edx.student.account.LoginView', function() {
var model = null,
view = null,
......@@ -69,7 +69,8 @@ define([
restrictions: {}
}
]
};
},
COURSE_ID = "edX/demoX/Fall";
var createLoginView = function(test) {
// Initialize the login model
......@@ -147,6 +148,35 @@ define([
expect(authComplete).toBe(true);
});
it('sends analytics info containing the enrolled course ID', function() {
createLoginView( this );
// Simulate that the user is attempting to enroll in a course
// by setting the course_id query string param.
spyOn($, 'url').andCallFake(function( param ) {
if (param === "?course_id") {
return encodeURIComponent( COURSE_ID );
}
});
// Attempt to login
submitForm( true );
// Verify that the client sent the course ID for analytics
var expectedData = {};
$.extend(expectedData, USER_DATA, {
analytics: JSON.stringify({
enroll_course_id: COURSE_ID
})
});
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( expectedData )
);
});
it('displays third-party auth login buttons', function() {
createLoginView(this);
......@@ -209,5 +239,4 @@ define([
expect(authComplete).toBe(true);
});
});
}
);
});
......@@ -6,14 +6,16 @@ define([
'js/student_account/models/RegisterModel',
'js/student_account/views/RegisterView'
], function($, _, TemplateHelpers, AjaxHelpers, RegisterModel, RegisterView) {
describe('edx.student.account.RegisterView', function() {
'use strict';
describe('edx.student.account.RegisterView', function() {
var model = null,
view = null,
requests = null,
authComplete = false,
PLATFORM_NAME = 'edX',
COURSE_ID = "edX/DemoX/Fall",
USER_DATA = {
email: 'xsy@edx.org',
name: 'Xsy M. Education',
......@@ -226,7 +228,7 @@ define([
createRegisterView(this);
// Submit the form, with successful validation
submitForm(true);
submitForm( true );
// Verify that the client contacts the server with the expected data
AjaxHelpers.expectRequest(
......@@ -242,6 +244,35 @@ define([
expect(authComplete).toBe(true);
});
it('sends analytics info containing the enrolled course ID', function() {
createRegisterView( this );
// Simulate that the user is attempting to enroll in a course
// by setting the course_id query string param.
spyOn($, 'url').andCallFake(function( param ) {
if (param === "?course_id") {
return encodeURIComponent( COURSE_ID );
}
});
// Attempt to register
submitForm( true );
// Verify that the client sent the course ID for analytics
var expectedData = {};
$.extend(expectedData, USER_DATA, {
analytics: JSON.stringify({
enroll_course_id: COURSE_ID
})
});
AjaxHelpers.expectRequest(
requests, 'POST',
FORM_DESCRIPTION.submit_url,
$.param( expectedData )
);
});
it('displays third-party auth registration buttons', function() {
createRegisterView(this);
......@@ -303,5 +334,4 @@ define([
expect(authComplete).toBe(true);
});
});
}
);
});
......@@ -24,14 +24,27 @@ var edx = edx || {};
},
sync: function(method, model) {
var headers = {
'X-CSRFToken': $.cookie('csrftoken')
};
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
analytics,
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent( courseId )
});
}
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes, { analytics: analytics });
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: model.attributes,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
......
......@@ -30,14 +30,27 @@ var edx = edx || {};
},
sync: function(method, model) {
var headers = {
'X-CSRFToken': $.cookie('csrftoken')
};
var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
data = {},
analytics,
courseId = $.url( '?course_id' );
// If there is a course ID in the query string param,
// send that to the server as well so it can be included
// in analytics events.
if ( courseId ) {
analytics = JSON.stringify({
enroll_course_id: decodeURIComponent( courseId )
});
}
// Include all form fields and analytics info in the data sent to the server
$.extend( data, model.attributes, { analytics: analytics });
$.ajax({
url: model.urlRoot,
type: model.ajaxType,
data: model.attributes,
data: data,
headers: headers,
success: function() {
model.trigger('sync');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment