@ricepuddin/redux-segment
Version:
Segment.io analytics integration for redux.
104 lines (79 loc) • 2.87 kB
JavaScript
import EventTypes from './event/types';
import { defaultMapper } from './event/configuration';
import { extractIdentifyFields } from './event/identify';
import { extractPageFields } from './event/page';
import { extractTrackFields } from './event/track';
import { extractAliasFields } from './event/alias';
import { extractGroupFields } from './event/group';
const ENV = typeof process !== 'undefined' && process.env.NODE_ENV || 'development';
function emit(type: string, fields: Array) {
try {
window.analytics[type](...fields);
} catch (error) {
if (ENV === 'development') {
console.warn(`Call to window.analytics[${type}] failed. Make sure that the anaytics.js`
+ ` script is loaded and executed before your application code.\n`, error);
}
}
}
function createTracker(customOptions = {}) {
const options = {
mapper: Object.assign({}, defaultMapper.mapper, customOptions.mapper)
};
return store => next => action => handleAction(store.getState.bind(store), next, action, options);
}
function appendAction(action: Object, analytics: Object) {
action.meta = Object.assign(
{},
{...action.meta},
{ analytics : { ...analytics } }
);
return action;
}
function handleAction(getState: Function, next: Function, action: Object, options: Object) {
if (action.meta && action.meta.analytics) return handleSpec(next, action);
if (typeof options.mapper[action.type] === 'function') {
let analytics = options.mapper[action.type](getState, action);
return handleSpec(next, appendAction(action, analytics));
}
if (typeof options.mapper[action.type] === 'string') {
let analytics = {eventType: options.mapper[action.type]};
return handleSpec(next, appendAction(action, analytics));
}
return next(action);
}
function getFields(type: string, fields: Object, actionType: string) {
const typeFieldHandlers = {
[EventTypes.identify]: extractIdentifyFields,
[EventTypes.page]: extractPageFields,
[EventTypes.track]: eventFields => extractTrackFields(eventFields, actionType),
[EventTypes.alias]: extractAliasFields,
[EventTypes.group]: extractGroupFields,
[EventTypes.reset]: () => [],
};
return typeFieldHandlers[type](fields);
}
function getEventType(spec) {
if (typeof spec === 'string') {
return spec;
}
return spec.eventType;
}
function handleIndividualSpec(spec: string | Object, action: Object) {
const type = getEventType(spec);
const fields = getFields(type, spec.eventPayload || {}, action.type);
emit(type, fields);
}
function handleSpec(next: Function, action: Object) {
const spec = action.meta.analytics;
if (Array.isArray(spec)) {
spec.forEach(s => handleIndividualSpec(s, action));
} else {
handleIndividualSpec(spec, action);
}
return next(action);
}
export {
createTracker,
EventTypes,
};