Merge pull request #4893 from edx/web-analytics/pass-ga-cookie
Re-use GA cookie when sending server-side events to Segment.io
This commit is contained in:
@@ -756,6 +756,7 @@ class CourseEnrollment(models.Model):
|
||||
tracker.emit(event_name, data)
|
||||
|
||||
if settings.FEATURES.get('SEGMENT_IO_LMS') and settings.SEGMENT_IO_LMS_KEY:
|
||||
tracking_context = tracker.get_tracker().resolve_context()
|
||||
analytics.track(self.user_id, event_name, {
|
||||
'category': 'conversion',
|
||||
'label': self.course_id.to_deprecated_string(),
|
||||
@@ -763,7 +764,12 @@ class CourseEnrollment(models.Model):
|
||||
'course': self.course_id.course,
|
||||
'run': self.course_id.run,
|
||||
'mode': self.mode,
|
||||
}, context={
|
||||
'Google Analytics': {
|
||||
'clientId': tracking_context.get('client_id')
|
||||
}
|
||||
})
|
||||
|
||||
except: # pylint: disable=bare-except
|
||||
if event_name and self.course_id:
|
||||
log.exception('Unable to emit event %s for user %s and course %s', event_name, self.user.username, self.course_id)
|
||||
|
||||
@@ -87,7 +87,7 @@ class TrackMiddleware(object):
|
||||
Extract information from the request and add it to the tracking
|
||||
context.
|
||||
|
||||
The following fields are injected in to the context:
|
||||
The following fields are injected into the context:
|
||||
|
||||
* session - The Django session key that identifies the user's session.
|
||||
* user_id - The numeric ID for the logged in user.
|
||||
@@ -96,6 +96,7 @@ class TrackMiddleware(object):
|
||||
* host - The "SERVER_NAME" header, which should be the name of the server running this code.
|
||||
* agent - The client browser identification string.
|
||||
* path - The path part of the requested URL.
|
||||
* client_id - The unique key used by Google Analytics to identify a user
|
||||
"""
|
||||
context = {
|
||||
'session': self.get_session_key(request),
|
||||
@@ -105,6 +106,14 @@ class TrackMiddleware(object):
|
||||
for header_name, context_key in META_KEY_TO_CONTEXT_KEY.iteritems():
|
||||
context[context_key] = request.META.get(header_name, '')
|
||||
|
||||
# Google Analytics uses the clientId to keep track of unique visitors. A GA cookie looks like
|
||||
# this: _ga=GA1.2.1033501218.1368477899. The clientId is this part: 1033501218.1368477899.
|
||||
google_analytics_cookie = request.COOKIES.get('_ga')
|
||||
if google_analytics_cookie is None:
|
||||
context['client_id'] = None
|
||||
else:
|
||||
context['client_id'] = '.'.join(google_analytics_cookie.split('.')[2:])
|
||||
|
||||
context.update(contexts.course_context_from_url(request.build_absolute_uri()))
|
||||
|
||||
tracker.get_tracker().enter_context(
|
||||
|
||||
@@ -45,6 +45,10 @@ class LegacyFieldMappingProcessor(object):
|
||||
def remove_shim_context(event):
|
||||
if 'context' in event:
|
||||
context = event['context']
|
||||
for field in CONTEXT_FIELDS_TO_INCLUDE:
|
||||
# These fields are present elsewhere in the event at this point
|
||||
context_fields_to_remove = set(CONTEXT_FIELDS_TO_INCLUDE)
|
||||
# This field is only used for Segment.io web analytics and does not concern researchers
|
||||
context_fields_to_remove.add('client_id')
|
||||
for field in context_fields_to_remove:
|
||||
if field in context:
|
||||
del context[field]
|
||||
|
||||
@@ -64,6 +64,7 @@ class TrackMiddlewareTestCase(TestCase):
|
||||
'path': '/courses/',
|
||||
'org_id': '',
|
||||
'course_id': '',
|
||||
'client_id': None,
|
||||
})
|
||||
|
||||
def get_context_for_path(self, path):
|
||||
|
||||
@@ -50,6 +50,7 @@ class LegacyFieldMappingProcessorTestCase(TestCase):
|
||||
'course_id': sentinel.course_id,
|
||||
'org_id': sentinel.org_id,
|
||||
'event_type': sentinel.event_type,
|
||||
'client_id': sentinel.client_id,
|
||||
}
|
||||
with django_tracker.context('test', context):
|
||||
django_tracker.emit(sentinel.name, data)
|
||||
|
||||
@@ -144,6 +144,39 @@ class TestTrackViews(TestCase):
|
||||
|
||||
self.mock_tracker.send.assert_called_once_with(expected_event)
|
||||
|
||||
@freeze_time(expected_time)
|
||||
def test_server_track_with_middleware_and_google_analytics_cookie(self):
|
||||
middleware = TrackMiddleware()
|
||||
request = self.request_factory.get(self.path_with_course)
|
||||
request.COOKIES['_ga'] = 'GA1.2.1033501218.1368477899'
|
||||
middleware.process_request(request)
|
||||
# The middleware emits an event, reset the mock to ignore it since we aren't testing that feature.
|
||||
self.mock_tracker.reset_mock()
|
||||
try:
|
||||
views.server_track(request, str(sentinel.event_type), '{}')
|
||||
|
||||
expected_event = {
|
||||
'username': 'anonymous',
|
||||
'ip': '127.0.0.1',
|
||||
'event_source': 'server',
|
||||
'event_type': str(sentinel.event_type),
|
||||
'event': '{}',
|
||||
'agent': '',
|
||||
'page': None,
|
||||
'time': expected_time,
|
||||
'host': 'testserver',
|
||||
'context': {
|
||||
'user_id': '',
|
||||
'course_id': u'foo/bar/baz',
|
||||
'org_id': 'foo',
|
||||
'path': u'/courses/foo/bar/baz/xmod/'
|
||||
},
|
||||
}
|
||||
finally:
|
||||
middleware.process_response(request, None)
|
||||
|
||||
self.mock_tracker.send.assert_called_once_with(expected_event)
|
||||
|
||||
@freeze_time(expected_time)
|
||||
def test_server_track_with_no_request(self):
|
||||
request = None
|
||||
|
||||
Reference in New Issue
Block a user