Need private packages and team management tools?Check out npm Teams »

@bufferapp/buffermetrics

0.9.0 • Public • Published

@bufferapp/buffermetrics

npm version Build Status

A Node.js library for tracking metrics with Express.js middleware.

  1. Usage
  2. Development

Usage

  1. Install
  2. Express Middleware
  3. Client Side Tracking
  4. Redux Middleware

Install

npm install @bufferapp/buffermetrics

Express Middleware

Note - For handling client side tracking, you must use body-parser 's json middleware.

When creating the middleware, give it a name. This is used to tag each event's source.

const buffermetricsMiddleware = require('@bufferapp/buffermetrics/middleware')
const app = express()
 
app.use(buffermetricsMiddleware({
  name: 'Marketing-Site',
  trackVisits: true,
  getExperiments: (req) => {
    return req.experiments // [{ id: String, name: String, enabled: Boolean }]
  }
}))

Now in other requests or middleware you can use the BufferMetrics library's methods:

app.get('/welcome', (req, res) => {
  req.buffermetrics.trackFunnelEvent({ id: 'X', ... })
  res.render('welcome')
})

Options

To configure the buffermetrics middleware there are a few options you can pass to the buffermetricsMiddleware function.

  • trackVisits - Boolean - Automatically track a visit for every successful response
  • getExperiments - Function - Append an experiments array each visit
  • debug - Boolean - Logs messages to aide in debugging and disables sending of events to the gRPC event collector
  • name - A future field for tracking the source of the event

Client Side Tracking

For client side tracking aside from using the Redux middleware below, you can import the client side tracking script and use that to send data to the /buffermetrics/* endpoints that are handled by the middleware above.

import buffermetrics from '@bufferapp/buffermetrics/client'
 
buffermetrics.trackAction({
  application: 'ANALYZE',
  location: 'SIDEBAR',
  action: 'CLICKED_ADD_CREDIT_CARD_LINK',
  metdata: {
    userId: user._id
  }
})

Redux

For the Redux middleware to work, the above Express middleware must be configured. This example uses @bufferapp/keywrapper .

import { createStore, applyMiddleware } from 'redux'
import keyWrapper from '@bufferapp/keywrapper'
import { createMiddleware } from '@bufferapp/buffermetrics/redux'
 
const actionTypes = keyWrapper('QUEUE', {
  POST_SHARE_NOW: 0,
  POST_DELETE: 0,
})
 
const buffermetricsMiddleware = createMiddleware({
  application: 'PUBLISH',
  metadata: (state, action) => ({ // appending metadata to each event - see below
    userId: state.userId,
    profileId: state.profileId,
  })
})
 
const store = createStore(
  reducer,
  applyMiddleware(buffermetricsMiddleware)
)

Once the Redux middleware is setup, when the user triggers an action in the application, the following event will be POSTed to the server which will be handled by the Express middleware.

For example, when the action POST_SHARE_NOW is triggered in the above example, the following action will be tracked:

{
  application: 'publish',
  location: 'queue',
  action: 'post_share_now',
  metadata: {
    userId: 'user1234567890',
    profileId: 'profile0987654321'
  }
}

Append metadata to each action

Actions are great by themselves, but often we will want to join the actions with other tables to aggregate the data. For this we can append metadata. The createMiddleware function has the metadata option which is a function which is run every time an action is called. When the action passes through the middleware, this is a time to add any useful metadata.

const buffermetricsMiddleware = createMiddleware({
  application: 'PUBLISH',
  metadata: (state, action) => {
    // ex. state = { userId: "1234567890", activeProfileId: "5678904321", ... }
    // ex. action = { type: "QUEUE__POST_SHARE_NOW", updateId: "9872342345" }
 
    // Each metric passing through may always grab some information out of state
    // like what user performed the action or what profile the user was acting on
    const m = {
      userId: state.userId,
      profileId: state.activeProfileId,
    }
 
    // Only some events will have an update id, so we can automatically add
    // it when it's available. This is easier when a standard parameter/field
    // is used
    if (action.updateId) {
      m.updateId = action.updateId
    }
    return m
  },
})

Batch or throttle metrics requests

Sending every metric immediately when it happens may cause performance issues on the client and on the server side. To help with that, there are two configuration options for controlling how metrics are send from the client, batchSize and throttle.

batchSize - The minimum number of items needed to be sent to the backend throttle - The number of milliseconds to require out in between request batches

It is possible to use just one or both configuration options.

const buffermetricsMiddleware = createMiddleware({
  application: 'PUBLISH',
  batchSize: 10,
  throttle: 1000,
})

Development

Setup

To get started work on this, clone this repo then run:

git submodule init
git submodule update
npm install

Updating BUDA Protobufs

To update to a new version of BUDA Protobufs:

cd buda-protobufs
git fetch
git checkout <version-tag>
cd ..
git add buda-protobufs
git commit -m "Upgrade BUDA to version <version-tag>"

Publishing

To update the package use npm version which will update the version, add a commit with the new version and add a git tag. See npm version --help for more information. Here's an example of how one could publish a new version:

npm version minor
git push origin/master
npm publish

Publishing a beta release

When testing it's a good idea to publish a beta version of the package and test it before you push a stable version. You can do this with this helper command which does not commit or add a git tag for the version:

npm run beta-version
npm publish --tag=beta

License

MIT

Keywords

none

Install

npm i @bufferapp/buffermetrics

DownloadsWeekly Downloads

1

Version

0.9.0

License

MIT

Unpacked Size

37.3 kB

Total Files

31

Last publish

Collaborators

  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar
  • avatar