diff --git a/cms/envs/common.py b/cms/envs/common.py index ddf9fe9801..2e1515d88f 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -782,6 +782,9 @@ EVENT_TRACKING_BACKENDS = { 'OPTIONS': { 'whitelist': [] } + }, + { + 'ENGINE': 'track.shim.GoogleAnalyticsProcessor' } ] } diff --git a/common/djangoapps/track/shim.py b/common/djangoapps/track/shim.py index cef42fdba4..37606d2723 100644 --- a/common/djangoapps/track/shim.py +++ b/common/djangoapps/track/shim.py @@ -166,3 +166,18 @@ class VideoEventProcessor(object): event['page'] = page event['event'] = json.dumps(payload) + + +class GoogleAnalyticsProcessor(object): + """Adds course_id as label, and sets nonInteraction property""" + + # documentation of fields here: https://segment.com/docs/integrations/google-analytics/ + # this should *only* be used on events destined for segment.com and eventually google analytics + def __call__(self, event): + context = event.get('context', {}) + course_id = context.get('course_id') + + if course_id is not None: + event['label'] = course_id + + event['nonInteraction'] = 1 diff --git a/common/djangoapps/track/tests/test_shim.py b/common/djangoapps/track/tests/test_shim.py index 2f8a0fa67b..fcd0bcd635 100644 --- a/common/djangoapps/track/tests/test_shim.py +++ b/common/djangoapps/track/tests/test_shim.py @@ -13,6 +13,12 @@ LEGACY_SHIM_PROCESSOR = [ } ] +GOOGLE_ANALYTICS_PROCESSOR = [ + { + 'ENGINE': 'track.shim.GoogleAnalyticsProcessor' + } +] + @override_settings( EVENT_TRACKING_PROCESSORS=LEGACY_SHIM_PROCESSOR, @@ -87,3 +93,59 @@ class LegacyFieldMappingProcessorTestCase(EventTrackingTestCase): 'session': '', } assert_events_equal(expected_event, emitted_event) + + +@override_settings( + EVENT_TRACKING_PROCESSORS=GOOGLE_ANALYTICS_PROCESSOR, +) +class GoogleAnalyticsProcessorTestCase(EventTrackingTestCase): + """Ensure emitted events contain the fields necessary for Google Analytics.""" + + def test_event_fields(self): + """ Test that course_id is added as the label if present, and nonInteraction is set. """ + data = {sentinel.key: sentinel.value} + + context = { + 'path': sentinel.path, + 'user_id': sentinel.user_id, + 'course_id': sentinel.course_id, + 'org_id': sentinel.org_id, + 'client_id': sentinel.client_id, + } + with self.tracker.context('test', context): + self.tracker.emit(sentinel.name, data) + + emitted_event = self.get_event() + + expected_event = { + 'context': context, + 'data': data, + 'label': sentinel.course_id, + 'name': sentinel.name, + 'nonInteraction': 1, + 'timestamp': FROZEN_TIME, + } + assert_events_equal(expected_event, emitted_event) + + def test_no_course_id(self): + """ Test that a label is not added if course_id is not specified, but nonInteraction is still set. """ + data = {sentinel.key: sentinel.value} + + context = { + 'path': sentinel.path, + 'user_id': sentinel.user_id, + 'client_id': sentinel.client_id, + } + with self.tracker.context('test', context): + self.tracker.emit(sentinel.name, data) + + emitted_event = self.get_event() + + expected_event = { + 'context': context, + 'data': data, + 'name': sentinel.name, + 'nonInteraction': 1, + 'timestamp': FROZEN_TIME, + } + assert_events_equal(expected_event, emitted_event) diff --git a/lms/envs/common.py b/lms/envs/common.py index c9559c3c85..2e41851c70 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -623,6 +623,9 @@ EVENT_TRACKING_BACKENDS = { 'OPTIONS': { 'whitelist': [] } + }, + { + 'ENGINE': 'track.shim.GoogleAnalyticsProcessor' } ] }