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

feat: RV Eventing on Payment Page #19

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
38 changes: 38 additions & 0 deletions cohesion.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const cohesionConfig = {
name: 'edx',
slug: 'edx',
domain: 'edx.org',
domainLabel: 'edx',
domainExtension: '.org',
domainLabelWithExtension: 'edx.org',
postTypeGql: '',
homepageGql: '',
siteUrl: 'https://www.edx.org',
cmsUrl: process.env.NEXT_PUBLIC_WORDPRESS_URL || '',
cmsUser: process.env.WP_USER || '',
cmsPwd: process.env.WP_PWD || '',
logoUrl: '',
studyMatchUrl: '',
voyagerUrl: '/discover',
identityToken: '',
gaCid: '',
gaSid: '',
gaMid: '',
defaultDegree: '',
defaultCategory: '',
defaultSubject: '',
tagularApiKey: '',
tagularSourceKey: 'src_2euJfAVNt6Z9kQz4e9t1SQBtm8x',
tagularWriteKey: 'wk_2euJfDkJVTtEVzsC8BPOb0g9dVj',
tagularCookieDomain: 'edx.org',
tagularDomainWhitelist: JSON.stringify([
'edx.org',
]),
monarchSourceId: '',
monarchToken: '',
newRelicAppID: '',
newRelicVoyagerAppID: '',
cookieLawId: '',
};

module.exports = cohesionConfig;
23 changes: 18 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
"redux-thunk": "^2.4.1",
"regenerator-runtime": "^0.13.9",
"reselect": "^4.1.6",
"universal-cookie": "^4.0.4"
"universal-cookie": "^4.0.4",
"uuid": "^11.0.2"
},
"devDependencies": {
"@edx/browserslist-config": "^1.2.0",
Expand Down
27 changes: 27 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,33 @@
<% if (htmlWebpackPlugin.options.OPTIMIZELY_PROJECT_ID) { %>
<script src="https://www.edx.org/optimizelyjs/<%= htmlWebpackPlugin.options.OPTIMIZELY_PROJECT_ID %>.js"></script>
<% } %>

<% /* NOTE: Adding Red Ventures related cohesion/tagular code for the launch of the new marketing website. */ %>
<% if (htmlWebpackPlugin.options.cohesionConfig) { %>
<script>
{`!function(co,h,e,s,i,o,n){var d='documentElement';var a='className';h[d][a]+=' preampjs';
n.k=e;co._Cohesion=n;co._Preamp={k:s,start:new Date};co._Fuse={k:i};co._Tagular={k:o};
[e,s,i,o].map(function(x){co[x]=co[x]||function(){(co[x].q=co[x].q||[]).push([].slice.call(arguments))}});
var b=function(){var u=h[d][a];h[d][a]=u.replace(/ ?preampjs/g,'')};
h.addEventListener('DOMContentLoaded',function(){co.setTimeout(b,3e3);
co._Preamp.docReady=co._Fuse.docReady=!0});var z=h.createElement('script');
z.async=1;z.src='https://beam.edx.org/cohesion/cohesion-latest.min.js';
z.onerror=function(){var ce='error',f='function';for(var o of co[e].q||[])o[0]===ce&&typeof o[1]==f&&o[1]();co[e]=function(n,cb){n===ce&&typeof cb==f&&cb()};b()};
h.head.appendChild(z);}
(window,document,'cohesion','preamp','fuse','tagular',{
tagular: {
apiHost: 'https://beam.edx.org/v2/t',
writeKey: '<%= htmlWebpackPlugin.options.cohesionConfig.tagularWriteKey %>',
sourceKey: '<%= htmlWebpackPlugin.cohesionConfig.tagularSourceKey %>',
cookieDomain: '<%= htmlWebpackPlugin.cohesionConfig.tagularCookieDomain %>',
domainWhitelist: <%= htmlWebpackPlugin.cohesionConfig.tagularDomainWhitelist %>,
apiVersion: 'v2/t',
multiparty: true,
taggy: { enabled: true },
}
})`}
</script>
<% } %>
</head>
<body>
<div id="root">
Expand Down
27 changes: 27 additions & 0 deletions src/cohesion/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export const ElementType = {
Link: 'LINK',
Entry: 'ENTRY',
Button: 'BUTTON',
};

export const PaymentTitle = 'Payment | edX';

export const EventMap = {
ProductClicked: 'redventures.ecommerce.v1.ProductClicked',
ProductLoaded: 'redventures.ecommerce.v1.ProductLoaded',
ProductViewed: 'redventures.ecommerce.v1.ProductViewed',
ElementClicked: 'redventures.usertracking.v3.ElementClicked',
ElementViewed: 'redventures.usertracking.v3.ElementViewed',
FieldSelected: 'redventures.usertracking.v3.FieldSelected',
FormSubmitted: 'redventures.usertracking.v3.FormSubmitted',
FormViewed: 'redventures.usertracking.v3.FormViewed',
};

export const IS_FULLY_SHOWN_THRESHOLD_OR_MARGIN = 1.0;
export const IS_SINGLE_PX_SHOWN_THRESHOLD_OR_MARGIN = 0.0;
export const DOCUMENT_ROOT_NODE = null;

export const defaultOptions = {
threshold: IS_FULLY_SHOWN_THRESHOLD_OR_MARGIN,
root: DOCUMENT_ROOT_NODE,
};
65 changes: 65 additions & 0 deletions src/cohesion/dataTranslationMatrices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const DEFAULT_LOOKUP_VALUE = '*';

// enums cause noo-shadow errors in prospectus
export const BaseTagularVariant = {
Courses: 'courses',
};

const TagularVariant = {
// Include base/x-ref things
...BaseTagularVariant,
// Supplied from Data Team
XSeries: 'certificates-xseries',
ProfessionalCertificate: 'certificates-prof-cert',
ExecEd: 'certificates-exec-ed',
MicroBachelors: 'certificates-micro-bachelors',
MicroMasters: 'certificates-micro-masters',
Bachelors: 'degrees-bachelors',
Masters: 'degrees-masters',
Doctorate: 'degrees-doctorate',
Bootcamps: 'bootcamps',
// Not Final
Certificates: 'degrees-certificates',
Licenses: 'degrees-licenses',
// Special Values
All: 'all-products/mixed',
Unknown: BaseTagularVariant.Courses,
};

const typeToVariant = {
[DEFAULT_LOOKUP_VALUE]: TagularVariant.Unknown, // missing value
// type_attr Slugs
bachelors: TagularVariant.Bachelors,
masters: TagularVariant.Masters,
microbachelors: TagularVariant.MicroBachelors,
micromasters: TagularVariant.MicroMasters,
'professional-certificate': TagularVariant.ProfessionalCertificate,
// 'professional-program-wl': TagularVariant.Unknown, Whitelabel Programs are no more.
xseries: TagularVariant.XSeries,
doctorate: TagularVariant.Doctorate,
license: TagularVariant.Licenses,
certificate: TagularVariant.Certificates,
// type_attr Display Names
Bachelors: TagularVariant.Bachelors,
Masters: TagularVariant.Masters,
MicroBachelors: TagularVariant.MicroBachelors,
MicroMasters: TagularVariant.MicroMasters,
'Professional Certificate': TagularVariant.ProfessionalCertificate,
// 'Professional Program': TagularVariant.Unknown, Whitelabel Programs are no more.
XSeries: TagularVariant.XSeries,
Doctorate: TagularVariant.Doctorate,
License: TagularVariant.Licenses,
Certificate: TagularVariant.Certificates,
// course_type Slugs
'executive-education-2u': TagularVariant.ExecEd,
'bootcamp-2u': TagularVariant.Bootcamps,
// Skipped as it was a note in the doc: 'Anything else': TagularVariant.Courses,
// course_type Display Name
'Executive Education': TagularVariant.ExecEd,
'Boot Camp': TagularVariant.Bootcamps,
Course: TagularVariant.Courses,
};

export default function translateVariant(x) {
return typeToVariant[x] || typeToVariant[DEFAULT_LOOKUP_VALUE];
}
77 changes: 77 additions & 0 deletions src/cohesion/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Cookies from 'universal-cookie';
import { v4 as uuidv4 } from 'uuid';
import { EventMap } from './constants';

/**
* Fetch or Create a Tagular CorrelationID. This also refreshes the cookie's expiry.
*/
export const getCorrelationID = () => {
const COOKIE_NAME = 'tglr_correlation_id';
const PARAM_NAME = 'correlationId';

function getQueryParameter(name) {
const params = new URLSearchParams(window.location.search);

return params.get(name);
}

let paramId = getQueryParameter(PARAM_NAME) || new Cookies().get(COOKIE_NAME);

if (!paramId) {
paramId = uuidv4();
}

const expirationDate = new Date();
expirationDate.setMinutes(expirationDate.getMinutes() + 30); // 30 mins expiration from now
new Cookies().set(COOKIE_NAME, paramId, { expires: expirationDate });

return paramId;
};

/**
* Submit ('beam') an event via Tagular to Make.
* @param eventName Schema Name of the Event
* @param eventData The data required by the schema
*/
export const tagularEvent = (eventName, eventData) => {
// if tagular is available, try sending given event with event data
if (typeof window !== 'undefined' && window.tagular) {
try {
window.tagular('beam', eventName, {
'@type': EventMap[eventName],
...eventData,
});
} catch (error) {
// eslint-disable-next-line no-console
console.warn(`Tagular event ${eventName} not sent.`, error);
}
} else {
// eslint-disable-next-line no-console
console.warn('Tagular not available on page.');
}
};

export function pageTrackingObject(pageType) {
return {
title: window.document.title,
url: window.location.href,
pageType,
referrer: window.document.referrer,
};
}

/**
* Make Near Slugs from Plain Strings for ease of eventing.
* @example
* "Computer Science" => "computer-science"
* "Humanities & Arts" => "humanities-&-arts"
* "Someone added a space " => "someone-added-a-space"
*
* @param x Input String
*/
export function hyphenateForTagular(x) {
return x
.trim()
.toLowerCase()
.replace(/[^\w&]/g, '-');
}
21 changes: 21 additions & 0 deletions src/feedback/AlertList.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ jest.mock('@edx/frontend-platform/logging', () => ({
logError: jest.fn(),
}));

// Mock IntersectionObserver
global.IntersectionObserver = class {
constructor(callback) {
this.callback = callback;
this.observedElements = new Set();
}

observe(element) {
this.callback([{ isIntersecting: true }]);
this.observedElements.add(element);
}

unobserve(element) {
this.observedElements.delete(element);
}

disconnect() {
this.observedElements.clear();
}
};

describe('AlertList', () => {
let store;

Expand Down
Loading
Loading