Skip to content

Instantly share code, notes, and snippets.

@Ranatchai
Last active September 12, 2021 22:15
Show Gist options
  • Save Ranatchai/6112c5c952299c6ac67bba7dff11c49c to your computer and use it in GitHub Desktop.
Save Ranatchai/6112c5c952299c6ac67bba7dff11c49c to your computer and use it in GitHub Desktop.
import React from 'react'
const MIXPANEL_TOKEN = '' // token here
const appProperties = {}
const _waitTracking = []
let mixpanel = null
let isInit = false
/*
always load mixpanel dynamic because it's huge https://github.com/mixpanel/mixpanel-js/issues/128
It uses dynamic-import syntax, that is in a ECMAScript proposal and not currently part of the language standard. if you use babel you need
https://yarnpkg.com/en/package/babel-plugin-syntax-dynamic-import
*/
export const loadMixpanel = () =>
import('mixpanel-browser').then(_mixpanel => {
mixpanel = _mixpanel
if (!isInit) {
mixpanel.init(MIXPANEL_TOKEN)
isInit = true
execWaitTracking()
console.log('mixpanel init')
}
return mixpanel
})
// exec track event that occur when mixpanel doesn't load complete
function execWaitTracking() {
for (let i = 0, length = _waitTracking.length; i < length; i++) {
const params = _waitTracking.shift()
track(...params)
}
}
export function track(...params) {
if (!mixpanel) {
_waitTracking.push(params)
return
}
const [eventName, properties = {}] = params
console.log('track', eventName)
mixpanel.track(eventName, {
...appProperties,
...properties
})
}
export const withTracker = Component =>
class ComponentWithTracker extends React.Component {
componentDidMount() {
// load mixpanel
loadMixpanel().catch(err => {
console.warn('load mixpanel failed', err)
})
}
render() {
return <Component {...this.props} track={track} mixpanel={mixpanel} />
}
}
// simply upgrade hoc to render props, https://reactrocket.com/post/turn-your-hocs-into-render-prop-components/
const Render = ({ children, ...props }) => children(props)
// convert hoc to render props
export const Tracker = withTracker(Render)
// auto track when rendered
export const Track = withTracker(
class Track extends React.Component {
componentDidMount() {
this.props.track(this.props.eventName, this.props.properties)
}
render() {
return null
}
}
)
@Ranatchai
Copy link
Author

Ranatchai commented Jul 9, 2018

React Examples

For Tracker, it's a render props component https://reactjs.org/docs/render-props.html

<Tracker>
  {({ track }) => (
    <SomeComponent onClick={() => {
      track('eventName', { /* some props here */ })
      doSomething()
    }} />
  )}
</Tracker>

For a Track component, use it when you want to track along with render something. it's very simple and useful for me.

const SecretModal = () => (
  <Modal title="very secret modal">
    <Track eventName="very secret modal is rendered" properties={{ /* some props here */ }} />
    <SecretContent/>
  </Modal>
)

For withTracker, it's a higher-order component. https://reactjs.org/docs/higher-order-components.html

const MyComponent = ({ track }) => {}
export default withTracker(MyComponent)

a bit old fashion, but still very useful for some case.

JS Case

// you can use track anywhere, but it's not automatic load mixpanel
track('eventName', properties)
// Not using global, but always using mixpanel instance via loadMixpanel(), to make sure it's loaded.
loadMixpanel().then(mixpanel => {
   mixpanel.identify(userId)
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment