Skip to content

Commit

Permalink
Update how we call the posthog API to include another person identifi…
Browse files Browse the repository at this point in the history
…er to allow for easier targetting (#1973)

* add userid to js calls, change python calls to user.id instead of user.email

* fmt

* check for user first

* python user checks

* fmt and things

* change how determine userid in header

* proper reporting

* change type on courseinfobox

* CourseInfoBox.js fix

* fmt

* change type for uniqueID

* fmt
  • Loading branch information
JenniWhitman committed Nov 2, 2023
1 parent 280c0a0 commit e013857
Show file tree
Hide file tree
Showing 16 changed files with 129 additions and 42 deletions.
24 changes: 17 additions & 7 deletions cms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
12 changes: 10 additions & 2 deletions cms/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions cms/templates/product_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ <h2>Who can take this course?</h2>
{% if page.is_program_page %}
<input id="programId" type="hidden" value="{{page.program.readable_id}}" />
{% endif %}
<input id="userId" type="hidden" value="{{ user.id }}" />

<div class="w-100" id="productDetailEnrollment"></div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/src/components/AnonymousMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<ul>
<li>
Expand Down
6 changes: 3 additions & 3 deletions frontend/public/src/components/CourseInfoBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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<BaseCourseRun>,
courseRuns: ?Array<EnrollmentFlaggedCourseRun>,
enrollments: ?Array<RunEnrollment>,
currentUser: CurrentUser,
toggleUpgradeDialogVisibility: () => Promise<any>,
setCurrentCourseRun: (run: EnrollmentFlaggedCourseRun) => Promise<any>,
currentUser: User
setCurrentCourseRun: (run: EnrollmentFlaggedCourseRun) => Promise<any>
}

const getStartDateText = (run: BaseCourseRun, isArchived: boolean = false) => {
Expand Down
5 changes: 4 additions & 1 deletion frontend/public/src/components/CourseProductDetailEnroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion frontend/public/src/components/Header.js
Original file line number Diff line number Diff line change
@@ -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"

Expand All @@ -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,
Expand All @@ -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 (
<React.Fragment>
Expand Down
5 changes: 4 additions & 1 deletion frontend/public/src/components/ProgramProductDetailEnroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion frontend/public/src/components/UserMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 7 additions & 3 deletions frontend/public/src/containers/ProductDetailEnrollApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@ const expandExpandBlock = (event: MouseEvent) => {

type Props = {
courseId: ?string,
programId: ?string
programId: ?string,
userId: ?number
}

export class ProductDetailEnrollApp extends React.Component<Props> {
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 => {
Expand Down
15 changes: 9 additions & 6 deletions frontend/public/src/containers/UpsellCardApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,19 @@ export class UpsellCardApp extends React.Component<Props, ProductDetailState> {
}

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
<Loader isLoading={isLoading}>
{run ? this.renderUpgradeEnrollmentDialog(run) : null}
</Loader>
) : null
<Loader isLoading={isLoading}>
{run ? this.renderUpgradeEnrollmentDialog(run) : null}
</Loader>
) : null
}
}

Expand Down
17 changes: 15 additions & 2 deletions frontend/public/src/entry/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,21 @@ const renderHeader = () => {
)
}

const renderEnrollSection = (courseId, programId, element, reduxStore) => {
const renderEnrollSection = (
courseId,
programId,
userId,
element,
reduxStore
) => {
ReactDOM.render(
<AppContainer>
<Provider store={reduxStore}>
<ProductDetailEnrollApp courseId={courseId} programId={programId} />
<ProductDetailEnrollApp
courseId={courseId}
programId={programId}
userId={userId}
/>
</Provider>
</AppContainer>,
element
Expand All @@ -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
)
Expand Down
10 changes: 7 additions & 3 deletions frontend/public/src/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)) ||
Expand All @@ -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)
}
17 changes: 14 additions & 3 deletions frontend/public/src/lib/util_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
})
})
})
9 changes: 6 additions & 3 deletions main/features.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""MITxOnline feature flags"""
import os
import uuid
from functools import wraps

from django.conf import settings
Expand Down Expand Up @@ -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)

Expand Down
20 changes: 15 additions & 5 deletions main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand Down

0 comments on commit e013857

Please sign in to comment.