Merge pull request #30878 from openedx/shafqat/VAN-1051

feat: VAN-1051 - Integrated Optimizely fullstack client and experiment
This commit is contained in:
Shafqat Farhan
2022-08-22 15:12:55 +05:00
committed by GitHub
9 changed files with 136 additions and 9 deletions

View File

@@ -635,6 +635,10 @@ DJFS = {
######################## BRANCH.IO ###########################
BRANCH_IO_KEY = ''
######################## OPTIMIZELY ###########################
OPTIMIZELY_PROJECT_ID = None
OPTIMIZELY_FULLSTACK_SDK_KEY = None
######################## GOOGLE ANALYTICS ###########################
GOOGLE_ANALYTICS_ACCOUNT = None

View File

@@ -59,6 +59,7 @@ from simple_history.models import HistoricalRecords
from user_util import user_util
import openedx.core.djangoapps.django_comment_common.comment_client as cc
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from common.djangoapps.course_modes.models import CourseMode, get_cosmetic_verified_display_price
from common.djangoapps.student.email_helpers import (
generate_proctoring_requirements_email_context,
@@ -76,6 +77,7 @@ from lms.djangoapps.courseware.models import (
OrgDynamicUpgradeDeadlineConfiguration,
)
from lms.djangoapps.courseware.toggles import streak_celebration_is_active
from lms.djangoapps.utils import OptimizelyClient
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.enrollments.api import (
@@ -1557,7 +1559,10 @@ class CourseEnrollment(models.Model):
Emits an event to explicitly track course enrollment and unenrollment.
"""
from openedx.core.djangoapps.schedules.config import set_up_external_updates_for_enrollment
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
from openedx.features.enterprise_support.utils import is_enterprise_learner
optimizely_client = OptimizelyClient.get_optimizely_client()
try:
context = contexts.course_context_from_course_id(self.course_id)
if enterprise_uuid:
@@ -1603,6 +1608,24 @@ class CourseEnrollment(models.Model):
if is_personalized_recommendation is not None:
segment_properties['is_personalized_recommendation'] = is_personalized_recommendation
# TODO: VAN-1052 - This is Optimizely's A/B experimentation block to test welcome email redesign.
# Remove this temporary block after pausing the experiment.
optimizely_experiment_variation = None
if optimizely_client:
optimizely_experiment_variation = optimizely_client.activate(
'welcome_email_redesign_experiment',
str(self.user.id),
{
'lang_preference': get_user_preference(self.user, LANGUAGE_KEY),
'is_enterprise_user': is_enterprise_learner(self.user),
}
)
optimizely_client.track('welcome_email_sent', str(self.user.id))
# Set this property to True only if the welcome email redesign Optimizely experiment is running
# and user_id falls in required variation.
segment_properties['redesign_email'] = optimizely_experiment_variation == 'redesign_email_enabled'
with tracker.get_tracker().context(event_name, context):
tracker.emit(event_name, data)
segment.track(self.user_id, event_name, segment_properties, traits=segment_traits)

View File

@@ -706,6 +706,7 @@ class EnrollmentEventTestMixin(EventTestMixin):
'external_course_updates': -1,
'course_start': course.start,
'course_pacing': course.pacing,
'redesign_email': False,
})
return properties, traits

View File

@@ -4,6 +4,8 @@ Helper Methods
from braze.client import BrazeClient
from django.conf import settings
from optimizely import optimizely
from optimizely.config_manager import PollingConfigManager
def _get_key(key_or_id, key_cls):
@@ -31,3 +33,23 @@ def get_braze_client():
api_url=braze_api_url,
app_id='',
)
class OptimizelyClient:
""" Class for instantiating an Optimizely full stack client instance. """
optimizely_client = None
@classmethod
def get_optimizely_client(cls):
if not cls.optimizely_client:
optimizely_sdk_key = settings.OPTIMIZELY_FULLSTACK_SDK_KEY
if not optimizely_sdk_key:
return None
config_manager = PollingConfigManager(
update_interval=10,
sdk_key=optimizely_sdk_key,
)
cls.optimizely_client = optimizely.Optimizely(config_manager=config_manager)
return cls.optimizely_client

View File

@@ -1509,6 +1509,7 @@ BRANCH_IO_KEY = ''
######################## OPTIMIZELY ###########################
OPTIMIZELY_PROJECT_ID = None
OPTIMIZELY_FULLSTACK_SDK_KEY = None
######################## subdomain specific settings ###########################
COURSE_LISTINGS = {}

View File

@@ -125,6 +125,7 @@ oauthlib # OAuth specification support for authentica
openedx-calc # Library supporting mathematical calculations for Open edX
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50)
optimizely-sdk # Optimizely full stack SDK for Python
ora2>=4.4.0
outcome-surveys # edx-platform plugin to send and track segment events needed for surveys
path

View File

@@ -48,6 +48,7 @@ attrs==22.1.0
# aiohttp
# blockstore
# edx-ace
# jsonschema
# openedx-events
babel==2.10.3
# via
@@ -157,6 +158,7 @@ cryptography==36.0.2
# django-fernet-fields
# edx-enterprise
# jwcrypto
# optimizely-sdk
# pyjwt
# pyopenssl
# snowflake-connector-python
@@ -288,6 +290,7 @@ django-filter==22.1
# -r requirements/edx/base.in
# blockstore
# edx-enterprise
# learner-pathway-progress
# lti-consumer-xblock
django-ipware==4.0.2
# via
@@ -398,6 +401,7 @@ djangorestframework==3.12.4
# edx-organizations
# edx-proctoring
# edx-submissions
# learner-pathway-progress
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -475,6 +479,7 @@ edx-drf-extensions==8.0.1
# edx-rbac
# edx-when
# edxval
# learner-pathway-progress
edx-enterprise==3.56.5
# via
# -c requirements/edx/../constraints.txt
@@ -598,11 +603,14 @@ icalendar==4.1.0
idna==3.3
# via
# -r requirements/edx/paver.txt
# optimizely-sdk
# requests
# snowflake-connector-python
# yarl
importlib-metadata==4.12.0
# via markdown
importlib-resources==5.9.0
# via jsonschema
inflection==0.5.1
# via drf-yasg
interchange==2021.0.4
@@ -636,6 +644,8 @@ jsonfield==3.1.0
# lti-consumer-xblock
# ora2
# outcome-surveys
jsonschema==4.14.0
# via optimizely-sdk
jwcrypto==1.3.1
# via pylti1p3
kombu==5.2.4
@@ -750,6 +760,8 @@ openedx-filters==0.7.0
# via
# -r requirements/edx/base.in
# lti-consumer-xblock
optimizely-sdk==4.1.0
# via -r requirements/edx/base.in
ora2==4.4.7
# via -r requirements/edx/base.in
oscrypto==1.3.0
@@ -787,6 +799,8 @@ pillow==9.2.0
# -r requirements/edx/base.in
# edx-enterprise
# edx-organizations
pkgutil-resolve-name==1.3.10
# via jsonschema
polib==1.1.1
# via edx-i18n-tools
prompt-toolkit==3.0.30
@@ -850,12 +864,18 @@ pynacl==1.5.0
pynliner==0.8.0
# via -r requirements/edx/base.in
pyopenssl==22.0.0
# via snowflake-connector-python
# via
# optimizely-sdk
# snowflake-connector-python
pyparsing==3.0.9
# via
# chem
# openedx-calc
# packaging
pyrsistent==0.18.1
# via
# jsonschema
# optimizely-sdk
pysrt==1.1.2
# via
# -r requirements/edx/base.in
@@ -942,6 +962,7 @@ requests==2.28.1
# geoip2
# learner-pathway-progress
# mailsnake
# optimizely-sdk
# pyjwkest
# pylti1p3
# python-swiftclient
@@ -1008,6 +1029,7 @@ six==1.16.0
# interchange
# isodate
# libsass
# optimizely-sdk
# pansi
# paver
# py2neo
@@ -1161,7 +1183,9 @@ xss-utils==0.4.0
yarl==1.8.1
# via aiohttp
zipp==3.8.1
# via importlib-metadata
# via
# importlib-metadata
# importlib-resources
# The following packages are considered to be unsafe in a requirements file:
# setuptools

View File

@@ -228,6 +228,7 @@ cryptography==36.0.2
# django-fernet-fields
# edx-enterprise
# jwcrypto
# optimizely-sdk
# pyjwt
# pyopenssl
# snowflake-connector-python
@@ -386,6 +387,7 @@ django-filter==22.1
# -r requirements/edx/testing.txt
# blockstore
# edx-enterprise
# learner-pathway-progress
# lti-consumer-xblock
django-ipware==4.0.2
# via
@@ -502,6 +504,7 @@ djangorestframework==3.12.4
# edx-organizations
# edx-proctoring
# edx-submissions
# learner-pathway-progress
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -590,6 +593,7 @@ edx-drf-extensions==8.0.1
# edx-rbac
# edx-when
# edxval
# learner-pathway-progress
edx-enterprise==3.56.5
# via
# -c requirements/edx/../constraints.txt
@@ -757,6 +761,7 @@ idna==3.3
# via
# -r requirements/edx/testing.txt
# anyio
# optimizely-sdk
# requests
# snowflake-connector-python
# yarl
@@ -769,7 +774,9 @@ importlib-metadata==4.12.0
# pytest-randomly
# sphinx
importlib-resources==5.9.0
# via jsonschema
# via
# -r requirements/edx/testing.txt
# jsonschema
inflection==0.5.1
# via
# -r requirements/edx/testing.txt
@@ -827,8 +834,11 @@ jsonfield==3.1.0
# lti-consumer-xblock
# ora2
# outcome-surveys
jsonschema==4.9.0
# via sphinxcontrib-openapi
jsonschema==4.14.0
# via
# -r requirements/edx/testing.txt
# optimizely-sdk
# sphinxcontrib-openapi
jwcrypto==1.3.1
# via
# -r requirements/edx/testing.txt
@@ -978,6 +988,8 @@ openedx-filters==0.7.0
# via
# -r requirements/edx/testing.txt
# lti-consumer-xblock
optimizely-sdk==4.1.0
# via -r requirements/edx/testing.txt
ora2==4.4.7
# via -r requirements/edx/testing.txt
oscrypto==1.3.0
@@ -1034,7 +1046,9 @@ pillow==9.2.0
pip-tools==6.8.0
# via -r requirements/edx/pip-tools.txt
pkgutil-resolve-name==1.3.10
# via jsonschema
# via
# -r requirements/edx/testing.txt
# jsonschema
platformdirs==2.5.2
# via
# -r requirements/edx/testing.txt
@@ -1075,8 +1089,9 @@ pyblake2==1.1.2
# -r requirements/edx/testing.txt
# blockstore
pycodestyle==2.8.0
# via
# -c requirements/edx/../constraints.txt
# via -r requirements/edx/testing.txt
# -r requirements/edx/testing.txt
pycountry==22.3.5
# via -r requirements/edx/testing.txt
pycparser==2.21
@@ -1163,6 +1178,7 @@ pynliner==0.8.0
pyopenssl==22.0.0
# via
# -r requirements/edx/testing.txt
# optimizely-sdk
# snowflake-connector-python
pyparsing==3.0.9
# via
@@ -1174,7 +1190,10 @@ pyparsing==3.0.9
pyquery==1.4.3
# via -r requirements/edx/testing.txt
pyrsistent==0.18.1
# via jsonschema
# via
# -r requirements/edx/testing.txt
# jsonschema
# optimizely-sdk
pysrt==1.1.2
# via
# -r requirements/edx/testing.txt
@@ -1304,6 +1323,7 @@ requests==2.28.1
# geoip2
# learner-pathway-progress
# mailsnake
# optimizely-sdk
# pact-python
# pyjwkest
# pylti1p3
@@ -1391,6 +1411,7 @@ six==1.16.0
# interchange
# isodate
# libsass
# optimizely-sdk
# pact-python
# pansi
# paver

View File

@@ -68,6 +68,7 @@ attrs==22.1.0
# aiohttp
# blockstore
# edx-ace
# jsonschema
# openedx-events
# outcome
# pytest
@@ -216,6 +217,7 @@ cryptography==36.0.2
# django-fernet-fields
# edx-enterprise
# jwcrypto
# optimizely-sdk
# pyjwt
# pyopenssl
# snowflake-connector-python
@@ -367,6 +369,7 @@ django-filter==22.1
# -r requirements/edx/base.txt
# blockstore
# edx-enterprise
# learner-pathway-progress
# lti-consumer-xblock
django-ipware==4.0.2
# via
@@ -483,6 +486,7 @@ djangorestframework==3.12.4
# edx-organizations
# edx-proctoring
# edx-submissions
# learner-pathway-progress
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -569,6 +573,7 @@ edx-drf-extensions==8.0.1
# edx-rbac
# edx-when
# edxval
# learner-pathway-progress
edx-enterprise==3.56.5
# via
# -c requirements/edx/../constraints.txt
@@ -726,6 +731,7 @@ idna==3.3
# via
# -r requirements/edx/base.txt
# anyio
# optimizely-sdk
# requests
# snowflake-connector-python
# yarl
@@ -734,6 +740,10 @@ importlib-metadata==4.12.0
# -r requirements/edx/base.txt
# markdown
# pytest-randomly
importlib-resources==5.9.0
# via
# -r requirements/edx/base.txt
# jsonschema
inflection==0.5.1
# via
# -r requirements/edx/base.txt
@@ -789,6 +799,10 @@ jsonfield==3.1.0
# lti-consumer-xblock
# ora2
# outcome-surveys
jsonschema==4.14.0
# via
# -r requirements/edx/base.txt
# optimizely-sdk
jwcrypto==1.3.1
# via
# -r requirements/edx/base.txt
@@ -925,6 +939,8 @@ openedx-filters==0.7.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
optimizely-sdk==4.1.0
# via -r requirements/edx/base.txt
ora2==4.4.7
# via -r requirements/edx/base.txt
oscrypto==1.3.0
@@ -971,6 +987,10 @@ pillow==9.2.0
# -r requirements/edx/base.txt
# edx-enterprise
# edx-organizations
pkgutil-resolve-name==1.3.10
# via
# -r requirements/edx/base.txt
# jsonschema
platformdirs==2.5.2
# via
# pylint
@@ -1010,8 +1030,9 @@ pyblake2==1.1.2
# -r requirements/edx/base.txt
# blockstore
pycodestyle==2.8.0
# via
# -c requirements/edx/../constraints.txt
# via -r requirements/edx/testing.in
# -r requirements/edx/testing.in
pycountry==22.3.5
# via -r requirements/edx/base.txt
pycparser==2.21
@@ -1090,6 +1111,7 @@ pynliner==0.8.0
pyopenssl==22.0.0
# via
# -r requirements/edx/base.txt
# optimizely-sdk
# snowflake-connector-python
pyparsing==3.0.9
# via
@@ -1099,6 +1121,11 @@ pyparsing==3.0.9
# packaging
pyquery==1.4.3
# via -r requirements/edx/testing.in
pyrsistent==0.18.1
# via
# -r requirements/edx/base.txt
# jsonschema
# optimizely-sdk
pysrt==1.1.2
# via
# -r requirements/edx/base.txt
@@ -1223,6 +1250,7 @@ requests==2.28.1
# geoip2
# learner-pathway-progress
# mailsnake
# optimizely-sdk
# pact-python
# pyjwkest
# pylti1p3
@@ -1308,6 +1336,7 @@ six==1.16.0
# interchange
# isodate
# libsass
# optimizely-sdk
# pact-python
# pansi
# paver
@@ -1526,6 +1555,7 @@ zipp==3.8.1
# via
# -r requirements/edx/base.txt
# importlib-metadata
# importlib-resources
# The following packages are considered to be unsafe in a requirements file:
# setuptools