Direct API Integration
In this article, you’ll learn how to get your customer data flowing into our system: your list of users, their properties, and information about events (activities) they’re performing inside your app.
When you sign up for a new Userlist account, your list of users is blank. User profiles will start appearing there once you start pushing data for each individual user. When that happens depends on how your developer implements the integration. For example, the Rails library has an import task that gets all users into the system at once (more about that below).
Alternatively, Segment users can set up their integration in a few clicks. View this guide for instructions on Segment.
Start planning your campaigns as early as possible — this way you'll know what properties and events to track. Download these free worksheets to speed up the process.
How behavior tracking works
You can track user behavior by sending us user data as well as events.
User data (properties) represents the current state of the user and doesn’t have a temporal aspect — we only store the latest version. One of the properties might have changed in the past, but you cannot tell just by looking at it. User properties include things like their name, company role, their current payment plan, and anything else you prefer to track — like total number of created tasks (in a project management app for example).
Events are composed of an event name, a timestamp to describe when the event occurred, a set of additional properties (specific to the event type), and a user that triggered that event. Events are important activities performed by the user inside your application. E.g. in a project management app, events might include things like completed a task, created a new project, etc.
In addition to custom events you send us from your application, Userlist automatically records events that happen inside our system (like when users open a message, click a link, join a segment, etc.). So you don’t have to worry about tracking these things yourself.
Setting up the integration
Integrating Userlist into your application is done by sending user data and events into the system via our HTTP JSON API or via our Segment integration. We also offer libraries for some frameworks and languages that help with the integration:
Language / Framework | GitHub |
---|---|
Ruby | https://github.com/userlist/userlist-ruby |
Ruby on Rails | https://github.com/userlist/userlist-rails |
JavaScript | https://github.com/userlist/userlist-javascript |
PHP | https://github.com/userlist/userlist-php |
Request payloads and responses
The Push API expects payloads as JSON as well as responds with JSON.
It’s recommended to set the Accept
and Content-Type
accordingly.
1
2
Accept: application/json
Content-Type: application/json; charset=utf-8
Timestamps are expected to be strings formatted according to ISO 8601:
YYYY-MM-DDTHH:MM:SS+HH:MM
. If no time zone is given, we’ll assume UTC.
Object keys, as well as event names, will be normalized to snake_case
.
You’re free to use any format you like for these, just be aware that
we’ll store it in snake_case
way.
Userlist will automatically recognize custom properties as timestamps when the value is formatted according to ISO 8601.
Limits
The Push API has a rate limit of 1000 requests per minute per account. Additionally, there is also a 100KB request size limit.
Authentication
To start sending data into Userlist, you first have to get your Push API Key. It is used to authenticate your requests to the Push API and connect the data with your account. Keep this Push API Key secure, or an attacker will be able to mess with your data and automation.
All requests to our Push API need to have the Push API Key in the
Authorization
header in this format:
1
Authorization: Push your-push-api-key-here
Errors
When things go wrong, the Push API will respond with appropriate HTTP status codes. Status codes in the 2xx range can be considered as successful. Status codes in the 4xx range indicate a problem with the initial request. Status codes in the 5xx range indicate errors on the server.
The Push API will also respond with a JSON body describing the error in more detail.
1
2
3
4
{
"status": 422,
"errors": ["User must exist"]
}
Tracking user data
User data can be tracked by sending POST
requests to
https://push.userlist.com/users
. The
identifier
is a unique identifier for that user within your
application. This can either be the user’s primary key in your database,
a generated tracking identifier or their email address (we don’t
recommend using email address though, because it’s less reliable).
Whatever you choose, please keep in mind that it’ll be the way
Userlist identifies this user moving forward.
You can also send marketing leads to Userlist without an identifier
,
as long as you include an email
.
The signed_up_at
parameter accepts timestamps in ISO 8601 format.
The custom properties
can be any format you like, and their type
will be inferred.
Parameter | Required |
---|---|
identifier | No1 |
No1 | |
signed_up_at | No |
properties | No |
relationships2 | No |
company2 | No |
companies2 | No |
1 Either an identifier or an email address is required.
2 These parameters are mutually exclusive. Please only provide one of them.
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /users HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e",
"email": "delaney.jones@example.net",
"properties": {
"first_name": "Delaney",
"last_name": "Jones"
},
"relationships": [
{
"company": "eb66093e-62be-47fb-82bc-64da1bd120b0",
"properties": {
"role": "owner"
}
}
]
}
When successful, the Push API will respond with 202 Accepted
and an
empty body. Afterwards, we’ll process the data and it’ll show up inside
Userlist within a few moments.
Deleting users
You can remove user data by sending a DELETE
request to
https://push.userlist.com/users
. The body of the request is the same as for creating or updating users. We’ll
process your deletion request within a few of moments and remove the
user, all their events, as well as all their messages. All campaigns
will immediately be stopped. If you send any data or event with this
property after requesting a deletion, we’ll treat it as fresh and create
a new user.
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
DELETE /users HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e"
}
When successful, the Push API will respond with 202 Accepted
and an
empty body. Afterwards, we’ll process the request and the user will
be removed from Userlist within a few moments.
Tracking company data
Company data can be tracked by sending POST
requests to
https://push.userlist.com/companies
. The only required parameter is
identifier
which is a unique identifier for that company within your
application. This can either be the company's primary key in your database,
or some kind of generated tracking identifier. Whatever you choose, make please keep in mind that it’ll be the way
Userlist identifies this company moving forward.
Parameter | Required |
---|---|
identifier | Yes |
name | No |
signed_up_at | No |
properties | No |
relationships1 | No |
user1 | No |
users1 | No |
1 These parameters are mutually exclusive. Please only provide one of them.
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
POST /companies HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"identifier": "eb66093e-62be-47fb-82bc-64da1bd120b0",
"name": "Example, Inc.",
"properties": {
"industry": "Testing",
"billing_plan": "enterprise"
},
"relationships": [
{
"user": {
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e",
"email": "delaney.jones@example.net",
"properties": {
"first_name": "Delaney",
"last_name": "Jones"
}
}
"properties": {
"role": "owner"
}
}
]
}
When successful, the Push API will respond with 202 Accepted
and an
empty body. Afterwards, we’ll process the data and it’ll show up inside
Userlist within a few moments.
Deleting companies
You can remove company data by sending a DELETE
request to
https://push.userlist.com/companies
. The body of the request is similar to the one you sent when sending the company data initially. We’ll
process your deletion request within a few of moments and remove the
company, all its events, as well as all relationships to users. The users that were part of that company are not deleted automatically. If you send any data or event with this
company after requesting a deletion, we’ll treat it as fresh and create
a new company record.
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
DELETE /companies HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"identifier": "eb66093e-62be-47fb-82bc-64da1bd120b0"
}
When successful, the Push API will respond with 202 Accepted
and an
empty body. Afterwards, we’ll process the request and the company will
be removed from Userlist within a few moments.
Tracking relationships
Userlist allows you to track relationships between users and companies. It's possible to track many-to-many relationships between users and companies. Creating a relationship needs at least two pieces of information: a user
and a company
. Both the user
and company
properties can be either an identifier or a user or company object with a structure like the one described above.
Parameter | Required |
---|---|
user | Yes |
company | Yes |
properties | No |
Here's what an example request might look like:
1
2
3
4
5
6
7
8
9
10
11
12
POST /relationships HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"user": "3d70d1d4-484a-4e72-8857-916ee525214e",
"company": "eb66093e-62be-47fb-82bc-64da1bd120b0",
"properties": {
"role": "admin"
}
}
When successful, the Push API will respond with 202 Accepted
and
an empty body. Afterwards, we’ll process the data and it’ll show up
inside Userlist within a few moments.
Deleting relationships
You can remove relationship data by sending a DELETE
request to
https://push.userlist.com/relationships
. We’ll
process your deletion request within a few of moments and remove the
relationship between this user and this company. Both the associated user and company are not deleted automatically.
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
9
DELETE /relationships HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"user": "3d70d1d4-484a-4e72-8857-916ee525214e",
"company": "eb66093e-62be-47fb-82bc-64da1bd120b0"
}
When successful, the Push API will respond with 202 Accepted
and an
empty body. Afterwards, we’ll process the request and the relationship will
be removed from Userlist within a few moments.
Tracking events
Similar to tracking user or company data, tracking events works by sending POST
requests to https://push.userlist.com/events
. Tracking an event
requires at least two pieces of information: a name
, and a user
or company
identifier. Other parameters are optional.
Parameter | Required |
---|---|
name | Yes |
user | Yes (unless there's a company) |
company | Yes (unless there's a user) |
occurred_at | No |
properties | No |
Here’s what an example request might look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /events HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"name": "product_purchased",
"user": "3d70d1d4-484a-4e72-8857-916ee525214e",
"properties": {
"product": "Flowers",
"price": "$12.99"
}
}
When successful, the Push API will respond with 202 Accepted
and
an empty body. Afterwards, we’ll process the data and it’ll show up
inside Userlist within a few moments.
Referencing and embedding resources
In all payload that allow referencing another resources by their identifier (like an event that references the user that performed the event) it's also possible to embed the resource in place.
The following example shows a payload that references a user by their identifier.
1
2
3
{
"user": "3d70d1d4-484a-4e72-8857-916ee525214e"
}
This is equivalent to the following expanded payload.
1
2
3
4
5
{
"user": {
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e"
}
}
This allows complex updates of multiple related resources in the same transaction. The following example shows how to update a nested user resource within the parent payload.
1
2
3
4
5
6
7
8
9
{
"user": {
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e",
"properties": {
"first_name": "Delaney",
"last_name": "Jones"
}
}
}
Nested properties
Nested properties will help structure your data, especially if you're managing multiple products in one Userlist account.
E.g. a billing plan property for Product A will look like this: user.product_a.billing_plan
.
Here's an example payload:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /users HTTP/1.1
Accept: application/json
Authorization: Push your-push-api-key-here
Content-Type: application/json; charset=utf-8
{
"identifier": "3d70d1d4-484a-4e72-8857-916ee525214e",
"properties": {
"product_a": {
"billing_plan": "pro"
},
"product_b": {
"billing_plan": "free"
}
}
}
However, we currently don't support namespacing for event names. You can send product_a.project_created
, but we'd normalize that to product_a_project_created
.
Client-side tracking
In addition to server-side tracking, Userlist also allows client-side tracking — via the same tracking script that powers in-app messages. See these articles for details:
- Setting Up In-App Messages (Developer Guide) — how to add a JavaScript snippet and generate user tokens
- Client-Side Tracking — how to use that script for sending user events and properties
Best practices for a successful integration
A successful integration isn’t just a matter of technical setup. It’s equally important to be strategic and consistent in your user tracking — so that the data reflects your business goals and makes sense to all team members down the road.
Before you start the integration process, you need to make the following decisions:
- Figure out what properties and events need to be tracked. What properties and events reflect user progress the best, and describe the milestones in your typical user journey?
- Choose a naming convention and use it to document these properties and events before you implement them in code.
For further reading, we recommend this article on naming conventions published by the team at Segment.
Here are some of our recommendations:
- Use a framework for naming events (e.g. Object-Action framework)
- Track time instead of boolean — this will enable you to segment more meaningfully and send better communications, since you know when the user performed a certain event last time (as opposed to a boolean)
- For dates without time we recommend to use an
_on
suffix (e.g.next_billing_on
), and for dates with time an_at
suffix (e.g.trial_expires_at
) - Be consistent with vocabulary and phrase structure. Our
recommendation for event names is resource name + verb in past
tense, e.g.
message_sent
,template_created
- Be consistent with capitalization and characters between words —
e.g.,
created-project
vscreated_project
(this isn't mission-critical as we normalize it anyways, but still a good practice)
What exactly should I track?
You don't need to reinvent the wheel. Sure, many properties are specific to your industry, but many of them are similar to most SaaS companies. To help you with planning, we created a set of free planning worksheets (12 pages, printable PDF) to use as a baseline.