Gaëtan Renaudeau
7 years ago
committed by
GitHub
39 changed files with 420 additions and 86 deletions
@ -0,0 +1,10 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
if [ -z $ANALYTICS_KEY ]; then |
||||
|
echo 'ANALYTICS_KEY must be set' |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
cd `dirname $0`/.. |
||||
|
|
||||
|
wget https://cdn.segment.com/analytics.js/v1/$ANALYTICS_KEY/analytics.min.js -O static/analytics.min.js |
@ -0,0 +1,29 @@ |
|||||
|
import { PureComponent } from 'react' |
||||
|
import { track } from './segment' |
||||
|
|
||||
|
class Track extends PureComponent<{ |
||||
|
onMount?: boolean, |
||||
|
onUnmount?: boolean, |
||||
|
onUpdate?: boolean, |
||||
|
event: string, |
||||
|
properties?: Object, |
||||
|
}> { |
||||
|
componentDidMount() { |
||||
|
if (this.props.onMount) this.track() |
||||
|
} |
||||
|
componentDidUpdate() { |
||||
|
if (this.props.onUpdate) this.track() |
||||
|
} |
||||
|
componentWillUnmount() { |
||||
|
if (this.props.onUnmount) this.track() |
||||
|
} |
||||
|
track = () => { |
||||
|
const { event, properties } = this.props |
||||
|
track(event, properties) |
||||
|
} |
||||
|
render() { |
||||
|
return null |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default Track |
@ -0,0 +1,14 @@ |
|||||
|
import { PureComponent } from 'react' |
||||
|
import { page } from './segment' |
||||
|
|
||||
|
class TrackPage extends PureComponent<{ category: string, name?: string, properties?: Object }> { |
||||
|
componentDidMount() { |
||||
|
const { category, name, properties } = this.props |
||||
|
page(category, name, properties) |
||||
|
} |
||||
|
render() { |
||||
|
return null |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default TrackPage |
@ -0,0 +1,18 @@ |
|||||
|
/* eslint-disable */ |
||||
|
import { getPath } from 'helpers/staticPath' |
||||
|
|
||||
|
// prettier-ignore
|
||||
|
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)};analytics.SNIPPET_VERSION="4.1.0"; |
||||
|
}}(); |
||||
|
|
||||
|
let loaded = false |
||||
|
export const load = () => { |
||||
|
if (loaded) return |
||||
|
loaded = true |
||||
|
var n = document.createElement('script') |
||||
|
n.type = 'text/javascript' |
||||
|
n.async = !0 |
||||
|
n.src = getPath('analytics.min.js') |
||||
|
var a = document.getElementsByTagName('script')[0] |
||||
|
a.parentNode.insertBefore(n, a) |
||||
|
} |
@ -0,0 +1,100 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import uuid from 'uuid/v4' |
||||
|
import logger from 'logger' |
||||
|
import invariant from 'invariant' |
||||
|
import user from 'helpers/user' |
||||
|
import { DEBUG_ANALYTICS } from 'config/constants' |
||||
|
import { langAndRegionSelector } from 'reducers/settings' |
||||
|
import { getSystemLocale } from 'helpers/systemLocale' |
||||
|
import { load } from './inject-in-window' |
||||
|
|
||||
|
invariant(typeof window !== 'undefined', 'analytics/segment must be called on renderer thread') |
||||
|
|
||||
|
const sessionId = uuid() |
||||
|
|
||||
|
const getContext = store => { |
||||
|
const state = store.getState() |
||||
|
const { language, region } = langAndRegionSelector(state) |
||||
|
const systemLocale = getSystemLocale() |
||||
|
return { |
||||
|
ip: '0.0.0.0', |
||||
|
appVersion: __APP_VERSION__, |
||||
|
language, |
||||
|
region, |
||||
|
environment: __DEV__ ? 'development' : 'production', |
||||
|
systemLanguage: systemLocale.language, |
||||
|
systemRegion: systemLocale.region, |
||||
|
sessionId, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
let storeInstance // is the redux store. it's also used as a flag to know if analytics is on or off.
|
||||
|
|
||||
|
export const start = (store: *) => { |
||||
|
storeInstance = store |
||||
|
const { analytics } = window |
||||
|
if (typeof analytics === 'undefined') { |
||||
|
logger.error('analytics is not available') |
||||
|
return |
||||
|
} |
||||
|
const { id } = user() |
||||
|
load() |
||||
|
analytics.identify( |
||||
|
id, |
||||
|
{}, |
||||
|
{ |
||||
|
context: getContext(store), |
||||
|
}, |
||||
|
) |
||||
|
if (DEBUG_ANALYTICS) { |
||||
|
logger.log(`analytics: start() with user id ${id}`) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export const stop = () => { |
||||
|
storeInstance = null |
||||
|
const { analytics } = window |
||||
|
if (typeof analytics === 'undefined') { |
||||
|
logger.error('analytics is not available') |
||||
|
return |
||||
|
} |
||||
|
analytics.reset() |
||||
|
if (DEBUG_ANALYTICS) { |
||||
|
logger.log(`analytics: stop()`) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export const track = (event: string, properties: ?Object) => { |
||||
|
if (!storeInstance) { |
||||
|
return |
||||
|
} |
||||
|
const { analytics } = window |
||||
|
if (typeof analytics === 'undefined') { |
||||
|
logger.error('analytics is not available') |
||||
|
return |
||||
|
} |
||||
|
analytics.track(event, properties, { |
||||
|
context: getContext(storeInstance), |
||||
|
}) |
||||
|
if (DEBUG_ANALYTICS) { |
||||
|
logger.log(`analytics: track(${event},`, properties) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export const page = (category: string, name: ?string, properties: ?Object) => { |
||||
|
if (!storeInstance) { |
||||
|
return |
||||
|
} |
||||
|
const { analytics } = window |
||||
|
if (typeof analytics === 'undefined') { |
||||
|
logger.error('analytics is not available') |
||||
|
return |
||||
|
} |
||||
|
analytics.page(category, name, properties, { |
||||
|
context: getContext(storeInstance), |
||||
|
}) |
||||
|
if (DEBUG_ANALYTICS) { |
||||
|
logger.log(`analytics: page(${category}, ${name || ''},`, properties) |
||||
|
} |
||||
|
} |
@ -0,0 +1,16 @@ |
|||||
|
import React, { Component, Fragment } from 'react' |
||||
|
import TrackPage from 'analytics/TrackPage' |
||||
|
import StepConnectDevice from '../StepConnectDevice' |
||||
|
|
||||
|
class ReceiveStepConnectDevice extends Component<*> { |
||||
|
render() { |
||||
|
return ( |
||||
|
<Fragment> |
||||
|
<TrackPage category="Receive" name="Step2" /> |
||||
|
<StepConnectDevice {...this.props} /> |
||||
|
</Fragment> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ReceiveStepConnectDevice |
@ -0,0 +1,16 @@ |
|||||
|
import React, { Component, Fragment } from 'react' |
||||
|
import TrackPage from 'analytics/TrackPage' |
||||
|
import StepConnectDevice from '../StepConnectDevice' |
||||
|
|
||||
|
class SendStepConnectDevice extends Component<*> { |
||||
|
render() { |
||||
|
return ( |
||||
|
<Fragment> |
||||
|
<TrackPage category="Send" name="Step2" /> |
||||
|
<StepConnectDevice {...this.props} /> |
||||
|
</Fragment> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default SendStepConnectDevice |
@ -0,0 +1,11 @@ |
|||||
|
// @flow
|
||||
|
import memoize from 'lodash/memoize' |
||||
|
|
||||
|
const parse = memoize(navLang => { |
||||
|
const localeSplit = (navLang || '').split('-') |
||||
|
const language = (localeSplit[0] || '').toLowerCase() || null |
||||
|
const region = (localeSplit[1] || '').toUpperCase() || null |
||||
|
return { language, region } |
||||
|
}) |
||||
|
|
||||
|
export const getSystemLocale = () => parse(window.navigator.language) |
@ -0,0 +1,18 @@ |
|||||
|
import { shareAnalyticsSelector } from 'reducers/settings' |
||||
|
import { start, stop } from 'analytics/segment' |
||||
|
|
||||
|
let isAnalyticsStarted = false |
||||
|
|
||||
|
export default store => next => action => { |
||||
|
next(action) |
||||
|
const state = store.getState() |
||||
|
const shareAnalytics = shareAnalyticsSelector(state) |
||||
|
if (shareAnalytics !== isAnalyticsStarted) { |
||||
|
isAnalyticsStarted = shareAnalytics |
||||
|
if (shareAnalytics) { |
||||
|
start(store) |
||||
|
} else { |
||||
|
stop() |
||||
|
} |
||||
|
} |
||||
|
} |
File diff suppressed because one or more lines are too long
@ -1,2 +1,3 @@ |
|||||
|
system: Use system locale |
||||
en: English |
en: English |
||||
fr: French |
fr: French |
||||
|
Loading…
Reference in new issue