This is our JS tracking library that we use to define and send events to Backtrack. Backtrack then forwards the events to Mixpanel.
It's available from the rest of Polecat under an alias '@Tracking'
.
The main reason we have this library is to add order to our Mixpanel events. For that reason events are defined with a schema. The properties dispatched with events are then validated against the schema in Backtrack before being forwarded to Mixpanel.
Sending events that are already defined is simple.
import { trackEvent } from '@Tracking';
import { widgetDeleted } from '@Tracking/events';
const onDelete = () => {
trackEvent(widgetDeleted({
'Widget ID': '1234',
'Integration Name': 'Zendesk Support',
}));
};
Similar to Redux actions, each event has an event creator defined up front. You'll find these events in the ./events
directory, categorised by type.
We have a helper defineEvent
that accepts
name
(String): The event nameschemaTypes
(Object): The schema definition for the event (See SchemaTypes section)...contexts
(Object): Any contexts for the event (See Contexts section)
import defineEvent from '@Tracking/define-event';
import SchemaTypes from '@Tracking/schema-types';
export const widgetDeleted = defineEvent('Widget - deleted', {
'Widget ID': SchemaTypes.string.isRequired,
'Integration Name': SchemaTypes.string.isRequired,
});
The Schema Types package is essentially a slimmed down version of PropTypes containing the following types:
SchemaTypes.string
SchemaTypes.number
SchemaTypes.bool
SchemaTypes.oneOf([])
There might be cases where several events have to contain the same properties. For example, all Dashboard related events may require a Dashboard ID. As Dashboard ID is stored in our application (Redux) state we can automatically inject it into events using a context.
Contexts are kept in the ./contexts
directory, each context is a single object that contains a schema type definition and a context function.
import SchemaTypes from '@Tracking/schema-types';
const dashboardContext = {
schema: {
'Dashboard ID': SchemaTypes.string.isRequired,
'Layout type': SchemaTypes.oneOf(['classic', 'box', 'container']).isRequired,
},
context: ({ reduxState }) => ({
'Dashboard ID': reduxState.currentDashboard.id,
'Layout type': reduxState.currentDashboard.type,
})
}
You can then pass that context to events when they are defined.
import defineEvent from '@Tracking/define-event';
import SchemaTypes from '@Tracking/schema-types';
import dashboardContext from '@Tracking/contexts/dashboard-context';
export const dashboardTitleChanged = defineEvent(
'Dashboard - Title changed',
{
'New Title': PropTypes.string,
},
dashboardContext,
);
Now, any time you dispatch the dashboardTitleChanged
event, the Dashboard ID and Layout type will be automatically injected into the properties.
Note: Properties passed to the event creator manually will override any property from contexts that has the same key.