Skip to content

Commit

Permalink
Merge pull request #1984 from daveajrussell/preview-analytics-events
Browse files Browse the repository at this point in the history
Add analytics events for browser preview
  • Loading branch information
daveajrussell authored Nov 1, 2024
2 parents 323e84c + 39fc3e7 commit 8dd931d
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/browser/modules/Stream/PlayFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { isConnectedAuraHost } from 'shared/modules/connections/connectionsDuck'
import { getEdition, isEnterprise } from 'shared/modules/dbMeta/dbMetaDuck'
import { DARK_THEME } from 'shared/modules/settings/settingsDuck'
import { LAST_GUIDE_SLIDE } from 'shared/modules/udc/udcDuck'
import { PreviewFrame } from './StartPreviewFrame'
import PreviewFrame from './StartPreviewFrame'

const AuraPromotion = () => {
const theme = useContext(ThemeContext)
Expand Down
29 changes: 26 additions & 3 deletions src/browser/modules/Stream/StartPreviewFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React from 'react'
import React, { Dispatch } from 'react'
import { Action } from 'redux'
import { trackNavigateToPreview } from 'shared/modules/preview/previewDuck'
import { connect } from 'react-redux'
import { withBus } from 'react-suber'

export const navigateToPreview = (): void => {
const path = window.location.pathname
Expand All @@ -26,7 +30,15 @@ export const navigateToPreview = (): void => {
}
}

export const PreviewFrame = () => {
type PreviewFrameProps = {
executeTrackNavigateToPreview: () => void
}
const PreviewFrame = ({ executeTrackNavigateToPreview }: PreviewFrameProps) => {
function trackAndNavigateToPreview() {
executeTrackNavigateToPreview()
navigateToPreview()
}

return (
<>
<div className="teasers">
Expand All @@ -36,7 +48,10 @@ export const PreviewFrame = () => {
<p>
Switch to the preview experience to access all the latest features.
</p>
<button onClick={navigateToPreview} className="btn btn-advertise">
<button
onClick={trackAndNavigateToPreview}
className="btn btn-advertise"
>
{"Let's go"}
</button>
</div>
Expand Down Expand Up @@ -86,3 +101,11 @@ export const PreviewFrame = () => {
</>
)
}

const mapDispatchToProps = (dispatch: Dispatch<Action>) => {
return {
executeTrackNavigateToPreview: () => dispatch(trackNavigateToPreview())
}
}

export default withBus(connect(null, mapDispatchToProps)(PreviewFrame))
7 changes: 7 additions & 0 deletions src/shared/modules/dbMeta/dbMetaEpics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ import {
getCurrentDatabase
} from 'shared/utils/selectors'
import { isBoltConnectionErrorCode } from 'services/bolt/boltConnectionErrors'
import { trackPageLoad } from '../preview/previewDuck'

function handleConnectionError(store: any, e: any) {
if (!e.code || isBoltConnectionErrorCode(e.code)) {
Expand Down Expand Up @@ -546,6 +547,12 @@ export const serverConfigEpic = (some$: any, store: any) =>
store.dispatch(triggerCredentialsTimeout())
}

setTimeout(() => {
// Track page load after server config is done
// setTimeout ensures telemetry settings have been propagated to the App
store.dispatch(trackPageLoad())
})

return Rx.Observable.of(null)
})
})
Expand Down
154 changes: 154 additions & 0 deletions src/shared/modules/preview/previewDuck.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { createBus, createReduxMiddleware } from 'suber'
import configureMockStore, { MockStoreEnhanced } from 'redux-mock-store'
import {
PREVIEW_EVENT,
trackNavigateToPreview,
trackPageLoad
} from './previewDuck'

describe('previewDuck tests', () => {
let store: MockStoreEnhanced<unknown, unknown>
const bus = createBus()
const mockStore = configureMockStore([createReduxMiddleware(bus)])

beforeAll(() => {
store = mockStore()
})

afterEach(() => {
bus.reset()
store.clearActions()
localStorage.clear()
})

test('trackNavigateToPreview sends a PREVIEW_EVENT', done => {
const action = trackNavigateToPreview()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action).toEqual({
type: PREVIEW_EVENT,
label: 'PREVIEW_UI_SWITCH',
data: {
switchedTo: 'preview',
timeSinceLastSwitch: null
}
})
done()
})

// When
store.dispatch(action)
})

test('trackNavigateToPreview sets hasTriedPreviewUI', done => {
localStorage.setItem('hasTriedPreviewUI', 'false')
const action = trackNavigateToPreview()

bus.take(PREVIEW_EVENT, () => {
// Then
const hasTriedPreviewUI = localStorage.getItem('hasTriedPreviewUI')
expect(hasTriedPreviewUI).toBe('true')
done()
})

// When
store.dispatch(action)
})

test('trackNavigateToPreview sends correct timeSinceLastSwitch when timeSinceLastSwitchMs is unset', done => {
const action = trackNavigateToPreview()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action.data.timeSinceLastSwitch).toBeNull()
done()
})

// When
store.dispatch(action)
})

test('trackNavigateToPreview sends correct timeSinceLastSwitch when timeSinceLastSwitchMs has been set', done => {
localStorage.setItem('timeSinceLastSwitchMs', Date.now().toString())
const action = trackNavigateToPreview()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action.data.timeSinceLastSwitch).not.toBeNull()
done()
})

// When
store.dispatch(action)
})

test('trackPageLoad sends a PREVIEW_EVENT', done => {
const action = trackPageLoad()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action).toEqual({
type: PREVIEW_EVENT,
label: 'PREVIEW_PAGE_LOAD',
data: { previewUI: false, hasTriedPreviewUI: false }
})
done()
})

// When
store.dispatch(action)
})

test('trackPageLoad sends correct hasTriedPreviewUI value when flag is unset', done => {
const action = trackPageLoad()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action.data.hasTriedPreviewUI).toBeFalsy()
done()
})

// When
store.dispatch(action)
})

test('trackPageLoad sends correct hasTriedPreviewUI value when flag is set', done => {
localStorage.setItem('hasTriedPreviewUI', 'true')
const action = trackPageLoad()

bus.take(PREVIEW_EVENT, () => {
// Then
const [action] = store.getActions()
expect(action.data.hasTriedPreviewUI).toBeTruthy()
done()
})

// When
store.dispatch(action)
})
})
66 changes: 66 additions & 0 deletions src/shared/modules/preview/previewDuck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const PREVIEW_EVENT = 'preview/PREVIEW_EVENT'

interface PreviewEventAction {
type: typeof PREVIEW_EVENT
label: string
data:
| {
switchedTo: 'preview' | 'classic'
timeSinceLastSwitch: number | null
}
| {
previewUI: boolean
hasTriedPreviewUI: boolean
}
}

export const trackNavigateToPreview = (): PreviewEventAction => {
const now = Date.now()
localStorage.setItem('hasTriedPreviewUI', 'true')

const timeSinceLastSwitchMs = localStorage.getItem('timeSinceLastSwitchMs')
localStorage.setItem('timeSinceLastSwitchMs', now.toString())

let timeSinceLastSwitch = null
if (timeSinceLastSwitchMs !== null) {
timeSinceLastSwitch = now - parseInt(timeSinceLastSwitchMs)
}

return {
type: PREVIEW_EVENT,
label: 'PREVIEW_UI_SWITCH',
data: {
switchedTo: 'preview',
timeSinceLastSwitch: timeSinceLastSwitch
}
}
}

export const trackPageLoad = (): PreviewEventAction => {
const hasTriedPreviewUI = localStorage.getItem('hasTriedPreviewUI') === 'true'

return {
type: PREVIEW_EVENT,
label: 'PREVIEW_PAGE_LOAD',
data: { previewUI: false, hasTriedPreviewUI }
}
}
11 changes: 11 additions & 0 deletions src/shared/modules/udc/udcDuck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import {
TRACK_CANNY_FEATURE_REQUEST
} from 'shared/modules/sidebar/sidebarDuck'
import cmdHelper from 'shared/services/commandInterpreterHelper'
import { PREVIEW_EVENT } from '../preview/previewDuck'

// Action types
export const NAME = 'udc'
Expand Down Expand Up @@ -324,3 +325,13 @@ export const trackErrorFramesEpic: Epic<Action, GlobalState> = (
}
})
.ignoreElements()

export const trackPreviewEpic: Epic<Action, GlobalState> = action$ => {
return action$.ofType(PREVIEW_EVENT).map((action: any) => {
return metricsEvent({
category: 'preview',
label: action.label,
data: action.data
})
})
}
4 changes: 3 additions & 1 deletion src/shared/rootEpic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import {
import {
trackCommandUsageEpic,
trackErrorFramesEpic,
trackPreviewEpic,
trackReduxActionsEpic,
udcStartupEpic
} from './modules/udc/udcDuck'
Expand Down Expand Up @@ -148,5 +149,6 @@ export default combineEpics(
trackReduxActionsEpic,
initializeCypherEditorEpic,
updateEditorSupportSchemaEpic,
fetchRemoteGuideEpic
fetchRemoteGuideEpic,
trackPreviewEpic
)

0 comments on commit 8dd931d

Please sign in to comment.