Commit 2abd023a by Will Daly

Merge pull request #5895 from edx/will/logistration-include-course-in-analytics

Logistration: Include course ID in analytics events for login/registration
parents bb257b6f 95a435ab
...@@ -343,6 +343,20 @@ def shim_student_view(view_func, check_logged_in=False): ...@@ -343,6 +343,20 @@ def shim_student_view(view_func, check_logged_in=False):
if "course_id" in request.POST: if "course_id" in request.POST:
del request.POST["course_id"] 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 # Backwards compatibility: the student view expects both
# terms of service and honor code values. Since we're combining # terms of service and honor code values. Since we're combining
# these into a single checkbox, the only value we may get # these into a single checkbox, the only value we may get
......
...@@ -150,6 +150,17 @@ class StudentViewShimTest(TestCase): ...@@ -150,6 +150,17 @@ class StudentViewShimTest(TestCase):
self.assertNotIn("enrollment_action", self.captured_request.POST) self.assertNotIn("enrollment_action", self.captured_request.POST)
self.assertNotIn("course_id", 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): def test_third_party_auth_login_failure(self):
view = self._shimmed_view( view = self._shimmed_view(
HttpResponse(status=403), HttpResponse(status=403),
......
...@@ -133,6 +133,13 @@ class LoginSessionView(APIView): ...@@ -133,6 +133,13 @@ class LoginSessionView(APIView):
def post(self, request): def post(self, request):
"""Log in a user. """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: Arguments:
request (HttpRequest) request (HttpRequest)
...@@ -148,7 +155,7 @@ class LoginSessionView(APIView): ...@@ -148,7 +155,7 @@ class LoginSessionView(APIView):
Example Usage: Example Usage:
POST /user_api/v1/login_session POST /user_api/v1/login_session
with POST params `email` and `password` with POST params `email`, `password`, and `remember`.
200 OK 200 OK
...@@ -246,6 +253,13 @@ class RegistrationView(APIView): ...@@ -246,6 +253,13 @@ class RegistrationView(APIView):
def post(self, request): def post(self, request):
"""Create the user's account. """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: Arguments:
request (HTTPRequest) request (HTTPRequest)
......
...@@ -24,14 +24,27 @@ var edx = edx || {}; ...@@ -24,14 +24,27 @@ var edx = edx || {};
}, },
sync: function(method, model) { sync: function(method, model) {
var headers = { var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
'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({ $.ajax({
url: model.urlRoot, url: model.urlRoot,
type: model.ajaxType, type: model.ajaxType,
data: model.attributes, data: data,
headers: headers, headers: headers,
success: function() { success: function() {
model.trigger('sync'); model.trigger('sync');
......
...@@ -30,14 +30,27 @@ var edx = edx || {}; ...@@ -30,14 +30,27 @@ var edx = edx || {};
}, },
sync: function(method, model) { sync: function(method, model) {
var headers = { var headers = { 'X-CSRFToken': $.cookie('csrftoken') },
'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({ $.ajax({
url: model.urlRoot, url: model.urlRoot,
type: model.ajaxType, type: model.ajaxType,
data: model.attributes, data: data,
headers: headers, headers: headers,
success: function() { success: function() {
model.trigger('sync'); 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