Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move GA object to Trigger off the notification set on redirect back from purchase #2337

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions ecommerce/templates/checkout_interstitial.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ <h1 class="mt-4">Redirecting to the payment processor...</h1>
<input type="hidden" readonly="readonly" name="{{ key }}" value="{{ value }}" />
{% endfor %}
</form>
{% if ga_purchase_flag %}
{{ ga_purchase_payload | json_script:"ga-purchase-payload" }}
<script type="text/javascript">
gtag("event", "purchase", JSON.parse(document.getElementById('ga-purchase-payload').textContent));
</script>
{% endif %}
<script type="text/javascript">
document.getElementById('checkout_form').submit();
</script>
Expand Down
1 change: 1 addition & 0 deletions ecommerce/views/v0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ def post_checkout_redirect(self, order_state, order, request):
{
"type": USER_MSG_TYPE_PAYMENT_ACCEPTED,
"run": order.lines.first().purchased_object.course.title,
"order": order.reference_number,
},
)
else:
Expand Down
2 changes: 1 addition & 1 deletion frontend/public/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"react-device-detect": "1.17.0",
"react-document-title": "2.0.3",
"react-dom": "16.14.0",
"react-ga": "2.7.0",
"react-ga4": "^2.1.0",
"react-google-recaptcha": "1.1.0",
"react-hot-loader": "4.13.1",
"react-markdown": "5.0.3",
Expand Down
5 changes: 4 additions & 1 deletion frontend/public/src/components/TopBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ const TopBar = ({ currentUser }: Props) => {
return (
<header className="site-header new-design d-flex d-flex flex-column">
{showComponent ? (
<NotificationContainer id="notifications-container" />
<NotificationContainer
id="notifications-container"
currentUser={currentUser}
/>
) : null}
<nav
className={`order-1 sub-nav navbar navbar-expand-md top-navbar ${
Expand Down
4 changes: 4 additions & 0 deletions frontend/public/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,7 @@ export const NODETYPE_COURSE = "course"

export const NODEOPER_ALL = "all_of"
export const NODEOPER_MIN = "min_number_of"

export const GOOGLE_ANALYTICS_EVENT_TYPE = {
GA_PURCHASE: "purchase"
}
23 changes: 22 additions & 1 deletion frontend/public/src/containers/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import urljoin from "url-join"
import users, { currentUserSelector } from "../lib/queries/users"
import { routes } from "../lib/urls"
import {
determineUserActionForGoogleAnalytics,
getStoredUserMessage,
removeStoredUserMessage
} from "../lib/notificationsApi"
Expand All @@ -32,6 +33,9 @@ import CatalogPage from "./pages/CatalogPage"

import type { Match, Location } from "react-router"
import type { CurrentUser } from "../flow/authTypes"
import { checkFeatureFlag } from "../lib/util"
import { GOOGLE_ANALYTICS_EVENT_TYPE } from "../constants"
import { sendGAEcommerceEvent } from "../util/gaUtils"

type Props = {
match: Match,
Expand All @@ -43,8 +47,25 @@ type Props = {
export class App extends React.Component<Props, void> {
componentDidMount() {
const { addUserNotification } = this.props
const { currentUser } = this.props

const userMsg = getStoredUserMessage()
const gaFeatureFlag = checkFeatureFlag(
"mitxonline-4099-dedp-google-analytics",
currentUser
)
if (gaFeatureFlag) {
const gaEcommerceEventObject =
determineUserActionForGoogleAnalytics(currentUser)
if (
gaEcommerceEventObject.action ===
GOOGLE_ANALYTICS_EVENT_TYPE["GA_PURCHASE"]
) {
const event = gaEcommerceEventObject.order
sendGAEcommerceEvent(gaEcommerceEventObject.action, event)
}
}

const userMsg = getStoredUserMessage(currentUser)
if (userMsg) {
addUserNotification({
"loaded-user-msg": {
Expand Down
25 changes: 23 additions & 2 deletions frontend/public/src/lib/notificationsApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { isEmptyText } from "./util"
import {
ALERT_TYPE_DANGER,
ALERT_TYPE_SUCCESS,
GOOGLE_ANALYTICS_EVENT_TYPE,
USER_MSG_COOKIE_NAME,
USER_MSG_TYPE_COMPLETED_AUTH,
USER_MSG_TYPE_ENROLL_BLOCKED,
Expand All @@ -25,15 +26,35 @@ type UserMessage = {
text: string
}

export function getStoredUserMessage(): UserMessage | null {
function ingestUserMessage(): userJson | null {
const userMsgValue = getCookie(USER_MSG_COOKIE_NAME)
if (!userMsgValue || isEmptyText(userMsgValue)) {
return null
}
const userMsgObject = JSON.parse(decodeURIComponent(userMsgValue))
return JSON.parse(decodeURIComponent(userMsgValue))
}

export function getStoredUserMessage(): UserMessage | null {
const userMsgObject = ingestUserMessage()
if (!userMsgObject) {
return null
}
return parseStoredUserMessage(userMsgObject)
}

export function determineUserActionForGoogleAnalytics() {
const userMsg = ingestUserMessage()
if (!userMsg) return null
const msgType = userMsg.type || null
if (!msgType) return null
if (msgType === USER_MSG_TYPE_PAYMENT_ACCEPTED) {
return {
action: GOOGLE_ANALYTICS_EVENT_TYPE["GA_PURCHASE"],
order: userMsg.order
}
}
}

export function parseStoredUserMessage(
userMsgJson: Object
): UserMessage | null {
Expand Down
17 changes: 17 additions & 0 deletions frontend/public/src/util/gaUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ga4 from "react-ga4"

export function sendGAEvent({ category, action, label, value }) {
const event = {
category: category,
action: action,
label: label
}
if (value !== undefined) {
event.value = value
}
ga4.event(event)
}

export function sendGAEcommerceEvent({ eventType, eventData }) {
ga4.gtag("event", eventType, eventData)
}
7 changes: 4 additions & 3 deletions frontend/public/src/util/withTracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@

// From https://github.com/ReactTraining/react-router/issues/4278#issuecomment-299692502
import React from "react"
import ga from "react-ga"
import ga4 from "react-ga4"

const withTracker = (WrappedComponent: Class<React.Component<*, *>>) => {
const debug = SETTINGS.reactGaDebug === "true"

if (SETTINGS.gaTrackingID) {
ga.initialize(SETTINGS.gaTrackingID, { debug: debug })
ga4.initialize(SETTINGS.gaTrackingID, { debug: debug })
}

const HOC = (props: Object) => {
const page = props.location.pathname
const title = props.location.title
if (SETTINGS.gaTrackingID) {
ga.pageview(page)
ga4.send({ hitType: "pageview", page: page, title: title })
}
return <WrappedComponent {...props} />
}
Expand Down
13 changes: 5 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15150,7 +15150,7 @@ __metadata:
react-device-detect: 1.17.0
react-document-title: 2.0.3
react-dom: 16.14.0
react-ga: 2.7.0
react-ga4: ^2.1.0
react-google-recaptcha: 1.1.0
react-hot-loader: 4.13.1
react-markdown: 5.0.3
Expand Down Expand Up @@ -18554,13 +18554,10 @@ __metadata:
languageName: node
linkType: hard

"react-ga@npm:2.7.0":
version: 2.7.0
resolution: "react-ga@npm:2.7.0"
peerDependencies:
prop-types: ^15.6.0
react: ^15.6.2 || ^16.0
checksum: 15d8571c156edfaa204ff0041db7a901b0eeca3e3b21774e918269b0fe48204bb5b6a3df882caea5e0077aa3a32be39a48e7082e556563338f2a78b402a59463
"react-ga4@npm:^2.1.0":
version: 2.1.0
resolution: "react-ga4@npm:2.1.0"
checksum: f7fb41141418d4ad14756f1126a1e9958db37d4d84ae6cd798043dc03a390b6dba74d69311af0349f0b9580a43bda8930138194ccc29c4100efe446e2d6eb057
languageName: node
linkType: hard

Expand Down
Loading