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
......@@ -763,9 +763,9 @@ exports[`eslint`] = {
[81, 35, 4, "\'data\' is defined but never used.", "2087377941"],
[121, 61, 4, "\'data\' is defined but never used.", "2087377941"]
],
"js/ducks/bookmark/index.spec.ts:1070259074": [
[96, 14, 7, "\'payload\' is assigned a value but never used.", "2531329355"],
[116, 14, 7, "\'payload\' is assigned a value but never used.", "2531329355"]
"js/ducks/bookmark/index.spec.ts:237544541": [
[99, 14, 7, "\'payload\' is assigned a value but never used.", "2531329355"],
[119, 14, 7, "\'payload\' is assigned a value but never used.", "2531329355"]
],
"js/ducks/bookmark/sagas.ts:2649953115": [
[20, 2, 19, "\'GetBookmarksRequest\' is defined but never used.", "2458762509"],
......@@ -875,8 +875,8 @@ exports[`eslint`] = {
[4, 2, 9, "Property name \`target_id\` must match one of the following formats: camelCase", "1702172486"],
[5, 2, 11, "Property name \`target_type\` must match one of the following formats: camelCase", "2535870899"]
],
"js/ducks/middlewares/analyticsMiddleware.ts:504068368": [
[8, 7, 8, "\'getState\' is defined but never used.", "1919118020"]
"js/ducks/middlewares/analyticsMiddleware.ts:854383951": [
[11, 7, 8, "\'getState\' is defined but never used.", "1919118020"]
],
"js/ducks/notification/api/tests/index.spec.ts:3130281759": [
[13, 6, 13, "Property name \`resource_name\` must match one of the following formats: camelCase", "2441095223"],
......@@ -1529,70 +1529,70 @@ exports[`eslint`] = {
"js/features/NavBar/index.tsx:2635832531": [
[69, 8, 19, "Must use destructuring props assignment", "1779396464"]
],
"js/fixtures/globalState.ts:2008341805": [
[15, 8, 12, "Property name \`html_content\` must match one of the following formats: camelCase", "574671502"],
[20, 8, 12, "Property name \`html_content\` must match one of the following formats: camelCase", "574671502"],
[40, 10, 10, "Property name \`group_name\` must match one of the following formats: camelCase", "2646960194"],
[41, 10, 9, "Property name \`group_url\` must match one of the following formats: camelCase", "991267566"],
[49, 10, 29, "Property name \`last_successful_run_timestamp\` must match one of the following formats: camelCase", "1157138603"],
[101, 4, 11, "Property name \`search_term\` must match one of the following formats: camelCase", "1115328666"],
[105, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[107, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[110, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[117, 10, 22, "Property name \`last_updated_timestamp\` must match one of the following formats: camelCase", "1908543892"],
[123, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[126, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[128, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[133, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[135, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[138, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[140, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[143, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[145, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[162, 6, 11, "Property name \`is_editable\` must match one of the following formats: camelCase", "389228086"],
[163, 6, 7, "Property name \`is_view\` must match one of the following formats: camelCase", "2715417645"],
[165, 6, 22, "Property name \`last_updated_timestamp\` must match one of the following formats: camelCase", "1908543892"],
[169, 6, 12, "Property name \`table_writer\` must match one of the following formats: camelCase", "1979434539"],
[169, 22, 15, "Property name \`application_url\` must match one of the following formats: camelCase", "1067313867"],
[170, 19, 14, "Property name \`is_partitioned\` must match one of the following formats: camelCase", "361132355"],
[171, 6, 13, "Property name \`table_readers\` must match one of the following formats: camelCase", "3636171154"],
[172, 28, 11, "Property name \`source_type\` must match one of the following formats: camelCase", "2336271487"],
[173, 6, 16, "Property name \`resource_reports\` must match one of the following formats: camelCase", "3614191341"],
[175, 6, 25, "Property name \`programmatic_descriptions\` must match one of the following formats: camelCase", "3262748393"],
[188, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[189, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[192, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[193, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[196, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[197, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[200, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[201, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[212, 6, 12, "Property name \`display_name\` must match one of the following formats: camelCase", "2661030023"],
[214, 6, 13, "Property name \`employee_type\` must match one of the following formats: camelCase", "309053760"],
[215, 6, 10, "Property name \`first_name\` must match one of the following formats: camelCase", "1941527303"],
[216, 6, 9, "Property name \`full_name\` must match one of the following formats: camelCase", "4383598"],
[217, 6, 15, "Property name \`github_username\` must match one of the following formats: camelCase", "4179409513"],
[218, 6, 9, "Property name \`is_active\` must match one of the following formats: camelCase", "1397809004"],
[219, 6, 9, "Property name \`last_name\` must match one of the following formats: camelCase", "16632887"],
[220, 6, 16, "Property name \`manager_fullname\` must match one of the following formats: camelCase", "3621874077"],
[221, 6, 11, "Property name \`profile_url\` must match one of the following formats: camelCase", "4082386394"],
[222, 6, 9, "Property name \`role_name\` must match one of the following formats: camelCase", "2456095625"],
[223, 6, 8, "Property name \`slack_id\` must match one of the following formats: camelCase", "352348961"],
[224, 6, 9, "Property name \`team_name\` must match one of the following formats: camelCase", "802349120"],
[225, 6, 7, "Property name \`user_id\` must match one of the following formats: camelCase", "2414288038"],
[238, 8, 12, "Property name \`display_name\` must match one of the following formats: camelCase", "2661030023"],
[240, 8, 13, "Property name \`employee_type\` must match one of the following formats: camelCase", "309053760"],
[241, 8, 10, "Property name \`first_name\` must match one of the following formats: camelCase", "1941527303"],
[242, 8, 9, "Property name \`full_name\` must match one of the following formats: camelCase", "4383598"],
[243, 8, 15, "Property name \`github_username\` must match one of the following formats: camelCase", "4179409513"],
[244, 8, 9, "Property name \`is_active\` must match one of the following formats: camelCase", "1397809004"],
[245, 8, 9, "Property name \`last_name\` must match one of the following formats: camelCase", "16632887"],
[246, 8, 16, "Property name \`manager_fullname\` must match one of the following formats: camelCase", "3621874077"],
[247, 8, 11, "Property name \`profile_url\` must match one of the following formats: camelCase", "4082386394"],
[248, 8, 9, "Property name \`role_name\` must match one of the following formats: camelCase", "2456095625"],
[249, 8, 8, "Property name \`slack_id\` must match one of the following formats: camelCase", "352348961"],
[250, 8, 9, "Property name \`team_name\` must match one of the following formats: camelCase", "802349120"],
[251, 8, 7, "Property name \`user_id\` must match one of the following formats: camelCase", "2414288038"]
"js/fixtures/globalState.ts:12004148": [
[18, 8, 12, "Property name \`html_content\` must match one of the following formats: camelCase", "574671502"],
[23, 8, 12, "Property name \`html_content\` must match one of the following formats: camelCase", "574671502"],
[43, 10, 10, "Property name \`group_name\` must match one of the following formats: camelCase", "2646960194"],
[44, 10, 9, "Property name \`group_url\` must match one of the following formats: camelCase", "991267566"],
[52, 10, 29, "Property name \`last_successful_run_timestamp\` must match one of the following formats: camelCase", "1157138603"],
[104, 4, 11, "Property name \`search_term\` must match one of the following formats: camelCase", "1115328666"],
[108, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[110, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[113, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[120, 10, 22, "Property name \`last_updated_timestamp\` must match one of the following formats: camelCase", "1908543892"],
[126, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[129, 6, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[131, 6, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[136, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[138, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[141, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[143, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[146, 8, 10, "Property name \`page_index\` must match one of the following formats: camelCase", "305070679"],
[148, 8, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"],
[165, 6, 11, "Property name \`is_editable\` must match one of the following formats: camelCase", "389228086"],
[166, 6, 7, "Property name \`is_view\` must match one of the following formats: camelCase", "2715417645"],
[168, 6, 22, "Property name \`last_updated_timestamp\` must match one of the following formats: camelCase", "1908543892"],
[172, 6, 12, "Property name \`table_writer\` must match one of the following formats: camelCase", "1979434539"],
[172, 22, 15, "Property name \`application_url\` must match one of the following formats: camelCase", "1067313867"],
[173, 19, 14, "Property name \`is_partitioned\` must match one of the following formats: camelCase", "361132355"],
[174, 6, 13, "Property name \`table_readers\` must match one of the following formats: camelCase", "3636171154"],
[175, 28, 11, "Property name \`source_type\` must match one of the following formats: camelCase", "2336271487"],
[176, 6, 16, "Property name \`resource_reports\` must match one of the following formats: camelCase", "3614191341"],
[178, 6, 25, "Property name \`programmatic_descriptions\` must match one of the following formats: camelCase", "3262748393"],
[191, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[192, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[195, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[196, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[199, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[200, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[203, 10, 8, "Property name \`tag_name\` must match one of the following formats: camelCase", "3608461679"],
[204, 10, 9, "Property name \`tag_count\` must match one of the following formats: camelCase", "3118465291"],
[215, 6, 12, "Property name \`display_name\` must match one of the following formats: camelCase", "2661030023"],
[217, 6, 13, "Property name \`employee_type\` must match one of the following formats: camelCase", "309053760"],
[218, 6, 10, "Property name \`first_name\` must match one of the following formats: camelCase", "1941527303"],
[219, 6, 9, "Property name \`full_name\` must match one of the following formats: camelCase", "4383598"],
[220, 6, 15, "Property name \`github_username\` must match one of the following formats: camelCase", "4179409513"],
[221, 6, 9, "Property name \`is_active\` must match one of the following formats: camelCase", "1397809004"],
[222, 6, 9, "Property name \`last_name\` must match one of the following formats: camelCase", "16632887"],
[223, 6, 16, "Property name \`manager_fullname\` must match one of the following formats: camelCase", "3621874077"],
[224, 6, 11, "Property name \`profile_url\` must match one of the following formats: camelCase", "4082386394"],
[225, 6, 9, "Property name \`role_name\` must match one of the following formats: camelCase", "2456095625"],
[226, 6, 8, "Property name \`slack_id\` must match one of the following formats: camelCase", "352348961"],
[227, 6, 9, "Property name \`team_name\` must match one of the following formats: camelCase", "802349120"],
[228, 6, 7, "Property name \`user_id\` must match one of the following formats: camelCase", "2414288038"],
[241, 8, 12, "Property name \`display_name\` must match one of the following formats: camelCase", "2661030023"],
[243, 8, 13, "Property name \`employee_type\` must match one of the following formats: camelCase", "309053760"],
[244, 8, 10, "Property name \`first_name\` must match one of the following formats: camelCase", "1941527303"],
[245, 8, 9, "Property name \`full_name\` must match one of the following formats: camelCase", "4383598"],
[246, 8, 15, "Property name \`github_username\` must match one of the following formats: camelCase", "4179409513"],
[247, 8, 9, "Property name \`is_active\` must match one of the following formats: camelCase", "1397809004"],
[248, 8, 9, "Property name \`last_name\` must match one of the following formats: camelCase", "16632887"],
[249, 8, 16, "Property name \`manager_fullname\` must match one of the following formats: camelCase", "3621874077"],
[250, 8, 11, "Property name \`profile_url\` must match one of the following formats: camelCase", "4082386394"],
[251, 8, 9, "Property name \`role_name\` must match one of the following formats: camelCase", "2456095625"],
[252, 8, 8, "Property name \`slack_id\` must match one of the following formats: camelCase", "352348961"],
[253, 8, 9, "Property name \`team_name\` must match one of the following formats: camelCase", "802349120"],
[254, 8, 7, "Property name \`user_id\` must match one of the following formats: camelCase", "2414288038"]
],
"js/fixtures/metadata/dashboard.ts:1885645250": [
[3, 2, 10, "Property name \`group_name\` must match one of the following formats: camelCase", "2646960194"],
......@@ -1938,6 +1938,9 @@ exports[`eslint`] = {
[132, 8, 7, "Property name \`user_id\` must match one of the following formats: camelCase", "2414288038"],
[135, 4, 13, "Property name \`total_results\` must match one of the following formats: camelCase", "248890114"]
],
"js/index.tsx:1902152286": [
[45, 6, 16, "Variable name \`Routes\` must match one of the following formats: camelCase, UPPER_CASE", "1048754879"]
],
"js/interfaces/Announcements.ts:685742554": [
[3, 2, 12, "Property name \`html_content\` must match one of the following formats: camelCase", "574671502"]
],
......
// 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