0.0.6 • Published 3 years ago

user-events v0.0.6

Weekly downloads
3
License
ISC
Repository
-
Last release
3 years ago

Analytics

A pluggable analytics library designed to work with any third party analytics tool.

Connect with your favorite analytic providers, trigger custom logic based on user activity, or easily provide opt out mechanisms for visitors who wish to turn off analytics entirely.

Table of Contents

Features

  • Pluggable - Bring your own third party tool
  • Works on client & server-side
  • Test & Debug analytics integrations with time travel & offline mode.
  • (WIP) In client, works offline. Queues events to send when connection resumes

Why

Companies frequently change analytics & collection requirements. This results in adding & removing analytic services a painful time consuming process.

This library aims to solves that with a simple abstraction layer.

Philosophy

You should never be locked into a tool.

To add or remove an analytics provider adjust the plugins you load into analytics.

Install

npm install analytics --save

Usage

import Analytics from 'analytics'
import googleAnalyticsPlugin from 'analytics-plugin-ga'
import customerIOPlugin from 'analytics-plugin-customerio'

const analytics = Analytics({
  app: 'my-app-name',
  version: 100,
  plugins: [
    googleAnalyticsPlugin({
      trackingId: 'UA-121991291',
    }),
    customerIOPlugin({
      siteId: '123-xyz'
    })
  ]
})

// Fire a page view
analytics.page()
// Fire event tracking
analytics.track('userPurchase', {
  price: 20
})
// Identify a visitor
analytics.identify('user-id-xyz', {
  firstName: 'bill',
  lastName: 'murray',
  email: 'da-coolest@aol.com'
})
//...

Demo

See Analytics Demo for a site example.

API

analytics.identify

Identify a user. This will trigger identify calls in any installed plugins and will set user data in localStorage

Arguments

  • userId String - Unique ID of user
  • traits Object - Object of user traits
  • options Object - Options to pass to indentify call
  • callback Function - Optional callback function after identify completes

Example

identify('xyz-123', {
  name: 'steve',
  company: 'hello-clicky'
})

analytics.track

Track an analytics event. This will trigger track calls in any installed plugins

Arguments

  • eventName String - Event name
  • payload Object - Event payload
  • options Object - Event options
  • callback Function - Callback to fire after tracking completes

Example

analytics.track('buttonClick')

analytics.page

Trigger page view. This will trigger page calls in any installed plugins

Arguments

  • data String - (optional) page data
  • options Object - Event options
  • callback Function - Callback to fire after page view call completes

Example

analytics.page()

analytics.getState

Get data about user, activity, or context. You can access sub-keys of state with dot.prop syntax.

Arguments

  • key String - (optional) dotprop sub value of state

Example

// Get the current state of analytics
analytics.getState()

// Get a subpath of state
analytics.getState('context.offline')

analytics.reset

Clear all information about the visitor & reset analytic state.

Arguments

  • callback Function - Handler to run after reset

analytics.dispatch

Emit events for other plugins or middleware to react to.

Arguments

analytics.storage

Storage utilities for persisting data. These methods will allow you to save data in localStorage, cookies, or to the window.

analytics.storage.getItem

Get value from storage

Arguments

  • key String - storage key
  • options Object - storage options

Example

analytics.storage.getItem('storage_key')

analytics.storage.setItem

Set storage value

Arguments

  • key String - storage key
  • value Any - storage value
  • options Object - storage options

Example

analytics.storage.setItem('storage_key', 'value')

analytics.storage.removeItem

Remove storage value

Arguments

  • key String - storage key
  • options Object - storage options

Example

analytics.storage.removeItem('storage_key')

analytics.user

Get user data

Arguments

  • key String - dot.prop subpath of user data

Example

// get all user data
const userData = analytics.user()

// get user company name
const companyName = analytics.user('company.name')

analytics.ready

Fire callback on analytics ready event

Arguments

  • callback Function - function to trigger when all providers have loaded

Example

analytics.ready((action, instance) => {
  console.log('all plugins have loaded')
})

analytics.on

Attach an event handler function for one or more events to the selected elements.

Arguments

  • name String - Name of event to listen to
  • callback Function - function to fire on event

Example

analytics.on('track', ({ action, instance }) => {
  console.log('track call just happened. Do stuff')
})

analytics.once

Attach a handler function to an event and only trigger it only once.

Arguments

  • name String - Name of event to listen to
  • callback Function - function to fire on event

Example

analytics.once('track', (action, instance) => {
  console.log('This will only triggered once')
})

analytics.enablePlugin

Enable analytics plugin

Arguments

  • name String|Array - name of integration(s) to disable
  • callback Function - callback after enable runs

Example

analytics.enablePlugin('google')

// enable multiple plugins at once
analytics.enablePlugin(['google', 'segment'])

analytics.disablePlugin

Disable analytics plugin

Arguments

  • name string|array - name of integration(s) to disable
  • callback Function - callback after disable runs

Example

analytics.disablePlugin('google')

analytics.disablePlugin(['google', 'segment'])

analytics.loadPlugin

Load registered analytic providers.

Arguments

  • namespace String - integration namespace

Example

analytics.loadPlugin('segment')

analytics.events

Events exposed by core analytics library and all loaded plugins

Analytic plugins

The analytics has a robust plugin system. Here is a list of currently available plugins:

Creating analytics plugins

The library is designed to work with any third party analytics tool.

Plugins are just plain javascript objects that expose methods for analytics core to register and call.

Here is a quick example of a plugin. This is a 'vanilla' plugin example for connecting a third party analytics tool

// vanilla-example.js
export default function googleAnalytics(userConfig) {
  // return object for analytics to use
  return {
    // All plugins require a namespace
    NAMESPACE: 'google-analytics',
    config: {
      whatEver: userConfig.fooBar,
      googleAnalyticsId: userConfig.id
    },
    initialize: ({ config }) => {
      // load provider script to page
    },
    page: ({ payload }) => {
      // call provider specific page tracking
    },
    track: ({ payload }) => {
      // call provider specific event tracking
    },
    identify: ({ payload }) => {
      // call provider specific user identify method
    },
    loaded: () => {
      // return boolean so analytics knows when it can send data to third party
      return !!window.gaplugins
    }
  }
}

To use a plugin, import it and pass it into the plugins array when you bootstrap analytics.

import Analytics from 'analytics'
import vanillaExample from './vanilla-example.js'

const analytics = Analytics({
  app: 'my-app-name',
  plugins: [
    vanillaExample({ id: 'xyz-123' }),
    ...otherPlugins
  ]
})

React to any event

Plugins can react to any event flowing through analytics.

For example, if you wanted to trigger custom logic when analytics bootstraps you can attach a function handler to the bootstrap event.

For a full list of core events, checkout events.js.

// plugin.js
export default function myPlugin(userConfig) {
  return {
    NAMESPACE: 'my-plugin',
    bootstrap: ({ payload, config, instance }) => {
      // Do whatever on `bootstrap`
    },
    pageStart: ({ payload, config, instance }) => {
      // Fire custom logic before .page calls
    },
    pageEnd: ({ payload, config, instance }) => {
      // Fire custom logic after .page calls
    },
    trackStart: ({ payload, config, instance }) => {
      // Fire custom logic before .track calls
    },
    'track:customerio': ({ payload, config, instance }) => {
      // Fire custom logic before customer.io plugin runs.
      // Here you can customize the data sent to individual analytics providers
    },
    trackEnd: ({ payload, config, instance }) => {
      // Fire custom logic after .track calls
    },
    ...
  }
}

Using this plugin is the same as any other.

import Analytics from 'analytics'
import customerIoPlugin from 'analytics-plugin-customerio'
import myPlugin from './plugin.js'

const analytics = Analytics({
  app: 'my-app-name',
  plugins: [
    myPlugin(),
    customerIoPlugin({
      trackingId: '1234'
    })
    ...otherPlugins
  ]
})

(optionally) Use middleware

Alternatively, you can also add whatever middleware functionality you'd like from the redux ecosystem.

// logger-plugin.js redux middleware
const logger = store => next => action => {
  if (action.type) {
    console.log(`>> dispatching ${action.type}`, JSON.stringify(action))
  }
  let result = next(action)

  return result
}

export default logger

Using this plugin is the same as any other.

import Analytics from 'analytics'
import loggerPlugin from './logger-plugin.js'

const analytics = Analytics({
  app: 'my-app-name',
  plugins: [
    ...otherPlugins,
    loggerPlugin
  ]
})

Opt out example plugin

This is a vanilla redux middleware that will opt out users from tracking. There are many ways to implement this type of functionality using analytics

const optOutMiddleware = store => next => action => {
  const { type } = action
  if (type === 'trackStart' || type === 'pageStart' || type === 'trackStart') {
    // Check cookie/localStorage/Whatever to see if visitor opts out

    // Here I am checking user traits persisted to localStorage
    const { user } = store.getState()

    // user has optOut trait cancel action
    if (user && user.traits.optOut) {
      return next({
        ...action,
        ...{
          abort: true,
          reason: 'User opted out'
        },
      })
    }
  }
  return next(finalAction)
}

export default optOutMiddleware

Plugin Naming Conventions

Plugins should follow a naming convention before being published to NPM

analytics-plugin-{your-plugin-name}

npm install analytics-plugin-awesome-thing

CONTRIBUTING

Contributions are always welcome, no matter how large or small. Before contributing, please read the code of conduct.