Identify
UpdatedSee our API documentation for code samples
This page can help you better understand when and how to use this API method. But, if you already know how it works and are ready to get started, you can go straight to our Data Pipelines API documentation and start writing code.
How it works
The Identify method helps you represent a user and their traits — the things you know about them, like their name, email address, and so on. When you use most of our libraries, like our JavaScript source, identifying a person keeps them in memory, so that future calls reference the identified person. This saves you the trouble of sending identifying information with every call.
See our API documentation for code samples
This page can help you better understand when and how to use this API method. But, if you already know how it works and are ready to get started, you can go straight to our Data Pipelines API documentation and start writing code.
When to send an identify call
While things vary based on the source library you use, you should send an identify
call when someone:
- First registers with your service
- Logs into your service or app
- Update their information—like when they change their email address, add a phone number, or set their subscription preferences
In general, you shouldn’t send an identify
call on every page load. Beyond the three cases above, additional identify calls are unnecessary and could cause you to hit your plan’s limits.
If you use our JavaScript source, we’ll automatically apply the right identity to calls after you identify a person. We store identity information in a cookie and local storage; if these values are present, you don’t need to send another identify
call unless you want to update the person’s traits.
If you use our other libraries, you’ll need to add the anonymousId
or userId
to your calls, but making additional identify
calls won’t fetch this information for you.
A typical call
A typical identify call is relatively straightforward. It contains a userId
and a traits
object. The userId
is a unique identifier for the person you’re identifying. The traitsA key-value pair that you associate with a person or an object—like a person’s name, the date they were created in your workspace, or a company’s billing date etc. Use attributes to target people and personalize messages. Attributes are analogous to traits in Data Pipelines. object contains information about the person, like their name, email address, and so on.
While this is the general shape of your call, our libraries actually capture much more information. See the full payload below. You can send additional objects in your call, overriding the information that our source libraries typically capture, but you’ll need to find documentation for your specific library for details.
analytics.identify('97980cfea0067', {
firstName: 'cool',
lastName: 'person',
email: 'cool.person@example.com'
});
The full payload
While your requests are typically short, our libraries capture much more information. This helps us provide context, not only for the person you identify, but the service you identify them from.
Customer.io and our libraries typically populate integrations
and timestamp values as shown in the payload below. If you use our JavaScript or mobile libraries, they’ll also populate context
for you. If you use our server-side libraries, you’ll need to populate context
yourself.
See common fields for more information about context, integrations, and timestamps in source payloads.
{
"type": "identify",
"traits": {
"name": "Cool Person",
"email": "cool.person@example.com",
"likes_baseball": true,
"games_attended": 5
},
"userId": "97980cfea0067",
"integrations": {
"All": true
},
"messageId": "string",
"receivedAt": "2019-08-24T14:15:22Z",
"sentAt": "2019-08-24T14:15:22Z",
"timestamp": "2019-08-24T14:15:22Z",
"version": 0,
"context": {
"active": true,
"ip": "string",
"locale": "string",
"userAgent": "string",
"channel": "browser",
"campaign": {
"name": "string",
"source": "string",
"medium": "string",
"term": "string",
"content": "string"
},
"page": {
"name": "string",
"path": "string",
"referrer": "string",
"search": "string",
"title": "string",
"url": "string",
"keywords": [
"string"
]
}
}
}
- anonymousId stringA unique substitute for a User ID in cases when you don’t have an absolutely unique identifier. Our libraries generate this value automatically to help you track people before they sign up, log in, provide their email, etc.
-
- active boolean
Whether a user is active.
This is usually used when you send an .identify() call to update the traits independently of when you’ve “last seen” a user.
- channel stringThe channel the event originated from.
Accepted values:
browser
,server
,mobile
- ip stringThe user’s IP address. This isn’t captured by our libraries, but by our servers when we receive client-side events (like from our JavaScript source).
- locale stringThe locale string for the current user, e.g.
en-US
. - userAgent stringThe user agent of the device making the request
-
- content string
- medium stringThe type of traffic a person/event originates from, like
email
, orreferral
. - name stringThe campaign name.
- source stringThe source of traffic—like the name of your email list, Facebook, Google, etc.
- term stringThe keyword term(s) a user came from.
- Additional UTM Parameters* string
-
- keywords array of [ strings ]A list/array of keywords describing the page’s content. The keywords are likely the same as, or similar to, the keywords you would find in an HTML
meta
tag for SEO purposes. This property is mainly used by content publishers that rely heavily on pageview tracking. This isn’t automatically collected. - name stringThe name of the page. Reserved for future use.
- path stringThe path portion of the page’s URL. Equivalent to the canonical
path
which defaults tolocation.pathname
from the DOM API. - referrer stringThe previous page’s full URL. Equivalent to
document.referrer
from the DOM API. - search stringThe query string portion of the page’s URL. Equivalent to
location.search
from the DOM API. - title stringThe page’s title. Equivalent to
document.title
from the DOM API. - url stringA page’s full URL. We first look for the canonical URL. If the canonical URL is not provided, we’ll use
location.href
from the DOM API.
-
- Enabled/Disabled integrations* boolean
- messageId stringA unique identifier for a Data Pipelines event, ensuring that each individual event is unique.
- receivedAt string (date-time)The ISO-8601 timestamp when Data Pipelines receives an event.
- sentAt string (date-time)The ISO-8601 timestamp when a library sends an event to Data Pipelines.
- timestamp string (date-time)The ISO-8601 timestamp when the event originally took place. This is mostly useful when you backfill data past events. If you’re not backfilling data, you can leave this field empty and we’ll use the current time or server time.
-
- createdAt string (date-time)We recommend that you pass date-time values as ISO 8601 date-time strings. We convert this value to fit destinations where appropriate.
- email stringA person’s email address. In some cases, you can pass an empty
userId
and we’ll use this value to identify a person. - Additional Traits* any typeTraits that you want to set on a person. These can take any JSON shape.
- type stringThe event type. This is set automatically by the request method/endpoint.
Accepted values:
identify
- userId stringThe unique identifier for a person. This value should be unique across systems, so you recognize the same person in your sources and destinations.
- version numberThe version of the API that received the event, automatically set by Customer.io.
Identifiers: User ID and Anonymous ID
You identify people with a unique value: either a userId
or an anonymousId
. The userId
is typically a UUID/ULID that represents that person across your backend services, though it can take any form you like as long as it’s unique. An anonymousId
is a value you assign to someone you don’t know yet. Every identify
call must have a User ID or an Anonymous ID.
User ID
User IDs are a more permanent identifier for a person, like a database ID that represents a person across all your backend services. Since these IDs are consistent across a customer’s lifetime, you should use them to identify
a person as soon as you know who they are.
Email as a userId
Customer.io Journeys lets you identify people by email address. So, as long as email addresses are unique to individual people in your use case, you can pass an email address as the userId
. We’ll parse emails and automatically set them as email
attributesA key-value pair that you associate with a person or an object—like a person’s name, the date they were created in your workspace, or a company’s billing date etc. Use attributes to target people and personalize messages. Attributes are analogous to traits in Data Pipelines. for you. This provides a handy way to identify people as leads when they’ve just provided their email address and then pass a database identifier for them when they become a customer, user, etc.
While this works really well for Customer.io Journeys, it doesn’t necessarily work for all destinations. Some destinations don’t support email addresses as userId
s, and some require a unique identifier that’s consistent across all your backend services. If you do pass email as a userId
, you should check that your integrations support email addresses as userId
s.
If you need to send email as an identifier, and some of your destinations don’t support that kind of model, you can filter the destinationsA destination is a place that you want to send data from one or more sources to. You can use your own workspace as a destination; send data to another service; or send data to your data warehouse. you send source data to using the integrations
object. Or you can modify your destination’s actions to exclude calls that use an email address as a userId
.
Anonymous ID
In many cases, you may not know who a person is yet — like when someone browses your website before they sign up for an account or log in. But in these cases, you may still want to capture information they voluntarily provide, events they perform, and pages they view. In these cases, you can reference a person with an Anonymous ID.
The Anonymous ID can be any pseudo-unique identifier. If you use our JavaScript library, we automatically generate anonymous IDs for you. But for our server and other libraries, you might use a session id. If you don’t have any readily available identifier, you can always generate new UUIDs.
Because our JavaScript library automatically generates anonymous IDs, you can send a request without the identifier and our library automatically inserts it. Here’s an example of a JavaScript identify
call for an anonymous user:
analytics.identify({
subscriptionStatus: 'inactive'
});
Customer.io Journeys doesn’t support anonymous identify calls yet
While many destinations support anonymous identify
calls, Customer.io Journeys does not support anonymous identify
calls yet. Journeys will ignore anonymous identify
calls because anonymous activity in Journeys is based on events.
This doesn’t mean you shouldn’t send anonymous identify
calls, even if you only connect to Journeys though. For example, if you use our JavaScript source, anonymous identify
calls store traits in local storage and attach them to subsequent identify
calls. This means that when you formally identify a person later, you don’t need to capture a bunch of traits at the same time; the JavaScript source will automatically associate their traits with their userId
.
Traits
Traits are things you know about your audience, like their email addresses, names, the plan
they’re on, and so on. You’ll include traits in identify
calls.
We reserve some traits that have semantic meanings for users because we handle them in special ways. For example, we always expect email
to be a string of the user’s email address. We’ll send this on to destinations that require an email address for their tracking.
You should only use reserved traits for their intended meaning.
Trait | Type | Description |
---|---|---|
address | Object | Street address of a user optionally containing: city , country , postalCode , state , or street |
age | Number | Age of a user |
avatar | String | URL to an avatar image for the user |
birthday | Date | User’s birthday |
company | Object | Company the user represents, optionally containing: name (String), id (String or Number), industry (String), employee_count (Number) or plan (String) |
createdAt | Date | Date the user’s account was first created. |
description | String | Description of the user |
email | String | Email address of a user |
firstName | String | First name of a user |
gender | String | Gender of a user |
id | String | Unique ID in your database for a user |
lastName | String | Last name of a user |
name | String | Full name of a user. If you only pass a first and last name we automatically fill in the full name for you. |
phone | String | Phone number of a user |
title | String | Title of a user, usually related to their position at a specific company. Example: “VP of Engineering” |
username | String | User’s username. This should be unique to each user, like the usernames of Twitter or GitHub. |
website | String | Website of a user |
Some destinations might represent these traits with slightly different names. For example, Mixpanel recognizes a $created
trait when a user is first created, while Intercom recognizes the same trait as created_at
. We attempt to handle all the destination-specific conversions for you automatically.
You can pass reserved traits using camelCase or snake_case. For example, in JavaScript you can match the rest of your camel-case code by sending firstName
, while in Python you can match your snake-case code by sending first_name
. That way the API never seems alien to your code base. However, you should keep in mind that some destinations might not support all reserved traits; if a destination doesn’t support a reserved trait and you send it in camelCase and snake_case from different sources, you may see both versions of your trait in the destination.