Identify

Updated

 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.

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 string
    A 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 string
      The channel the event originated from.

      Accepted values:browser,server,mobile

    • ip string
      The 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 string
      The locale string for the current user, e.g. en-US.
    • userAgent string
      The user agent of the device making the request
      • content string
      • medium string
        The type of traffic a person/event originates from, like email, or referral.
      • name string
        The campaign name.
      • source string
        The source of traffic—like the name of your email list, Facebook, Google, etc.
      • term string
        The 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 string
        The name of the page. Reserved for future use.
      • path string
        The path portion of the page’s URL. Equivalent to the canonical path which defaults to location.pathname from the DOM API.
      • referrer string
        The previous page’s full URL. Equivalent to document.referrer from the DOM API.
      • search string
        The query string portion of the page’s URL. Equivalent to location.search from the DOM API.
      • title string
        The page’s title. Equivalent to document.title from the DOM API.
      • url string
        A 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 string
    A 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 string
      A 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 type
      Traits that you want to set on a person. These can take any JSON shape.
  • type string
    The event type. This is set automatically by the request method/endpoint.

    Accepted values:identify

  • userId string
    The unique identifier for a person. This value should be unique across systems, so you recognize the same person in your sources and destinations.
  • version number
    The 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 userIds, 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 userIds.

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.

TraitTypeDescription
addressObjectStreet address of a user optionally containing: city, country, postalCode, state, or street
ageNumberAge of a user
avatarStringURL to an avatar image for the user
birthdayDateUser’s birthday
companyObjectCompany the user represents, optionally containing: name (String), id (String or Number), industry (String), employee_count (Number) or plan (String)
createdAtDateDate the user’s account was first created.
descriptionStringDescription of the user
emailStringEmail address of a user
firstNameStringFirst name of a user
genderStringGender of a user
idStringUnique ID in your database for a user
lastNameStringLast name of a user
nameStringFull name of a user. If you only pass a first and last name we automatically fill in the full name for you.
phoneStringPhone number of a user
titleStringTitle of a user, usually related to their position at a specific company. Example: “VP of Engineering”
usernameStringUser’s username. This should be unique to each user, like the usernames of Twitter or GitHub.
websiteStringWebsite 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.

Copied to clipboard!
  Contents
Is this page helpful?