Skip to content

Node.js SDK

npm version

The Node.js SDK lets you send events to Amplitude. This library is open-source, check it out on GitHub.

Node SDK Resources (Beta)

GitHub · Releases · API Reference

Ampli Wrapper versus the Amplitude SDK

The Ampli Wrapper is an autogenerated library based on your pre-defined tracking plan. This is a lightweight wrapper over the Amplitude SDK that provides type-safety, automatic code completion, linting, and schema validation. The generated code replicates the spec in the Tracking Plan and enforces its rules and requirements. This guide is about the Amplitude SDK. To learn more about Ampli Wrapper, see Ampli Wrapper Overview and examples. Click here for more documentation on Ampli for Node.

Getting started

Installation

To get started with using Node SDK, install the package to your project via NPM or script loader.

Install as Node package

This package is published on NPM registry and you can install it using npm and yarn.

npm install @amplitude/analytics-node
yarn add @amplitude/analytics-node

Usage

Initialize the SDK

Initialization is necessary before any instrumentation is done. The API key for your Amplitude project is required. The SDK can be used anywhere after it's initialized anywhere in an application.

import { init } from '@amplitude/analytics-node';

// Option 1, initialize with API_KEY only
init(API_KEY);

// Option 2, initialize including configuration
init(API_KEY, {
  flushIntervalMillis: 30 * 1000, // Sets request interval to 30s
});

Debugging

You can control the level of logs printed to the developer console.

  • 'None': Suppresses all log messages.
  • 'Error': Shows error messages only.
  • 'Warn': Shows error messages and warnings. This is the default value if logLevel isn't explicitly specified.
  • 'Verbose': Shows informative messages.
  • 'Debug': Shows error messages, warnings, and informative messages that may be useful for debugging, including the function context information for all SDK public method invocations. This logging mode is only suggested to be used in development phases.

Set the log level by configuring the logLevel with the level you want.

amplitude.init(API_KEY, {
  logLevel: amplitude.Types.LogLevel.Warn,
});

The default logger outputs logs to the developer console. You can provide your own logger implementation based on the Logger interface for any customization purpose. For example, collecting any error messages from the SDK in a production environment.

Set the logger by configuring the loggerProvider with your own implementation.

amplitude.init(API_KEY, {
  loggerProvider: new MyLogger(),
});

Debug Mode

Enable the debug mode by setting the logLevel to "Debug", example:

amplitude.init(API_KEY, {
  logLevel: amplitude.Types.LogLevel.Debug,
});

With the default logger, extra function context information will be output to the developer console when invoking any SDK public method, including:

  • 'type': Category of this context, e.g., "invoke public method".
  • 'name': Name of invoked function, e.g., "setUserId".
  • 'args': Arguments of the invoked function.
  • 'stacktrace': Stacktrace of the invoked function.
  • 'time': Start and end timestamp of the function invocation.
  • 'states': Useful internal states snapshot before and after the function invocation.

EU data residency

You can configure the server zone when initializing the client for sending data to Amplitude's EU servers. The SDK sends data based on the server zone if it's set.

Note

For EU data residency, the project must be set up inside Amplitude EU. You must initialize the SDK with the API key from Amplitude EU.

import * as amplitude from '@amplitude/analytics-node';

amplitude.init(API_KEY, {
  serverZone: amplitude.Types.ServerZone.EU,
});

Tracking an event

Important notes about sending events

This SDK uses the HTTP V2 API and follows the same constraints for events. Make sure that all events logged in the SDK have the event_type field and at least one of device_id or user_id, and follows the HTTP API's constraints on each of those fields.

To prevent instrumentation issues, device IDs and user IDs must be strings with a length of 5 characters or more. If an event contains a device ID or user ID that's too short, the ID value is removed from the event. If the event doesn't have a user_id or device_id value, the upload may be rejected with a 400 status. Override the default minimum length of 5 character by passing the min_id_length option with the request.

Events represent how users interact with your application. For example, "Button Clicked" may be an action you want to note.

import { track } from '@amplitude/analytics-node';

// Track a basic event
track('Button Clicked', undefined, {
  user_id: 'user@amplitude.com',
});

// Track events with optional properties
const eventProperties = {
  buttonColor: 'primary',
};
track('Button Clicked', eventProperties, {
  user_id: 'user@amplitude.com',
});

User properties

User properties help you understand your users at the time they performed some action within your app such as their device details, their preferences, or language.

Identify is for setting the user properties of a particular user without sending any event. The SDK supports the operations set, setOnce, unset, add, append, prepend, preInsert, postInsert, and remove on individual user properties. The operations are declared via a provided Identify interface. Chain together multiple operations together in a single Identify object. The Identify object is then passed to the Amplitude client to send to the server.

Note

If the Identify call is sent after the event, the results of operations are visible immediately in the dashboard user’s profile area, but it don't appear in chart result until another event is sent after the Identify call. The identify call only affects events going forward. More details here.

Set a user property

The Identify object provides controls over setting user properties. An Identify object must first be instantiated, then Identify methods can be called on it, and finally the client makes a call with the Identify object.

import { identify, Identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.set

This method sets the value of a user property. For example, you can set a role property of a user.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.set('location', 'LAX');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.setOnce

This method sets the value of a user property only once. Subsequent calls using setOnce() are ignored. For example, you can set an initial login method for a user and since only the initial value is tracked, setOnce() ignores subsequent calls.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.setOnce('initial-location', 'SFO');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.add

This method increments a user property by some numerical value. If the user property doesn't have a value set yet, it's initialized to 0 before being incremented. For example, you can track a user's travel count.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.add('travel-count', 1);

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Arrays in user properties

Arrays can be used as user properties. You can directly set arrays or use prepend, append, preInsert and postInsert to generate an array.

Identify.prepend

This method prepends a value or values to a user property array. If the user property doesn't have a value set yet, it's initialized to an empty list before the new values are prepended.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.prepend('visited-locations', 'LAX');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.append

This method appends a value or values to a user property array. If the user property doesn't have a value set yet, it's initialized to an empty list before the new values are prepended.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.append('visited-locations', 'SFO');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.preInsert

This method pre-inserts a value or values to a user property, if it doesn't exist in the user property yet. Pre-insert means inserting the value at the beginning of a given list. If the user property doesn't have a value set yet, it's initialized to an empty list before the new values are pre-inserted. If the user property has an existing value, it's a no operation.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.preInsert('unique-locations', 'LAX');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.postInsert

This method post-inserts a value or values to a user property, if it doesn't exist in the user property yet. Post-insert means inserting the value at the end of a given list. If the user property doesn't have a value set yet, it's initialized to an empty list before the new values are post-inserted. If the user property has an existing value, it's a no operation.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.postInsert('unique-locations', 'SFO');

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

Identify.remove

This method removes a value or values to a user property, if it exists in the user property. Remove means remove the existing value from the given list. If the item doesn't exist in the user property, it's a no operation.

import { Identify, identify } from '@amplitude/analytics-node';

const identifyObj = new Identify();
identifyObj.remove('unique-locations', 'JFK')

identify(identifyObj, {
  user_id: 'user@amplitude.com',
});

User groups

Feature availability

This feature is available in accounts with a Growth or Enterprise plan with the Accounts add-on.

Amplitude supports assigning users to groups and performing queries, such as Count by Distinct, on those groups. If at least one member of the group has performed the specific event, then the count includes the group.

For example, you want to group your users based on what organization they're in by using an 'orgId'. Joe is in 'orgId' '10', and Sue is in 'orgId' '15'. Sue and Joe both perform a certain event. You can query their organizations in the Event Segmentation Chart.

When setting groups, define a groupType and groupName. In the previous example, 'orgId' is the groupType and '10' and '15' are the values for groupName. Another example of a groupType could be 'sport' with groupName values like 'tennis' and 'baseball'.

Setting a group also sets the groupType:groupName as a user property, and overwrites any existing groupName value set for that user's groupType, and the corresponding user property value. groupType is a string, and groupName can be either a string or an array of strings to indicate that a user is in multiple groups.

import { setGroup } from '@amplitude/analytics-node';

// set group with single group name
setGroup('orgId', '15', {
  user_id: 'user@amplitude.com',
});

// set group with multiple group names
setGroup('sport', ['soccer', 'tennis'], {
  user_id: 'user@amplitude.com',
});

Group properties

Feature availability

This feature is available in accounts with a Growth or Enterprise plan with the Accounts add-on.

Use the Group Identify API to set or update properties of particular groups. These updates only affect events going forward.

The groupIdentify() method accepts a group type and group name string parameter, as well as an Identify object that's applied to the group.

import { Identify, groupIdentify } from '@amplitude/analytics-node';

const groupType = 'plan';
const groupName = 'enterprise';
const event = new Identify()
event.set('key1', 'value1');

groupIdentify(groupType, groupName, identify, {
  user_id: 'user@amplitude.com',
});

Revenue tracking

The preferred method of tracking revenue for a user is to use revenue() in conjunction with the provided Revenue interface. Revenue instances store each revenue transaction and allow you to define several special revenue properties (such as "revenueType", "productIdentifier", etc.) that are used in Amplitude's Event Segmentation and Revenue LTV charts. These Revenue instance objects are then passed into revenue() to send as revenue events to Amplitude. This lets automatically display data relevant to revenue in the platform. You can use this to track both in-app and non-in-app purchases.

To track revenue from a user, call revenue each time a user generates revenue. For example, a customer purchased 3 units of a product at $3.99.

import { Revenue, revenue } from '@amplitude/analytics-node';

const event = new Revenue()
  .setProductId('com.company.productId')
  .setPrice(3.99)
  .setQuantity(3);

revenue(event, {
  user_id: 'user@amplitude.com',
});

Revenue interface

Name Description
product_id Optional. String. An identifier for the product. Amplitude recommends something like the Google Play Store product ID. Defaults to null.
quantity Required. Int. The quantity of products purchased. Note: revenue = quantity * price. Defaults to 1
price Required. Double. The price of the products purchased, and this can be negative. Note: revenue = quantity * price. Defaults to null.
revenue_type Optional, but required for revenue verification. String. The revenue type (for example, tax, refund, income). Defaults to null.
receipt Optional. String. The receipt identifier of the revenue. Defaults to null
receipt_sig Optional, but required for revenue verification. String. The receipt signature of the revenue. Defaults to null.
properties Optional. JSONObject. An object of event properties to include in the revenue event. Defaults to null.

Flush the event buffer

The flush method triggers the client to send buffered events.

import { flush } from '@amplitude/analytics-node';

flush();

By default, flush is called automatically in an interval, if you want to flush the events all together, you can control the async flow with the optional Promise interface, example:

await init(AMPLITUDE_API_KEY).promise;
track('Button Clicked', undefined, {
  user_id: 'user@amplitude.com',
});
await flush().promise;

Opt users out of tracking

You can turn off logging for a given user by setting setOptOut to true.

import { setOptOut } from '@amplitude/analytics-node';

setOptOut(true);

No events are saved or sent to the server while setOptOut is enabled, and the setting persists across page loads.

Re-enable logging by setting setOptOut to false.

import { setOptOut } from '@amplitude/analytics-node';

setOptOut(false);

Callback

All asynchronous API are optionally awaitable through a Promise interface. This also serves as callback interface.

import { track } from '@amplitude/analytics-node';

// Using async/await
const results = await track('Button Clicked', undefined, {
  user_id: 'user@amplitude.com',
}).promise;
result.event; // {...} (The final event object sent to Amplitude)
result.code; // 200 (The HTTP response status code of the request.
result.message; // "Event tracked successfully" (The response message)

// Using promises
track('Button Clicked', undefined, {
  user_id: 'user@amplitude.com',
}).promise.then((result) => {
  result.event; // {...} (The final event object sent to Amplitude)
  result.code; // 200 (The HTTP response status code of the request.
  result.message; // "Event tracked successfully" (The response message)
});

Plugins

Plugins allow you to extend Amplitude SDK's behavior by, for example, modifying event properties (enrichment type) or sending to a third-party APIs (destination type). A plugin is an object with methods setup() and execute().

add

The add method adds a plugin to Amplitude client instance. Plugins can help processing and sending events.

import { add } from '@amplitude/analytics-node';

add(new Plugin());

remove

The remove method removes the given plugin name from the client instance if it exists.

import { remove } from '@amplitude/analytics-node';

remove(plugin.name);

Create your custom plugin

Plugin.setup

This method contains logic for preparing the plugin for use and has config as a parameter. The expected return value is undefined. A typical use for this method, is to copy configuration from config or instantiate plugin dependencies. This method is called when the plugin is registered to the client via client.add().

Plugin.execute

This method contains the logic for processing events and has event as parameter. If used as enrichment type plugin, the expected return value is the modified/enriched event. If used as a destination type plugin, the expected return value is undefined. This method is called for each event instrumented using the client interface, including Identify, GroupIdentify and Revenue events.

Plugin examples

Enrichment type plugin

Here's an example of a plugin that modifies each instrumented event by adding an increment integer to event_id property of an event starting from 100.

import { init, add } from '@amplitude/analytics-node';
import { NodeConfig, EnrichmentPlugin, Event, PluginType } from '@amplitude/analytics-types';

export class AddEventIdPlugin implements EnrichmentPlugin {
  name = 'add-event-id';
  type = PluginType.ENRICHMENT as const;
  currentId = 100;
  config?: NodeConfig;

  /**
   * setup() is called on plugin installation
   * example: client.add(new AddEventIdPlugin());
   */
  async setup(config: NodeConfig): Promise<undefined> {
     this.config = config;
     return;
  }

  /**
   * execute() is called on each event instrumented
   * example: client.track('New Event');
   */
  async execute(event: Event): Promise<Event> {
    event.event_id = this.currentId++;
    return event;
  }
}

init('API_KEY');
add(new AddEventIdPlugin());

Destination type plugin

Here's an example of a plugin that sends each instrumented event to a target server URL using your preferred HTTP client.

import { init, add } from '@amplitude/analytics-node';
import { NodeConfig, DestinationPlugin, Event, PluginType, Result } from '@amplitude/analytics-types';
import fetch from 'node-fetch';

export class MyDestinationPlugin implements DestinationPlugin {
  name = 'my-destination-plugin';
  type = PluginType.DESTINATION as const;
  serverUrl: string;
  config?: NodeConfig;

  constructor(serverUrl: string) {
    this.serverUrl = serverUrl;
  }

  /**
   * setup() is called on plugin installation
   * example: client.add(new MyDestinationPlugin());
   */
  async setup(config: NodeConfig): Promise<undefined> {
    this.config = config;
    return;
  }

  /**
   * execute() is called on each event instrumented
   * example: client.track('New Event');
   */
  async execute(event: Event): Promise<Result> {
    const payload = { key: 'secret', data: event };
    const response = await fetch(this.serverUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: '*/*',
      },
      body: JSON.stringify(payload),
    });
    return {
      code: response.status,
      event: event,
      message: response.statusText,
    };
  }
}

init('API_KEY');
add(new MyDestinationPlugin('https://custom.domain.com'));

Advanced topics

Custom HTTP Client

You can provide an implementation of Transport interface to the transportProvider configuration option for customization purpose, for example, sending requests to your proxy server with customized HTTP request headers.

import { Transport } from '@amplitude/analytics-types';

class MyTransport implements Transport {
  async send(serverUrl: string, payload: Payload): Promise<Response | null> {
    // check example: https://github.com/amplitude/Amplitude-TypeScript/blob/main/packages/analytics-client-common/src/transports/fetch.ts
  }
}

amplitude.init(API_KEY, {
  transportProvider: new MyTransport(),
});