feat: [UEPR-177] send user properties and feedback submition data to google analytics

This commit is contained in:
MiroslavDionisiev 2025-03-28 09:35:08 +02:00
parent 1dd87fdec6
commit e90aa45e37
11 changed files with 124 additions and 37 deletions

View file

@ -7,6 +7,7 @@ import {
} from './qualitative_feedback_data.js';
import {QualitativeFeedback} from './qualitative_feedback.jsx';
import {connect} from 'react-redux';
import {triggerAnalyticsEvent} from '../../../lib/google-analytics-utils.js';
const DebuggingFeedback = ({hideFeedback, isOpen}) => {
const onHideFeedback = useCallback(
@ -14,11 +15,22 @@ const DebuggingFeedback = ({hideFeedback, isOpen}) => {
[hideFeedback]
);
const sendGAEvent = useCallback(
data =>
triggerAnalyticsEvent({
event: 'qualitative-feedback',
feedbackName: 'Debugging Feedback',
feedbackResponse: data
}),
[]
);
return (
<QualitativeFeedback
feedbackData={QUALITATIVE_FEEDBACK_DATA.debugging}
hideFeedback={onHideFeedback}
isOpen={isOpen}
sendGAEvent={sendGAEvent}
/>
);
};

View file

@ -7,6 +7,7 @@ import {
} from './qualitative_feedback_data.js';
import {QualitativeFeedback} from './qualitative_feedback.jsx';
import {connect} from 'react-redux';
import {triggerAnalyticsEvent} from '../../../lib/google-analytics-utils.js';
const IdeasGeneratorFeedback = ({hideFeedback, isOpen}) => {
const onHideFeedback = useCallback(
@ -14,11 +15,22 @@ const IdeasGeneratorFeedback = ({hideFeedback, isOpen}) => {
[hideFeedback]
);
const sendGAEvent = useCallback(
data =>
triggerAnalyticsEvent({
event: 'qualitative-feedback',
feedbackName: 'Ideas Generator Feedback',
feedbackResponse: data
}),
[]
);
return (
<QualitativeFeedback
feedbackData={QUALITATIVE_FEEDBACK_DATA.ideasGenerator}
hideFeedback={onHideFeedback}
isOpen={isOpen}
sendGAEvent={sendGAEvent}
/>
);
};

View file

@ -45,7 +45,7 @@ FeedbackOption.propTypes = {
value: PropTypes.string
};
export const QualitativeFeedback = ({feedbackData, hideFeedback, isOpen}) => {
export const QualitativeFeedback = ({feedbackData, hideFeedback, isOpen, sendGAEvent}) => {
const [displayModal, setDisplayModal] = useState(false);
const [_, setFilledFeedback] = useLocalStorage(
feedbackData.questionId,
@ -54,6 +54,7 @@ export const QualitativeFeedback = ({feedbackData, hideFeedback, isOpen}) => {
const intl = useIntl();
const onClose = useCallback(() => {
sendGAEvent('closed');
setFilledFeedback(true);
hideFeedback();
setDisplayModal(false);
@ -63,6 +64,7 @@ export const QualitativeFeedback = ({feedbackData, hideFeedback, isOpen}) => {
const onSubmit = useCallback(
formData => {
if (formData.feedback) {
sendGAEvent(formData.feedback);
setFilledFeedback(true);
hideFeedback();
setDisplayModal(false);
@ -144,5 +146,6 @@ QualitativeFeedback.propTypes = {
).isRequired
}).isRequired,
hideFeedback: PropTypes.func,
isOpen: PropTypes.bool
isOpen: PropTypes.bool,
sendGAEvent: PropTypes.func
};

View file

@ -7,25 +7,39 @@ import {
} from './qualitative_feedback_data.js';
import {QualitativeFeedback} from './qualitative_feedback.jsx';
import {connect} from 'react-redux';
import {triggerAnalyticsEvent} from '../../../lib/google-analytics-utils.js';
const StarterProjectsFeedback = ({hideFeedback, isOpen}) => {
const StarterProjectsFeedback = ({hideFeedback, isOpen, projectName}) => {
const onHideFeedback = useCallback(
() => hideFeedback(QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects),
[hideFeedback]
);
const sendGAEvent = useCallback(
data =>
triggerAnalyticsEvent({
event: 'qualitative-feedback',
feedbackName: 'Starter Projects Feedback',
projectName: projectName,
feedbackResponse: data
}),
[]
);
return (
<QualitativeFeedback
feedbackData={QUALITATIVE_FEEDBACK_DATA.starterProjects}
hideFeedback={onHideFeedback}
isOpen={isOpen}
sendGAEvent={sendGAEvent}
/>
);
};
StarterProjectsFeedback.propTypes = {
isOpen: PropTypes.bool,
hideFeedback: PropTypes.func
hideFeedback: PropTypes.func,
projectName: PropTypes.string
};
const mapDispatchToProps = dispatch => ({

View file

@ -7,6 +7,7 @@ import {
} from './qualitative_feedback_data.js';
import {QualitativeFeedback} from './qualitative_feedback.jsx';
import {connect} from 'react-redux';
import {triggerAnalyticsEvent} from '../../../lib/google-analytics-utils.js';
const TutorialsFeedback = ({hideFeedback, isOpen}) => {
const onHideFeedback = useCallback(
@ -14,11 +15,22 @@ const TutorialsFeedback = ({hideFeedback, isOpen}) => {
[hideFeedback]
);
const sendGAEvent = useCallback(
data =>
triggerAnalyticsEvent({
event: 'qualitative-feedback',
feedbackName: 'Tutorials Feedback',
feedbackResponse: data
}),
[]
);
return (
<QualitativeFeedback
feedbackData={QUALITATIVE_FEEDBACK_DATA.tutorials}
hideFeedback={onHideFeedback}
isOpen={isOpen}
sendGAEvent={sendGAEvent}
/>
);
};

View file

@ -1,4 +1,6 @@
const {isDateInRange, isUserEligible} = require('./user-eligibility');
import {sendUserProperties} from './google-analytics-utils';
const {isDateInRange, isUserEligible, getUserRoles} = require('./user-eligibility');
const localStorageAvailable =
'localStorage' in window && window.localStorage !== null;
@ -51,3 +53,11 @@ export const shouldDisplayFeedbackWidget = (
isUserEligibleForFeedback(user, permissions, feedbackQuestionId, feedbackUserRate) &&
isFeedbackDisplayed(feedbacksDisplayed)
);
export const sendUserPropertiesForFeedback = (user, permissions, shouldDisplayFeedback) => {
sendUserProperties(
user,
shouldDisplayFeedback,
{userRoles: getUserRoles(permissions)}
);
};

View file

@ -8,10 +8,10 @@ export const triggerAnalyticsEvent = eventVaribles => {
});
};
export const sendUserProperties = (user, permissions, eligibilityCheck, userProperties) => {
export const sendUserProperties = (user, eligibilityCheck, userProperties) => {
window.dataLayer = window.dataLayer || [];
if (!eligibilityCheck(user, permissions)) {
if (!eligibilityCheck) {
const nulledUserProperties = Object.keys(userProperties).reduce(
(acc, current) => {
acc[current] = null;
@ -21,7 +21,7 @@ export const sendUserProperties = (user, permissions, eligibilityCheck, userProp
);
window.dataLayer.push({
testGroup: null,
gender: null,
ageGroup: null,
...nulledUserProperties
});

View file

@ -49,8 +49,7 @@ export const shouldDisplayOnboarding = (user, permissions) =>
export const sendUserPropertiesForOnboarding = (user, permissions) => {
sendUserProperties(
user,
permissions,
isUserEligibleForOnboarding,
isUserEligibleForOnboarding(user, permissions),
{testGroup: onboardingTestGroup(user)}
);
};

View file

@ -36,6 +36,15 @@ export const calculateAgeGroup = (birthYear, birthMonth) => {
return '[17+]';
};
export const getUserRoles = permissions => {
const permissionsToExclude = ['social', 'mute_status'];
return Object.keys(permissions)
.filter(permissionKey => !permissionsToExclude.includes(permissionKey))
.filter(userRole => permissions[userRole])
.join(',');
};
export const isUserEligible = (user, permissions, callback = () => true) =>
Object.keys(user).length !== 0 &&
Object.keys(permissions).length !== 0 &&

View file

@ -30,7 +30,7 @@ const {useRef} = require('react');
const {
QUALITATIVE_FEEDBACK_QUESTION_ID
} = require('../../components/modal/feedback/qualitative_feedback_data.js');
const {shouldDisplayFeedbackWidget} = require('../../lib/feedback.js');
const {shouldDisplayFeedbackWidget, sendUserPropertiesForFeedback} = require('../../lib/feedback.js');
require('./ideas.scss');
@ -164,17 +164,21 @@ const Ideas = ({
addGreenFlagClickListeners(iframe);
}
};
const shoulDisplayFeedback = shouldDisplayFeedbackWidget(
user,
permissions,
QUALITATIVE_FEEDBACK_QUESTION_ID.ideasGenerator,
process.env.QUALITATIVE_FEEDBACK_IDEAS_GENERATOR_USER_RATE,
feedback
);
if (
iframe &&
shouldDisplayFeedbackWidget(
if (iframe && shoulDisplayFeedback) {
sendUserPropertiesForFeedback(
user,
permissions,
QUALITATIVE_FEEDBACK_QUESTION_ID.ideasGenerator,
process.env.QUALITATIVE_FEEDBACK_IDEAS_GENERATOR_USER_RATE,
feedback
)
) {
shoulDisplayFeedback
);
iframe.addEventListener('load', onIframeLoad);
}
@ -193,7 +197,7 @@ const Ideas = ({
<div className="banner-wrapper">
<iframe
ref={iframeRef}
src={`${process.env.IDEAS_GENERATOR_SOURCE}/embed`}
src={`http://localhost:8333/projects/9999923/embed`}
width="485"
height="402"
allowfullscreen

View file

@ -48,7 +48,7 @@ const {sendUserPropertiesForOnboarding, shouldDisplayOnboarding} = require('../.
const {triggerAnalyticsEvent} = require('../../lib/google-analytics-utils.js');
const {StarterProjectsFeedback} = require('../../components/modal/feedback/starter-projects-feedback.jsx');
const {QUALITATIVE_FEEDBACK_QUESTION_ID} = require('../../components/modal/feedback/qualitative_feedback_data.js');
const {shouldDisplayFeedbackWidget} = require('../../lib/feedback.js');
const {shouldDisplayFeedbackWidget, sendUserPropertiesForFeedback} = require('../../lib/feedback.js');
const {displayQualitativeFeedback} = require('../../redux/qualitative-feedback.js');
const {DebuggingFeedback} = require('../../components/modal/feedback/debugging-feedback.jsx');
const {TutorialsFeedback} = require('../../components/modal/feedback/tutorials-feedback.jsx');
@ -73,15 +73,20 @@ const IntlGUIWithProjectHandler = ({...props}) => {
}, [props.projectId, prevProjectId, props.user, props.permissions]);
const displayGuiFeedback = useCallback((feedbackQuestionId, feedbackUserRate) => {
if (
shouldDisplayFeedbackWidget(
const shoulDisplayFeedback = shouldDisplayFeedbackWidget(
props.user,
props.permissions,
feedbackQuestionId,
feedbackUserRate,
props.feedback
);
if (shoulDisplayFeedback) {
sendUserPropertiesForFeedback(
props.user,
props.permissions,
feedbackQuestionId,
feedbackUserRate,
props.feedback
)
) {
shoulDisplayFeedback
);
props.displayFeedback(feedbackQuestionId);
}
}, [props.user, props.permissions, props.feedback, props.displayFeedback]);
@ -300,17 +305,22 @@ class Preview extends React.Component {
sendUserPropertiesForOnboarding(this.props.user, this.props.permissions);
const fromStarterProjectsPage = queryString.parse(location.search).fromStarterProjectsPage === 'true';
if (
fromStarterProjectsPage &&
shouldDisplayFeedbackWidget(
const shoulDisplayFeedback = shouldDisplayFeedbackWidget(
this.props.user,
this.props.permissions,
QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects,
process.env.QUALITATIVE_FEEDBACK_STARTER_PROJECTS_USER_RATE,
this.props.feedback
);
if (fromStarterProjectsPage && shoulDisplayFeedback) {
sendUserPropertiesForFeedback(
this.props.user,
this.props.permissions,
QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects,
process.env.QUALITATIVE_FEEDBACK_STARTER_PROJECTS_USER_RATE,
this.props.feedback
)
) {
this.props.displayFeedback(QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects);
shoulDisplayFeedback
);
this.props.displayFeedback(
QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects
);
}
}
}
@ -876,6 +886,7 @@ class Preview extends React.Component {
>
<StarterProjectsFeedback
isOpen={this.props.feedback[QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects]}
projectName={this.props.projectInfo.title}
/>
<PreviewPresentation
addToStudioOpen={this.state.addToStudioOpen}
@ -978,6 +989,7 @@ class Preview extends React.Component {
<>
<StarterProjectsFeedback
isOpen={this.props.feedback[QUALITATIVE_FEEDBACK_QUESTION_ID.starterProjects]}
projectName={this.props.projectInfo.title}
/>
<IntlGUIWithProjectHandler
assetHost={this.props.assetHost}