Skip to content

Middleware

Note

Middleware is only supported in Ampli legacy. Plugins replaced middleware in the latest Ampli version.

Middleware lets you extend Amplitude by running a sequence of custom code on every event. This pattern is flexible and you can use it to support event enrichment, transformation, filtering, routing to third-party destinations, and more.

Each middleware is a simple function with this signature:

function (payload: MiddlewarePayload: next: MiddlewareNext): void;

The payload contains the event to send and an optional extra that lets you pass custom data to your own middleware implementations.

To invoke the next middleware in the queue, use the next function. You must call next(payload) to continue the middleware chain. If a middleware doesn't call next, then the event processing stops executing after the current middleware completes.

Add middleware to Ampli via ampli.client.addEventMiddleware(). You can add as many middleware as you like. Each middleware runs in the order in which it's added.

Note

In Amplitude's Browser SDKs, add Middleware directly via ampli instead of ampli.client. To add Middleware in these SDKs you should use ampli.addEventMiddlware().

const loggingMiddleware: Middleware = (payload, next) => {
  console.log(`[ampli] event=${payload.event} extra=${payload.extra}`);
  // continue to next middleware in chain
  next(payload);
}

const filteringMiddleware: Middleware = (payload, next) => {
  const {eventType} =  payload.event;
  if (shouldSendEvent(eventType)) {
    next(payload)
  } else {
    // event will not continue to following middleware or be sent to Amplitude
    console.log(`Filtered event: ${eventType}`);
  }
}

ampli.client.addEventMiddleware(loggingMiddleware)
ampli.client.addEventMiddleware(filteringMiddleware)

Middleware examples

Modify events

ampli.client.addEventMiddleware((payload, next) => {
  const { event } = payload;
  if (hasPii(event.properties)) {
    obfuscate(payload.event.properties);
  }
  next(payload);
});

Enrich events

ampli.client.addEventMiddleware((payload, next) => {
  const { event } = payload;
  if (needsDeviceId(event)) {
    payload.event.deviceId = getDeviceId();
  }
  next(payload)
});

Basic filtering

ampli.client.addEventMiddleware((payload, next) => {
  const { event } = payload;
  if (event.name !== 'Event to Skip') {
    next(payload);
  }
});

Forward data to other services, but not Amplitude

import amplitude from 'amplitude/sdk'
import ampli = './ampli';
import adroll from 'adroll';
import segment from 'segment';
import snowplow from 'snowplow';

ampli.client.addEventMiddleware((payload, next) => {
  const { event, extra } = payload;
  segment.track(event.name, event.properties, { extra.anonymousId })
  adroll.track();
  snowplow.track(event.name, event.properties, extra.snowplow.context);
  // next();
});

Use client-side validation

ampli.client.addEventMiddleware((payload, next) => {
  if (isDevelopment && !SchemaValidator.isValid(payload.event)) {
    throw Error(`Invalid event ${event.name}`);
  }
  next(payload);
});

ampli.client.addEventMiddleware((payload, next) => {
  const { event, extra } = payload;
  segment.track(event.name, event.properties, { extra.segment.anonymousId })
  next(payload);
});