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.
Middleware is only supported in Maintenance SDKs except the maintenance Browser SDK and legacy Ampli. Middleware has been replaced by Plugins in the latest SDK and Ampli versions.
Each middleware is a simple function with this signature:
1/**2 * A function to run on the Event stream (each logEvent call)3 *4 * @param payload The `payload` contains the `event` to send and an optional `extra` that lets you pass custom data to your own middleware implementations.5 * @param next Function to run the next middleware in the chain, not calling next will end the middleware chain6 */7 8function (payload: MiddlewarePayload: next: MiddlewareNext): void;
Types in middleware:
Name |
Type | Description |
---|---|---|
MiddlewarePayload.event |
Event | The event data being sent. The event may vary by platform. |
MiddlewarePayload.extra |
{ [x: string]: any } | Unstructured object to let users pass extra data to middleware. |
MiddlewareNext |
(payload: MiddlewarePayload) => void | Function called at the end of each Middleware to run the next middleware in the chain. |
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.
Middleware access to event fields may vary by platform. To ensure comprehensive access, Amplitude recommends updating to the latest Ampli version and utilizing the Plugins feature.
For Browser Ampli, the following are the accessible keys under payload
.
Name |
Type | Description |
---|---|---|
event.event_type |
string | The event name. |
event.event_properties |
{ [key: string]: any } | The event properties. |
event.user_id |
string | The event level user ID. |
event.device_id |
string | The event level device ID. |
event.user_properties |
{ [key: string]: any } | The event level user properties. |
extra |
{ [x: string]: any } | The extra information you want to send that lets you pass custom data to your own middleware implementations. |
For other platforms, middleware can access and modify the entire Event JSON object, allowing for comprehensive adjustments as needed. Learn more at here.
Add middleware to Amplitude via amplitude.addEventMiddleware()
. You can add as many middleware as you like. Each middleware runs in the order in which it's added.
1amplitude.addEventMiddleware(yourMiddleware());
Use an Middleware to modify event properties, transformation, filtering, routing to third-party destinations, and more:
1 amplitude.addEventMiddleware((payload, next) => {2 const {eventType} = payload.event;3 if (shouldSendEvent(eventType)) {4 next(payload)5 } else {6 // event will not continue to following middleware or be sent to Amplitude7 console.log(`Filtered event: ${eventType}`);8 }9});
1amplitude.addEventMiddleware((payload, next) => {2 const { event } = payload;3 if (hasPii(event.event_properties)) {4 payload.event.event_properties = obfuscate(payload.event.event_properties);5 }6 next(payload);7});
1amplitude.addEventMiddleware((payload, next) => {2 const { event } = payload;3 if (needsDeviceId(event)) {4 payload.event.deviceId = getDeviceId();5 }6 next(payload)7});
This is an example of how to send event level groups in Ampli V1. How to send event level groups in SDKs(not in Ampli) is different. Please check the specific SDKs for the usage.
1ampli.addEventMiddleware((payload, next) => { 2 const {event, extra} = payload; 3 if (event && extra && event.extra.groups) { 4 event.groups = event.extra.groups; 5 } 6 7 next(payload); 8}); 9 10// Pass the event level groups info though middleware extra when calling the tracking plan.11const extra = {groups: {"test_group_name": "test_group_value"}};12ampli.eventWithGroups({requiredNumber: 1.23, requiredBoolean: false}, extra);
1import amplitude from 'amplitude/sdk' 2import adroll from 'adroll'; 3import segment from 'segment'; 4import snowplow from 'snowplow'; 5 6amplitude.addEventMiddleware((payload, next) => { 7 const { event, extra } = payload; 8 segment.track(event.event_type, event.event_properties, { extra.anonymousId }) 9 adroll.track();10 snowplow.track(event.event_type, event.event_properties, extra.snowplow.context);11 // next();12});
1amplitude.addEventMiddleware((payload, next) => {2 if (isDevelopment && !SchemaValidator.isValid(payload.event)) {3 throw Error(`Invalid event ${event.event_type}`);4 }5 next(payload);6});
Thanks for your feedback!
June 16th, 2024
Need help? Contact Support
Visit Amplitude.com
Have a look at the Amplitude Blog
Learn more at Amplitude Academy
© 2024 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.