diff --git a/.circleci/config.yml b/.circleci/config.yml index 23019f1e68..c8c19b8760 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -188,7 +188,6 @@ workflows: filters: branches: only: - - hot-fix-hall-of-fame - develop # Production builds are exectuted # when PR is merged to the master diff --git a/__tests__/shared/components/Header/__snapshots__/index.jsx.snap b/__tests__/shared/components/Header/__snapshots__/index.jsx.snap index 03831a507a..8f8fa0afc8 100644 --- a/__tests__/shared/components/Header/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/Header/__snapshots__/index.jsx.snap @@ -182,10 +182,26 @@ exports[`Default render 1`] = ` "title": "Switch to BUSINESS", } } + tracking={ + Object { + "default": undefined, + "event": [Function], + "init": [Function], + "pageView": [Function], + } + } /> } setOpenMore={[Function]} theme="light" + tracking={ + Object { + "default": undefined, + "event": [Function], + "init": [Function], + "pageView": [Function], + } + } /> `; \ No newline at end of file diff --git a/config/default.js b/config/default.js index 87e727e9ba..7de679aec0 100644 --- a/config/default.js +++ b/config/default.js @@ -96,6 +96,9 @@ module.exports = { SWIFT_PROGRAM_ID: 3445, + /* Google Analytics tracking ID */ + GOOGLE_ANALYTICS_ID: 'UA-161803421-1', + /* Various URLs. Most of them lead to different segments of Topcoder * platform. */ URL: { diff --git a/config/production.js b/config/production.js index cf3c4a06c3..4b23f3f9a5 100644 --- a/config/production.js +++ b/config/production.js @@ -17,6 +17,7 @@ module.exports = { }, LOG_ENTRIES_TOKEN: '', SERVER_API_KEY: 'aa9ccf36-3936-450c-9983-097ddba51bef', + GOOGLE_ANALYTICS_ID: 'UA-6340959-1', URL: { ARENA: 'https://arena.topcoder.com', APP: 'https://community-app.topcoder.com', diff --git a/package.json b/package.json index dfc7e769a1..f575c2c4d2 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test": "npm run lint && npm run --runInBand jest", "commitlint": "commitlint -E HUSKY_GIT_PARAMS", "release:changelog": "npm run conventional-changelog -- -p angular -i CHANGELOG.md -s", - "postinstall": "rimraf node_modules/navigation-component/node_modules/topcoder-react-utils && rimraf node_modules/navigation-component/node_modules/topcoder-react-lib && rimraf node_modules/topcoder-react-ui-kit/node_modules/topcoder-react-utils" + "postinstall": "rimraf node_modules/navigation-component/node_modules/topcoder-react-utils && rimraf node_modules/topcoder-react-ui-kit/node_modules/topcoder-react-utils" }, "repository": { "type": "git", @@ -62,6 +62,7 @@ "filestack-react": "^2.0.0", "flag-icon-css": "^3.3.0", "focus-trap-react": "^6.0.0", + "react-ga": "^2.7.0", "helmet": "^3.12.1", "highlight.js": "^9.18.1", "html-to-text": "^5.1.1", @@ -133,7 +134,7 @@ "tc-accounts": "git+https://github.com/appirio-tech/accounts-app.git#dev", "tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3", "tc-ui": "^1.0.12", - "topcoder-react-lib": "v0.17.0", + "topcoder-react-lib": "v0.17.1", "topcoder-react-ui-kit": "^1.0.11", "topcoder-react-utils": "0.7.8", "turndown": "^4.0.2", diff --git a/src/shared/actions/index.js b/src/shared/actions/index.js index c8ef70d154..4b9dea938f 100644 --- a/src/shared/actions/index.js +++ b/src/shared/actions/index.js @@ -6,6 +6,9 @@ import { actions } from 'topcoder-react-lib'; import pageActions from './page'; +import * as tracking from './tracking'; + +export { tracking }; export default { ...pageActions, diff --git a/src/shared/actions/tracking.js b/src/shared/actions/tracking.js new file mode 100644 index 0000000000..dfac3113d9 --- /dev/null +++ b/src/shared/actions/tracking.js @@ -0,0 +1,46 @@ +/* global window */ + +import ReactGA from 'react-ga'; +import { config } from 'topcoder-react-utils'; + +const TRACKING_NAME = 'tracking'; + +/** + * init - Init Google Analytics tracking + * @param {string} userId + */ +export const init = (userId) => { + ReactGA.initialize([{ + trackingId: config.GOOGLE_ANALYTICS_ID, + gaOptions: { + name: TRACKING_NAME, + userId, + }, + }], { + alwaysSendToDefaultTracker: false, + }); +}; + +/** + * pageView - Track page view + */ +export const pageView = () => { + ReactGA.pageview(window.location.pathname + + window.location.search, [TRACKING_NAME]); +}; + +/** + * event - Add custom tracking event. + * @param {string} category + * @param {string} action + * @param {string} label + */ +export const event = (category, action, label) => { + ReactGA.event({ + category, + action, + label, + }, [TRACKING_NAME]); +}; + +export default undefined; diff --git a/src/shared/components/Header/index.jsx b/src/shared/components/Header/index.jsx index 87d1c14c29..28f85b0051 100644 --- a/src/shared/components/Header/index.jsx +++ b/src/shared/components/Header/index.jsx @@ -2,8 +2,8 @@ import _ from 'lodash'; import React, { useState, useEffect } from 'react'; import PT from 'prop-types'; import { config } from 'topcoder-react-utils'; -import { tracking } from 'topcoder-react-lib'; import Logo from 'assets/images/tc-logo.svg'; +import { tracking } from '../../actions'; let TopNavRef; let LoginNavRef; @@ -54,23 +54,18 @@ const Header = ({ }, []); /* - * Reload notificaitons if token was changed - * This prevent to use expired token in API call - */ - if (auth) { - useEffect(() => { - loadNotifications(auth.tokenV3); - }, [auth.tokenV3]); - } - - /* - * Init Google Analytics + * Load Notifications and Init Google Analytics */ - if (auth && auth.user) { - useEffect(() => { - tracking.init(auth.user.handle); - }, [auth.user.handle]); - } + useEffect(() => { + if (auth) { + if (auth.tokenV3) { + loadNotifications(auth.tokenV3); + } + if (auth.user) { + tracking.init(auth.user.handle); + } + } + }, []); if (TopNavRef) { return ( @@ -95,6 +90,7 @@ const Header = ({ auth={auth} profile={normalizedProfile} authURLs={config.HEADER_AUTH_URLS} + tracking={tracking} /> )} logo={} @@ -106,6 +102,7 @@ const Header = ({ setOpenMore={handleChangeOpenMore} loggedIn={!_.isEmpty(profile)} profileHandle={profile ? profile.handle : ''} + tracking={tracking} /> ); diff --git a/src/shared/components/Notifications/TabsPanel/index.jsx b/src/shared/components/Notifications/TabsPanel/index.jsx index 13d72e384f..6bb6f1d820 100644 --- a/src/shared/components/Notifications/TabsPanel/index.jsx +++ b/src/shared/components/Notifications/TabsPanel/index.jsx @@ -1,7 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import cn from 'classnames'; -import { tracking } from 'topcoder-react-lib'; import styles from './style.scss'; @@ -21,7 +20,7 @@ export default class TabsPanel extends React.Component { render() { - const { changeTab } = this.props; + const { changeTab, tracking } = this.props; const { tab } = this.state; return (
@@ -106,4 +105,5 @@ export default class TabsPanel extends React.Component { TabsPanel.propTypes = { changeTab: PropTypes.func.isRequired, + tracking: PropTypes.shape().isRequired, }; diff --git a/src/shared/components/Notifications/index.jsx b/src/shared/components/Notifications/index.jsx index 358380c760..f2f4dc03ae 100644 --- a/src/shared/components/Notifications/index.jsx +++ b/src/shared/components/Notifications/index.jsx @@ -4,8 +4,8 @@ import cn from 'classnames'; import _ from 'lodash'; import moment from 'moment'; import { Link } from 'topcoder-react-utils'; -import { tracking } from 'topcoder-react-lib'; import IconArrow from 'assets/images/notifications/arrow.svg'; +import { tracking } from '../../actions'; import styles from './style.scss'; import TabsPanel from './TabsPanel'; @@ -184,6 +184,7 @@ export default class NotificationList extends React.Component {
this.setState({ activeTab: tab })} + tracking={tracking} />