Unverified Commit 7da4c54c authored by Marcos Iglesias's avatar Marcos Iglesias Committed by GitHub

feat: Adds page view tracking with the new analytics approach (#838)

* Listens to history from the routes component
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>

* Adds UI reducer, pageView action and logic to track page views using analytics
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>

* Fixing linting error
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>

* Updating betterer results
Signed-off-by: 's avatarMarcos Iglesias <miglesiasvalle@lyft.com>
parent b2d5e8ff
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import { expectSaga, testSaga } from 'redux-saga-test-plan';
import * as matchers from 'redux-saga-test-plan/matchers';
import { throwError } from 'redux-saga-test-plan/providers';
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import { Middleware } from 'redux';
import { RootState } from '../rootReducer';
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import { combineReducers } from 'redux';
import dashboard, { DashboardReducerState } from 'ducks/dashboard/reducer';
......@@ -13,6 +16,7 @@ import tableMetadata, {
import lastIndexed, { LastIndexedReducerState } from './lastIndexed/reducer';
import tags, { TagsReducerState } from './tags/reducer';
import user, { UserReducerState } from './user/reducer';
import ui, { UIReducerState } from './ui';
import bookmarks, { BookmarkReducerState } from './bookmark/reducer';
import notification, { NotificationReducerState } from './notification/reducer';
import issue, { IssueReducerState } from './issue/reducer';
......@@ -30,6 +34,7 @@ export interface GlobalState {
lastIndexed: LastIndexedReducerState;
tags: TagsReducerState;
user: UserReducerState;
ui: UIReducerState;
}
const rootReducer = combineReducers<GlobalState>({
......@@ -45,6 +50,7 @@ const rootReducer = combineReducers<GlobalState>({
lastIndexed,
tags,
user,
ui,
});
export default rootReducer;
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import reducer, { pageViewed, pageViewActionType, UIReducerState } from '.';
describe('UI ducks', () => {
describe('actions', () => {
describe('pageViewed', () => {
it('returns the action to track a page view', () => {
const expected = '/testURL';
const action = pageViewed(expected);
const { type, meta } = action;
expect(type).toEqual(pageViewActionType);
expect(meta.analytics.name).toEqual(pageViewActionType);
expect(meta.analytics.payload.category).toEqual('pageView');
expect(meta.analytics.payload.label).toEqual(expected);
});
});
});
describe('reducer', () => {
const testState: UIReducerState = {};
describe('when pageViewed is triggered', () => {
it('should return the existing state', () => {
const expected = testState;
const actual = reducer(testState, pageViewed('/testURL'));
expect(actual).toEqual(expected);
});
});
});
});
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
export const pageViewActionType = 'analytics/pageView';
// Actions
export function pageViewed(path: string) {
return {
type: pageViewActionType,
meta: {
analytics: {
name: pageViewActionType,
payload: {
category: 'pageView',
label: `${path}`,
},
},
},
};
}
// Reducer
export interface UIReducerState {}
export const initialState: UIReducerState = {};
export default function reducer(
state: UIReducerState = initialState,
action
): UIReducerState {
switch (action.type) {
case pageViewActionType: {
return state;
}
default:
return state;
}
}
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import { GlobalState } from 'ducks/rootReducer';
import { ResourceType, SendingState } from 'interfaces';
......@@ -253,6 +256,7 @@ const globalState: GlobalState = {
},
},
},
ui: {},
};
export default globalState;
......@@ -16,6 +16,10 @@ import { analyticsMiddleware } from 'ducks/middlewares';
import { BrowserHistory } from 'utils/navigationUtils';
import { pageViewed } from 'ducks/ui';
import rootReducer from 'ducks/rootReducer';
import rootSaga from 'ducks/rootSaga';
import DashboardPage from './pages/DashboardPage';
import AnnouncementPage from './pages/AnnouncementPage';
import BrowsePage from './pages/BrowsePage';
......@@ -29,9 +33,6 @@ import Preloader from './components/Preloader';
import Footer from './features/Footer';
import NavBar from './features/NavBar';
import rootReducer from './ducks/rootReducer';
import rootSaga from './ducks/rootSaga';
const sagaMiddleware = createSagaMiddleware();
const createStoreWithMiddleware = applyMiddleware(
ReduxPromise,
......@@ -42,26 +43,45 @@ const store = createStoreWithMiddleware(rootReducer);
sagaMiddleware.run(rootSaga);
const Routes: React.FC = () => {
const history = BrowserHistory;
function trackPageView() {
store.dispatch(pageViewed(window.location.pathname));
}
React.useEffect(() => {
trackPageView(); // To track the first pageview upon load
history.listen(trackPageView); // To track the subsequent pageviews
}, [history]);
return (
<>
<Route component={NavBar} />
<Switch>
<Route path="/announcements" component={AnnouncementPage} />
<Route path="/browse" component={BrowsePage} />
<Route path="/dashboard/:uri" component={DashboardPage} />
<Route path="/search" component={SearchPage} />
<Route
path="/table_detail/:cluster/:database/:schema/:table"
component={TableDetail}
/>
<Route path="/user/:userId" component={ProfilePage} />
<Route path="/404" component={NotFoundPage} />
<Route path="/" component={HomePage} />
</Switch>
</>
);
};
ReactDOM.render(
<DocumentTitle title="Amundsen - Data Discovery Portal">
<Provider store={store}>
<Router history={BrowserHistory}>
<div id="main">
<Preloader />
<Route component={NavBar} />
<Switch>
<Route path="/announcements" component={AnnouncementPage} />
<Route path="/browse" component={BrowsePage} />
<Route path="/dashboard/:uri" component={DashboardPage} />
<Route path="/search" component={SearchPage} />
<Route
path="/table_detail/:cluster/:database/:schema/:table"
component={TableDetail}
/>
<Route path="/user/:userId" component={ProfilePage} />
<Route path="/404" component={NotFoundPage} />
<Route path="/" component={HomePage} />
</Switch>
<Routes />
<Footer />
</div>
</Router>
......
// Copyright Contributors to the Amundsen project.
// SPDX-License-Identifier: Apache-2.0
import Analytics, { AnalyticsInstance } from 'analytics';
import * as ConfigUtils from 'config/config-utils';
import { pageViewActionType } from 'ducks/ui';
let sharedAnalyticsInstance;
......@@ -20,8 +24,17 @@ export const analyticsInstance = (): AnalyticsInstance => {
return sharedAnalyticsInstance;
};
export const trackEvent = (eventName: string, properties: Map<string, any>) => {
export const trackEvent = (
eventName: string,
properties: Record<string, any>
) => {
const analytics = analyticsInstance();
analytics.track(eventName, properties);
if (eventName === pageViewActionType) {
analytics.page({
url: properties.label,
});
} else {
analytics.track(eventName, properties);
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment