Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(app): Add persistent unique user ID to intercom data #2004

Merged
merged 2 commits into from
Aug 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions app-shell/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,20 @@ const DEFAULTS = {
}
},

// analytics
// analytics (mixpanel)
analytics: {
appId: uuid(),
optedIn: false,
seenOptIn: false
}
},

// user support (intercom)
support: {
userId: uuid(),
createdAt: Math.floor(Date.now() / 1000),
name: 'Unknown User',
email: null
}
}

// lazy load store, overrides, and log because of config/log interdependency
Expand Down
22 changes: 1 addition & 21 deletions app/src/analytics/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @flow
// analytics module
import noop from 'lodash/noop'
import {LOCATION_CHANGE} from 'react-router-redux'
import mixpanel from 'mixpanel-browser'

import type {State, ThunkAction, Middleware} from '../types'
Expand All @@ -17,7 +16,6 @@ type AnalyticsConfig = $PropertyType<Config, 'analytics'>
const log = createLogger(__filename)

// pulled in from environment at build time
const INTERCOM_ID = process.env.OT_APP_INTERCOM_ID
const MIXPANEL_ID = process.env.OT_APP_MIXPANEL_ID

const MIXPANEL_OPTS = {
Expand All @@ -29,16 +27,14 @@ const MIXPANEL_OPTS = {
track_pageview: false
}

// intercom and mixpanel.track handlers (noop)
let intercom = noop
// mixpanel.track handler (default noop)
let track = noop

export function initializeAnalytics (): ThunkAction {
return (_, getState) => {
const config = getState().config.analytics

log.debug('Analytics config', {config})
initializeIntercom(config)
initializeMixpanel(config)
}
}
Expand All @@ -64,11 +60,6 @@ export const analyticsMiddleware: Middleware =
track(event.name, event.properties)
}

// update intercom on page change
if (action.type === LOCATION_CHANGE) {
intercom('update')
}

// enable mixpanel tracking if optedIn goes to true
if (
action.type === 'config:SET' &&
Expand All @@ -94,17 +85,6 @@ export function getAnalyticsSeen (state: State) {
return state.config.analytics.seenOptIn
}

function initializeIntercom (config: AnalyticsConfig) {
if (INTERCOM_ID) {
log.debug('Initializing Intercom')

const data = {app_id: INTERCOM_ID, 'App Version': version}

intercom = global.Intercom || intercom
intercom('boot', data)
}
}

function initializeMixpanel (config: AnalyticsConfig) {
if (MIXPANEL_ID) {
log.debug('Initializing Mixpanel')
Expand Down
7 changes: 7 additions & 0 deletions app/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ export type Config = {
optedIn: boolean,
seenOptIn: boolean,
},

support: {
userId: string,
createdAt: number,
name: string,
email: ?string,
},
}

type UpdateConfigAction = {|
Expand Down
11 changes: 6 additions & 5 deletions app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {checkForShellUpdates, shellMiddleware} from './shell'
import {healthCheckMiddleware} from './health-check'
import {apiClientMiddleware as robotApiMiddleware} from './robot'
import {initializeAnalytics, analyticsMiddleware} from './analytics'
import {initializeSupport, supportMiddleware} from './support'

import reducer from './reducer'

Expand All @@ -30,6 +31,7 @@ const middleware = applyMiddleware(
shellMiddleware,
healthCheckMiddleware,
analyticsMiddleware,
supportMiddleware,
routerMiddleware(history)
)

Expand Down Expand Up @@ -59,13 +61,12 @@ if (module.hot) {
module.hot.accept('./components/App', renderApp)
}

// TODO(mc, 2018-03-29): developer mode in app settings
if (process.env.NODE_ENV === 'development') {
global.store = store
}
// attach store to window if devtools are on
if (store.getState().config.devtools) global.store = store

// initialize analytics after first render
// initialize analytics and support after first render
store.dispatch(initializeAnalytics())
store.dispatch(initializeSupport())

// kickoff an initial update check at launch
store.dispatch(checkForShellUpdates())
Expand Down
54 changes: 54 additions & 0 deletions app/src/support.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// @flow
// user support module
import noop from 'lodash/noop'
import {LOCATION_CHANGE} from 'react-router-redux'

import {version} from './../package.json'
import createLogger from './logger'

import type {ThunkAction, Middleware} from './types'
import type {Config} from './config'

type SupportConfig = $PropertyType<Config, 'support'>

const log = createLogger(__filename)

// pulled in from environment at build time
const INTERCOM_ID = process.env.OT_APP_INTERCOM_ID

// intercom handler (default noop)
let intercom = noop

export function initializeSupport (): ThunkAction {
return (_, getState) => {
const config = getState().config.support

log.debug('Support config', {config})
initializeIntercom(config)
}
}

export const supportMiddleware: Middleware = (store) => (next) => (action) => {
// update intercom on page change
// TODO(mc, 2018-08-02): this is likely to hit intercom throttle limit
if (action.type === LOCATION_CHANGE) intercom('update')

return next(action)
}

function initializeIntercom (config: SupportConfig) {
if (INTERCOM_ID) {
const data = {
app_id: INTERCOM_ID,
user_id: config.userId,
created_at: config.createdAt,
name: config.name,
email: config.email,
'App Version': version
}

log.debug('Initializing Intercom', {data})
intercom = global.Intercom || intercom
intercom('boot', data)
}
}