diff --git a/cms/models.py b/cms/models.py
index ad14e38935..7ee18b5226 100644
--- a/cms/models.py
+++ b/cms/models.py
@@ -750,25 +750,35 @@ def products(self):
return page_data
def get_context(self, request, *args, **kwargs):
+ hubspot_portal_id = settings.HUBSPOT_PORTAL_ID
+ hubspot_home_page_form_guid = settings.HUBSPOT_HOME_PAGE_FORM_GUID
+
if request.user.is_authenticated:
- user = request.user.email
+ user = request.user.id
else:
if "anonymous_session_id" not in request.session:
request.session["anonymous_session_id"] = str(uuid.uuid4())
user = request.session["anonymous_session_id"]
- hubspot_portal_id = settings.HUBSPOT_PORTAL_ID
- hubspot_home_page_form_guid = settings.HUBSPOT_HOME_PAGE_FORM_GUID
+
show_new_featured_carousel = features.is_enabled(
- features.ENABLE_NEW_HOME_PAGE_FEATURED, False, user
+ features.ENABLE_NEW_HOME_PAGE_FEATURED,
+ False,
+ user,
)
show_new_design_hero = features.is_enabled(
- features.ENABLE_NEW_HOME_PAGE_HERO, False, user
+ features.ENABLE_NEW_HOME_PAGE_HERO,
+ False,
+ user,
)
show_home_page_video_component = features.is_enabled(
- features.ENABLE_NEW_HOME_PAGE_VIDEO, False, user
+ features.ENABLE_NEW_HOME_PAGE_VIDEO,
+ False,
+ user,
)
show_home_page_contact_form = features.is_enabled(
- features.ENABLE_NEW_HOME_PAGE_CONTACT_FORM, False, user
+ features.ENABLE_NEW_HOME_PAGE_CONTACT_FORM,
+ False,
+ user,
)
return {
diff --git a/cms/models_test.py b/cms/models_test.py
index bce68bfb06..dcafd9b14f 100644
--- a/cms/models_test.py
+++ b/cms/models_test.py
@@ -170,8 +170,16 @@ def test_course_page_context(
member.linked_instructor_page
for member in course_page.linked_instructors.order_by("order").all()
],
- "new_design": features.is_enabled("mitxonline-new-product-page"),
- "new_footer": features.is_enabled("mitxonline-new-footer"),
+ "new_design": features.is_enabled(
+ "mitxonline-new-product-page",
+ False,
+ request.user.id if request.user.is_authenticated else "anonymousUser",
+ ),
+ "new_footer": features.is_enabled(
+ "mitxonline-new-footer",
+ False,
+ request.user.id if request.user.is_authenticated else "anonymousUser",
+ ),
}
context = course_page.get_context(request=request)
diff --git a/cms/templates/product_page.html b/cms/templates/product_page.html
index 831cb59f57..b3e4e6c3ae 100644
--- a/cms/templates/product_page.html
+++ b/cms/templates/product_page.html
@@ -118,6 +118,7 @@
Who can take this course?
{% if page.is_program_page %}
{% endif %}
+
diff --git a/frontend/public/src/components/AnonymousMenu.js b/frontend/public/src/components/AnonymousMenu.js
index 574e439d8e..db23b3303a 100644
--- a/frontend/public/src/components/AnonymousMenu.js
+++ b/frontend/public/src/components/AnonymousMenu.js
@@ -12,7 +12,7 @@ type Props = {
const AnonymousMenu = ({ mobileView }: Props) => {
const identifierPostfix = mobileView ? "Mobile" : "Desktop"
- const newDesign = checkFeatureFlag("mitxonline-new-header")
+ const newDesign = checkFeatureFlag("mitxonline-new-header", "anonymousUser")
return (
-
diff --git a/frontend/public/src/components/CourseInfoBox.js b/frontend/public/src/components/CourseInfoBox.js
index 448a761fca..eeb07e0e5e 100644
--- a/frontend/public/src/components/CourseInfoBox.js
+++ b/frontend/public/src/components/CourseInfoBox.js
@@ -11,16 +11,16 @@ import type { BaseCourseRun } from "../flow/courseTypes"
import { EnrollmentFlaggedCourseRun, RunEnrollment } from "../flow/courseTypes"
import { getCookie } from "../lib/api"
import { isWithinEnrollmentPeriod } from "../lib/courseApi"
-import type { User } from "../flow/authTypes"
+import type { CurrentUser } from "../flow/authTypes"
import { routes } from "../lib/urls"
type CourseInfoBoxProps = {
courses: Array,
courseRuns: ?Array,
enrollments: ?Array,
+ currentUser: CurrentUser,
toggleUpgradeDialogVisibility: () => Promise,
- setCurrentCourseRun: (run: EnrollmentFlaggedCourseRun) => Promise,
- currentUser: User
+ setCurrentCourseRun: (run: EnrollmentFlaggedCourseRun) => Promise
}
const getStartDateText = (run: BaseCourseRun, isArchived: boolean = false) => {
diff --git a/frontend/public/src/components/CourseProductDetailEnroll.js b/frontend/public/src/components/CourseProductDetailEnroll.js
index 9dd5aa2812..00b43ed86a 100644
--- a/frontend/public/src/components/CourseProductDetailEnroll.js
+++ b/frontend/public/src/components/CourseProductDetailEnroll.js
@@ -625,7 +625,10 @@ export class CourseProductDetailEnroll extends React.Component<
enrollments,
enrollmentsIsLoading
} = this.props
- const showNewDesign = checkFeatureFlag("mitxonline-new-product-page")
+ const showNewDesign = checkFeatureFlag(
+ "mitxonline-new-product-page",
+ currentUser && currentUser.id ? currentUser.id : "anonymousUser"
+ )
let run,
product = null
diff --git a/frontend/public/src/components/Header.js b/frontend/public/src/components/Header.js
index 60997faa7d..c65dfdef45 100644
--- a/frontend/public/src/components/Header.js
+++ b/frontend/public/src/components/Header.js
@@ -1,6 +1,8 @@
// @flow
+/* global SETTINGS:false*/
import React from "react"
import * as Sentry from "@sentry/browser"
+import posthog from "posthog-js"
import TopAppBar from "./TopAppBar"
@@ -15,7 +17,9 @@ type Props = {
}
const Header = ({ currentUser, location }: Props) => {
+ let featureFlagUserId = "anonymousUser"
if (currentUser && currentUser.is_authenticated) {
+ featureFlagUserId = currentUser.id
Sentry.configureScope(scope => {
scope.setUser({
id: currentUser.id,
@@ -24,12 +28,19 @@ const Header = ({ currentUser, location }: Props) => {
name: currentUser.name
})
})
+ posthog.identify(currentUser.id, {
+ environment: SETTINGS.environment,
+ user_id: currentUser.id
+ })
} else {
Sentry.configureScope(scope => {
scope.setUser(null)
})
}
- const showNewDesign = checkFeatureFlag("mitxonline-new-header")
+ const showNewDesign = checkFeatureFlag(
+ "mitxonline-new-header",
+ featureFlagUserId
+ )
if (showNewDesign) {
return (
diff --git a/frontend/public/src/components/ProgramProductDetailEnroll.js b/frontend/public/src/components/ProgramProductDetailEnroll.js
index 70d01abdb8..cfcdbb2af4 100644
--- a/frontend/public/src/components/ProgramProductDetailEnroll.js
+++ b/frontend/public/src/components/ProgramProductDetailEnroll.js
@@ -382,7 +382,10 @@ export class ProgramProductDetailEnroll extends React.Component<
programEnrollmentsLoading
} = this.props
- const showNewDesign = checkFeatureFlag("mitxonline-new-product-page")
+ const showNewDesign = checkFeatureFlag(
+ "mitxonline-new-product-page",
+ currentUser && currentUser.id ? currentUser.id : "anonymousUser"
+ )
let enrollment = undefined
diff --git a/frontend/public/src/components/UserMenu.js b/frontend/public/src/components/UserMenu.js
index 0cf2080248..96fc16ff99 100644
--- a/frontend/public/src/components/UserMenu.js
+++ b/frontend/public/src/components/UserMenu.js
@@ -42,7 +42,10 @@ const UserMenu = ({ currentUser, useScreenOverlay }: Props) => {
/* eslint-disable prefer-const */
let menuChildProps: MenuChildProps
let dropdownIdentifier = "dropdownMenuButton"
- const showNewDesign = checkFeatureFlag("mitxonline-new-header")
+ const showNewDesign = checkFeatureFlag(
+ "mitxonline-new-header",
+ currentUser && currentUser.id ? currentUser.id : "anonymousUser"
+ )
menuChildProps = useScreenOverlay
? {
li: overlayListItemProps,
diff --git a/frontend/public/src/containers/ProductDetailEnrollApp.js b/frontend/public/src/containers/ProductDetailEnrollApp.js
index c5d75916f6..1724e0446c 100644
--- a/frontend/public/src/containers/ProductDetailEnrollApp.js
+++ b/frontend/public/src/containers/ProductDetailEnrollApp.js
@@ -30,14 +30,18 @@ const expandExpandBlock = (event: MouseEvent) => {
type Props = {
courseId: ?string,
- programId: ?string
+ programId: ?string,
+ userId: ?number
}
export class ProductDetailEnrollApp extends React.Component {
render() {
- const { courseId, programId } = this.props
+ const { courseId, programId, userId } = this.props
- const showNewDesign = checkFeatureFlag("mitxonline-new-product-page")
+ const showNewDesign = checkFeatureFlag(
+ "mitxonline-new-product-page",
+ userId ? userId : "anonymousUser"
+ )
if (showNewDesign) {
document.querySelectorAll("a.expand_here_link").forEach(link => {
diff --git a/frontend/public/src/containers/UpsellCardApp.js b/frontend/public/src/containers/UpsellCardApp.js
index 0e2636ea6b..c49257a0a5 100644
--- a/frontend/public/src/containers/UpsellCardApp.js
+++ b/frontend/public/src/containers/UpsellCardApp.js
@@ -110,16 +110,19 @@ export class UpsellCardApp extends React.Component {
}
render() {
- const { courseRuns, isLoading } = this.props
+ const { courseRuns, currentUser, isLoading } = this.props
const run = courseRuns ? courseRuns[0] : null
- return !checkFeatureFlag("mitxonline-new-product-page") ? (
+ return !checkFeatureFlag(
+ "mitxonline-new-product-page",
+ currentUser && currentUser.id ? currentUser.id : "anonymousUser"
+ ) ? (
// $FlowFixMe: isLoading null or undefined
-
- {run ? this.renderUpgradeEnrollmentDialog(run) : null}
-
- ) : null
+
+ {run ? this.renderUpgradeEnrollmentDialog(run) : null}
+
+ ) : null
}
}
diff --git a/frontend/public/src/entry/header.js b/frontend/public/src/entry/header.js
index ae923672b2..d9928d0c52 100644
--- a/frontend/public/src/entry/header.js
+++ b/frontend/public/src/entry/header.js
@@ -39,11 +39,21 @@ const renderHeader = () => {
)
}
-const renderEnrollSection = (courseId, programId, element, reduxStore) => {
+const renderEnrollSection = (
+ courseId,
+ programId,
+ userId,
+ element,
+ reduxStore
+) => {
ReactDOM.render(
-
+
,
element
@@ -68,13 +78,16 @@ document.addEventListener("DOMContentLoaded", function() {
const upsellCardEl = document.getElementById("upsellCard")
const courseIdEl = document.getElementById("courseId")
const programIdEl = document.getElementById("programId")
+ const userIdEl = document.getElementById("userId")
if (enrollSectionEl && (programIdEl || courseIdEl)) {
const productDetailStore = configureStore()
const courseId = courseIdEl ? courseIdEl.value : undefined
const programId = programIdEl ? programIdEl.value : undefined
+ const userId = userIdEl ? userIdEl.value : undefined
renderEnrollSection(
courseId,
programId,
+ userId,
enrollSectionEl,
productDetailStore
)
diff --git a/frontend/public/src/lib/util.js b/frontend/public/src/lib/util.js
index ca6e059e99..59df80430d 100644
--- a/frontend/public/src/lib/util.js
+++ b/frontend/public/src/lib/util.js
@@ -262,12 +262,16 @@ export const getFlexiblePriceForProduct = (product: Product) => {
export const intCheckFeatureFlag = (
flag: string,
+ uniqueID: string | number,
document: Object,
settings: Object
) => {
const params = new URLSearchParams(document.location.search)
if (SETTINGS.posthog_api_host) {
- posthog.setPersonPropertiesForFlags({ environment: SETTINGS.environment })
+ posthog.setPersonPropertiesForFlags({
+ environment: SETTINGS.environment,
+ user_id: uniqueID
+ })
}
return (
(SETTINGS.posthog_api_host && posthog.isFeatureEnabled(flag)) ||
@@ -276,6 +280,6 @@ export const intCheckFeatureFlag = (
)
}
-export const checkFeatureFlag = (flag: string) => {
- return intCheckFeatureFlag(flag, document, SETTINGS)
+export const checkFeatureFlag = (flag: string, uniqueID: string | number) => {
+ return intCheckFeatureFlag(flag, uniqueID, document, SETTINGS)
}
diff --git a/frontend/public/src/lib/util_test.js b/frontend/public/src/lib/util_test.js
index 4f4156169e..ab348f8223 100644
--- a/frontend/public/src/lib/util_test.js
+++ b/frontend/public/src/lib/util_test.js
@@ -319,9 +319,20 @@ describe("utility functions", () => {
}
it("returns the flag setting if the feature flag is set", () => {
- assert.isTrue(intCheckFeatureFlag("test_flag", document, SETTINGS))
- assert.isFalse(intCheckFeatureFlag("other_test_flag", document, SETTINGS))
- assert.isTrue(intCheckFeatureFlag("flagtwo", document, SETTINGS))
+ assert.isTrue(
+ intCheckFeatureFlag("test_flag", "anonymousUser", document, SETTINGS)
+ )
+ assert.isFalse(
+ intCheckFeatureFlag(
+ "other_test_flag",
+ "anonymousUser",
+ document,
+ SETTINGS
+ )
+ )
+ assert.isTrue(
+ intCheckFeatureFlag("flagtwo", "anonymousUser", document, SETTINGS)
+ )
})
})
})
diff --git a/main/features.py b/main/features.py
index 8c576c73d7..1ce2ee810d 100644
--- a/main/features.py
+++ b/main/features.py
@@ -1,5 +1,6 @@
"""MITxOnline feature flags"""
import os
+import uuid
from functools import wraps
from django.conf import settings
@@ -35,13 +36,15 @@ def is_enabled(name, default=None, unique_id=settings.HOSTNAME):
import posthog
else:
posthog = None
-
return (
posthog
- and posthog.feature_enabled(
+ and posthog.get_feature_flag(
name,
unique_id,
- person_properties={"environment": settings.ENVIRONMENT},
+ person_properties={
+ "environment": settings.ENVIRONMENT,
+ "user_id": unique_id,
+ },
)
) or settings.FEATURES.get(name, default or settings.FEATURES_DEFAULT)
diff --git a/main/views.py b/main/views.py
index e30ad5db26..507c336b2d 100644
--- a/main/views.py
+++ b/main/views.py
@@ -11,16 +11,22 @@
from rest_framework.pagination import LimitOffsetPagination
from main import features
-from main.features import is_enabled
-
def get_base_context(request):
"""
Returns the template context key/values needed for the base template and all templates that extend it
"""
context = {
- "new_design": features.is_enabled(features.ENABLE_NEW_DESIGN, False),
- "new_footer": features.is_enabled(features.ENABLE_NEW_FOOTER, False),
+ "new_design": features.is_enabled(
+ features.ENABLE_NEW_DESIGN,
+ False,
+ request.user.id if request.user.is_authenticated else "anonymousUser",
+ ),
+ "new_footer": features.is_enabled(
+ features.ENABLE_NEW_FOOTER,
+ False,
+ request.user.id if request.user.is_authenticated else "anonymousUser",
+ ),
}
if settings.GOOGLE_DOMAIN_VERIFICATION_TAG_VALUE:
@@ -44,7 +50,11 @@ def catalog(request, **kwargs):
"""
The catalog view.
"""
- if features.is_enabled(features.ENABLE_NEW_DESIGN):
+ if features.is_enabled(
+ features.ENABLE_NEW_DESIGN,
+ False,
+ request.user.id if request.user.is_authenticated else "anonymousUser",
+ ):
context = get_base_context(request)
return render(request, "index.html", context=context)
return handler404(request, Exception)