This article relates to both journy.io's SDKs and Twilio Segment SDKs.
journy.io’s Node.js library lets you record data from your platform, from your Node.js code.
All of journy.io’s server-side libraries are built for high-performance, so you can use them in your web server controller code. This library uses an internal queue to make identify
and track
calls non-blocking and fast. It also batches messages and flushes asynchronously to journy.io’s servers.
Getting Started
Make sure you’re using a version of Node that’s 14 or higher.
Run the relevant command to add journy.io’s Node library module to your
package.json
.npm install @segment/analytics-node
Initialize the
Analytics
constructor the module exposes with your journy.io SDK connector Write Key, like so:import { Analytics } from "@segment/analytics-node"; const analytics = new Analytics({ writeKey: "YOUR_WRITE_KEY", host: "https://analyze.journy.io", // Check Proxy Settings path: "/backend/v1/batch" });
Be sure to replace YOUR_WRITE_KEY
with your actual Write Key which you can find in journy.io by navigating to: Connections > API/SDK Connector and selecting the source tab and going to the Node.js tab.
This creates an instance of Analytics
that you can use to send data to journy.io for your project. The default initialization settings are production-ready and queue 20 messages before sending any requests.
There is an option in journy.io to set a proxy ("Use proxy domain") so traffic flows through your own domain. In that case, host
will have another value, pointing to your own domain.
Basic tracking methods
The basic tracking methods below serve as the building blocks of your journy.io tracking. They include Identify, Group, Track, and Page.
These methods correspond with those used in the journy.io Spec. The documentation on this page explains how to use these methods in Node.js.
Identify
For any of the different methods described on this page, you can replace the properties and traits in the code samples with variables that represent the data collected.
identify
lets you tie a user to their actions and record traits about them. It includes a unique User ID and/or anonymous ID, and any optional traits you know about them.
journy.io recommends that you make an identify
call:
After a user first registers
After a user logs in
When a user updates their info (for example, they change or add a new address)
Example of an anonymous identify
call:
analytics.identify({ anonymousId: "48d213bb-95c3-4f8d-af97-86b2b404dcfe", traits: { friends: 42 } });
This call identifies the user and records their unique anonymous ID, and labels them with the friends
trait.
Example of an identify
call for an identified user:
analytics.identify({ userId: "abc123", //Elon Musk — unique Id from database traits: { firstname: "Elon", lastname: "Musk", email: "elon.musk@tesla.com", friends: 42 } });
The call above identifies Elon by his unique User ID (the one you know him by in your database), and labels him with the firstname
, lastname
, email
, and friends
traits.
The identify
call has the following fields:
FIELD | DETAILS |
| The ID for this user in your database. Note: at least one of |
| An ID associated with the user when you don’t know who they are (for example, the anonymousId generated by |
| A dictionary of traits you know about the user. Things like: |
| A JavaScript date object representing when the identify took place. If the identify just happened, leave it out as journy.io uses the server’s time. If you’re importing data from the past make sure to send a |
| A dictionary of extra context to attach to the call. Note: |
Identifying users happen incremental: You can identify users with a subset of traits
; and later make another identify call with another subset of traits
. The result of both identify calls will be the union of all traits
.
To delete a traits
, you have to add them to the identify
call with value null:
analytics.identify({ userId: "abc123", //Elon Musk — unique Id from database traits: { firstname: "Elon", lastname: "Musk", email: null, friends: 42 } });
Find details on the identify method payload in journy.io’s Identify Spec.
Group
group
lets you associate an identified user with a group. A group could be a company, organization, account, project or team! It also lets you record custom traits about the group, like industry or number of employees.
journy.io recommends that you make a group
call:
After a user first registers, entering its company details.
After a user logs in. Make a group call for each account the user is part of.
When a user updates their info, make a group call for each account the user is part of.
Example group
call, adding user Elon Musk to account Tesla, as an 'admin':
analytics.group({ userId: "abc123", //Elon Musk — unique Id from database groupId: "xyz789", //Tesla Inc — unique Id from database traits: { name: "Tesla Inc", industry: "Automotive" } context: { relationship: { role: "admin", }, }, });
The group
call has the following fields:
FIELD | DETAILS |
| The ID for this user in your database. _Note: at least one of |
| An ID associated with the user when you don’t know who they are (eg., the anonymousId generated by |
| The ID of the group. |
| A dict of traits you know about the group. For a company, they might be things like |
| A dict containing any context about the request. |
| A |
To identify a group, without adding a user, you can use anonymousId
with the same value of the groupId
. It goes like this:
analytics.group({ anonymousId: "xyz789", //Tesla Inc — unique Id from database groupId: "xyz789", //Tesla Inc — unique Id from database traits: { name: "Tesla Inc", industry: "Automotive" } });
Group-calling accounts happen incremental: You can identify users with a subset of traits
; and later make another identify call with another subset of traits
. The result of both identify calls will be the union of all traits
.
To delete a traits
, you have to add them to the group
call with a null reference:
analytics.group({ anonymousId: "xyz789", //Tesla Inc — unique Id from database groupId: "xyz789", //Tesla Inc — unique Id from database traits: { name: "Tesla Inc", industry: null } });
Find more details about group
, including the group
payload, in the journy.io Spec.
Track
track
lets you record the actions your users perform, optionally within the context of an account. Every action triggers what we call an “event”, which can also have associated event metadata.
You’ll want to track events that are indicators of success for your site, like Signed Up, Item Purchased or Article Bookmarked.
To get started, we recommend tracking just a few important events. You can always add more later!
Example anonymous track
call:
analytics.track({ anonymousId: "48d213bb-95c3-4f8d-af97-86b2b404dcfe", event: "Car Sold", properties: { total_amount: 39999.99, currency: "usd", shippingMethod: "200-day" } });
Example identified track
call by a user Elon Musk:
analytics.track({ userId: "abc123", //Elon Musk — same Id as from identify call event: "Car Sold", properties: { total_amount: 39999.99, currency: "usd", shippingMethod: "200-day" } });
B2B example identified track
call by a user Elon Musk in the context of account Tesla, back on Dec 12th 2015:
analytics.track({ userId: "abc123", //Elon Musk — same Id as from identify call event: "Car Sold", properties: { total_amount: 39999.99, currency: "usd", shippingMethod: "200-day" }, timestamp: "2015-12-12T19:11:01.249Z", context: { groupId: "xyz789" }, //Tesla Inc — same Id as from group call });
This example track
call tells us that Elon Musk triggered the Car Sold event with a revenue of $39999.99 and chose your hypothetical ‘200-day’ shipping, back on Dec 12th 2015.
track
event properties can be anything you want to record. In this case, revenue and shipping method.
The track
call has the following fields:
FIELD | DETAILS |
| The ID for this user in your database. _Note: at least one of |
| An ID associated with the user when you don’t know who they are (for example, the anonymousId generated by |
| The name of the event you’re tracking. We recommend human-readable names like |
| A dictionary of event metadata for the event. If the event was |
| A JavaScript date object representing when the track took place. If the track just happened, leave it out and we’ll use the server’s time. If you’re importing data from the past make sure you to send a |
| A dictionary of extra context to attach to the call. Note: |
Find details on best practices in event naming as well as the track
method payload in the journy.io Spec.
Page
The page
method lets you record page views on your website, along with optional extra information about the page being viewed. It is also user to record screen views in your app/on your platform.
Important Note:
When a
name
is provided in the page call, journy.io will collect those calls and stores them as (app) screen objects.Without name, journy.io regards those calls as (website) page objects.
If you’re using our client-side set up in combination with the Node.js library, page calls are already tracked for you by default. However, if you want to record your own page views manually and aren’t using our client-side library, read on!
Example page
call, where a user Elon Musk visits the pricing page:
analytics.page({ userId: "abc123", //Elon Musk — same Id as from identify call category: "Web", name: "pricing page", properties: { url: "https://www.example.com/pricing", title: "Pricing Page | Example", referrer: "https://www.example.com/product" } });
B2B example page
call, where a user Elon Musk visits the pricing page, when being in account Tesla, back on Dec 12th 2015:
analytics.page({ userId: "abc123", //Elon Musk — same Id as from identify call category: "Web", name: "pricing page", properties: { url: "https://www.example.com/pricing", title: "Pricing Page | Example", referrer: "https://www.example.com/product" }, timestamp: "2015-12-12T19:11:01.249Z", context: { groupId: "xyz789" } //Tesla Inc — same Id as from group call });
The page
call has the following fields:
FIELD | DETAILS |
| The ID for this user in your database. _Note: at least one of |
| An ID associated with the user when you don’t know who they are (eg., the anonymousId generated by |
| The category of the page. Useful for things like ecommerce where many pages often live under a larger category. |
| The name of the page, for example Signup or Home. Providing a name will determine if journy.io will record a screen (with name) or a page (without name). |
| A dictionary of properties of the page. A few properties specially recognized and automatically translated: |
| A JavaScript date object representing when the track took place. If the track just happened, leave it out and we’ll use the server’s time. If you’re importing data from the past make sure you to send a |
| A dictionary of extra context to attach to the call. Note: |
Find details on the page
payload in the journy.io Spec.
Configuration
The second argument to the Analytics
constructor is an optional list of settings to configure the module.
const analytics = new Analytics({ writeKey: "<YOUR_WRITE_KEY>", host: "https://analyze.journy.io", path: "/backend/v1/batch", maxRetries: 3, maxEventsInBatch: 15, flushInterval: 10000, disable: false })
SETTING | DETAILS |
| The key that corresponds to your journy.io SDK connector |
| The base URL of the API. The default is: “https://analyze.journy.io” |
| The API path route. The default is: “backend/v1/batch” |
| The number of times to retry flushing a batch. The default is: |
| The number of messages to enqueue before flushing. The default is: |
| The number of milliseconds to wait before flushing the queue automatically. The default is: |
| The maximum number of milliseconds to wait for an http request. The default is: |
| Disable the analytics library for testing. The default is: |
| A custom HTTP Client implementation to support alternate libraries or proxies. Defaults to global fetch or node-fetch for older versions of node. |
Graceful shutdown
Avoid losing events after shutting down your console. Call .closeAndFlush()
to stop collecting new events and flush all existing events. If a callback on an event call is included, this also waits for all callbacks to be called, and any of their subsequent promises to be resolved.
await analytics.closeAndFlush() // or await analytics.closeAndFlush({ timeout: 5000 }) // force resolve after 5000ms
Here’s an example of how to use graceful shutdown:
const app = express() const server = app.listen(3000) const onExit = async () => { await analytics.closeAndFlush() server.close(() => { console.log("Gracefully closing server...") process.exit() }) } ['SIGINT', 'SIGTERM'].forEach((code) => process.on(code, onExit))
Error handling
To keep track of errors, subscribe and log all event delivery errors by running:
const analytics = new Analytics({ writeKey: "<YOUR_WRITE_KEY>", host: "https://analyze.journy.io", path: "/backend/v1/batch" }) analytics.on("error", (err) => console.error(err))