User Attributes

Attributes represent the things you know about your audience—their name, preferences, email address, etc.

How it works

Attributes are data points about people in your audience: things like first_name, is_account_manager or num_projects—any information that is important for your business.

Attributes can be a string, boolean or a number, and can be used to create data-driven segments or to include information in your emails. You will also be able to use these attributes in emails that you send by typing {{customer.first_name}} in your email. Any email can access a customer attribute, but event attributes are available only in event triggered emails.

Attributes are stored in the customer object, so you can access any attribute with {{customer.ATTRIBUTE_NAME}}.

 Avoid storing sensitive information in

You should limit the personal data you store to what you’ll use in You should not store sensitive data passwords and other tokens in While we take every effort to protect you and your customers’ data, limiting the data you share outside your backend systems limits potential security concerns and helps you respect your customers’ privacy.

When troubleshooting support tickets, you can grant support access to your workspace for a limited time. When you grant access, support personnel can see your audience’s attributes and the data you store.

Attribute names are case sensitive

Before you map out the attributes that you want to store, you should know that attribute names are case sensitive. So, if you send an attribute for some people called first_name and attribute called First_name for other people, you’ll have two different attributes in your workspace.

This can make it hard to personalize messages with liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable {{customer.first_name}}. or add the right people to segmentsA group of people who match a series of conditions. People enter and exit the segment automatically when they match or stop matching conditions.—because not everybody will have the same attribute.

As you get started, make sure that you use a consistent naming scheme for attributes so that it’s easy to target attributes in segments or with liquid. You can use the data index to identify inconsistencies in your attribute names.

We also recommend that you avoid using spaces, periods or special characters in attribute names, because it can make it hard to reference your attributes with liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable {{customer.first_name}}..

How do I send attribute data?

Pass customer attributes through the _cio.identify() function in the JavaScript snippet, our REST API, or any of our libraries.

Here’s an example of how to send custom user attributes:

<script type="text/javascript">
      id:         'userid_34', // must be unique per customer
      email:      '',
      created_at: 1333688268, // seconds since the epoch (January 1, 1970)

      // Custom user attributes
      first_name:  'Joe',
      plan_name:  'free',
      is_account_manager: true,
      num_projects:  15

Internal attributes

We reserve the use of all user attributes beginning with an underscore _ for internal use only. These attributes aren’t eligible for segmentation, searching, or triggering of campaigns.

For example: if you have a segment for “Americans” built on the attribute country being equal to “America”, that will work. If you instead use _country, you can still send us that attribute, but any customers with it will not be eligible for segmentation, no matter what its value.


The values that identify a unique person are called Identifiers; typically, these are id and email. In most cases, you can treat these values as attributes.

If your workspace supports multiple identifiers—email, ID, etc—you can create a person without setting all of their identifiers. You might need to set or change these attribute values on people in your workspace after you add them. Like other attributes, unless they are already set.

If an identifier is already set, you can change it:

Create a segment based on user attributes

Once you are sending us custom attributes, you’ll have a lot of flexibility in how you can use them to create data-driven segments. Here’s a simple example for the attribute is_account_manager:


You can also set the numeric value of an attribute:


In fact, there’s a great deal of flexibility in how you can define your segments:

Segmentation options
Segmentation options

You can also check whether an attribute is between two values. For example, if you want to isolate customers with an NPS score of 5-8 (inclusive), you can do so with the “is between” option in the attribute dropdown:


Create segment based on event attributes

If you’re including event data in your events, you’ll be able to segment based on that information. For example, if you’d like to know who bought a t-shirt:


You’ll be able to segment by one piece of event data in each condition.

Also, if you want to know who bought a t-shirt recently (within the last month, maybe), you can do that too. Click Refine and add your timeframe:


Important things to know

Reserved attributes has reserved attributes to support core functionality in the platform.

AttributePurposeRequiredData Format
idA unique identifier for people. If the id does not yet exist, we create a new person.When importing by idOur default id limit is set to 150 characters. All valid utf characters are allowed.
emailA person’s email address. If your workspace uses email as a unique identifier (the default setting for new workspaces), and the email address does not yet exist, we create a new person. The TO line of your email templates is prefilled with this attribute.When importing by emailValid RFC 5322 email addresses.
cio_idA unique, immutable identifier set by, set automatically when you add a person.Created by Customer.iostring
created_atRecommended. Holds the date when a profile was created. This value lets you to take advantage of timestamp operators in segments and helps you determine the age of a person’s profile.Optionalunix epoch
_created_in_customerio_atThe date-time when a person was added in This value can be different from created_at. In the API, this value is represented by the timestamp for the cio_id attribute.Created by Customer.iounix epoch
unsubscribedDetermines whether a person is subscribed or unsubscribed from your campaigns and newsletters. (reference)OptionalWe support any case of true (i.e. TRUE, true, tRUe, etc.) or ‘1’ to represent unsubscribed. Any other value is considered “false”, or subscribed.
mobile_ad_idUsed to record either Apple’s Advertising Identifier (IDFA) or Android’s Advertising ID (AAID). This id can improve match accuracy in Google or Facebook Ads when using Ad Audiences.OptionalApple’s Advertising Identifier (IDFA) or Android’s Advertising ID (AAID)
email_sha256To keep your data secure, you can hash your customer email using the SHA256 algorithm before sending it to your account. This field is only used in Ad Audiences and cannot be used to send messages.OptionalValid encoded sha256
mobile_ad_id_sha256To keep your data secure, you can hash the mobilead_id using the SHA256 algorithm before sending it to your account. _This field is only used in Ad Audiences.OptionalValid encoded sha256 has also reserved these object and relationship attributes:

AttributePurposeRequiredData Format
cio_object_idA unique, immutable identifier for objects provided by If this does not yet exist in your workspace, we create a new object.When importing by cio_object_id
object_idA unique identifier for objects. If the object_id does not yet exist, we create a new object.When importing by object_idOur default id limit is set to 150 characters. All valid UTF characters are allowed.
relationshipUsed to reference relationships in liquid. Cannot be used as the name of an object attribute.To reference relationships in liquid

Using attributes in messages

Customer attributes come from the user’s profile and are available in any message type. They are pulled into your message content by using Liquid code like {{ customer.attribute_name }} in your message templates.

Event attributes come from the data you include in the events you send and are only available in event-triggered campaigns. They are pulled into your message content by using Liquid code like {{ event.attribute_name }} in your message templates.

Attribute data

You can store attributes as any JSON data type, including arrays, objects, and complex arrays of objects. You should store attributes in formats true to their type: you should store boolean values as booleans (e.g. true instead of "true"), and numbers as numbers, not strings (e.g. 42 instead of "42").

You’ll access attributes in segmentsA group of people who match a series of conditions. People enter and exit the segment automatically when they match or stop matching conditions., filters, liquidA syntax that supports variables, letting you personalize messages for your audience. For example, if you want to reference a person’s first name, you might use the variable {{customer.first_name}}., and so on using JSON dot notation. For example, if you store your customer’s address as an object with a property called city, you could access the city in liquid using {{ }}.

If you store an attribute containing an array of address objects, you might access the city for the first address with {{ customer.address[0].city }}. Remember, arrays are zero-indexed.

In segments, you can use array notation without an index to loop over the entire array. For example, if you wanted to find any address in an array of address objects matching a specific city, you could use customer.address[].city. If you only wanted to use the first address object, you would keep the index, using customer.address[0].city. See complex values in segments for more information.

Chronology of attribute updates

Attribute updates (identify() API calls) are processed in the order we receive them. However, due to various network conditions, we can’t guarantee that we will receive them in the order you send them. To ensure your attributes end up with the values you intend, you’ll want to add an additional attribute to each API call named _timestamp. The _timestamp value should be a UNIX timestamp that represents the date and time the update was made.

When we receive multiple attribute updates for the same user:

  • If the updates do not include a _timestamp value, the attribute values in the last update we process will prevail.
  • If the updates include a _timestamp value, the attribute values in the update having the newest _timestamp will prevail.
  • If the updates include the same _timestamp value, the attribute values in the first update will prevail. Values for existing attributes sent in subsequent updates will be ignored. Values for attributes sent in subsequent updates - that were not sent in the first update - will not be ignored. They will be added if they do not already exist. If they do already exist, they will be updated so long as the _timestamp value for this call is newer than the timestamp of the last update those attributes were a part of.

Please note that this is accurate down to the second. If requests are sent within microseconds of each other, there is still the potential that they could be out of order.

Here is an example set of API calls for our US region containing a _timestamp value. If your account is in the EU region, make sure you use


curl -i \
-X PUT \
-u site-id:api-key \
-d _timestamp=1522081942 \
-d Attr1='attr1_val3_sent1st_timestamp=1522081942(newer)'


curl -i \
-X PUT \
-u site-id:api-key \
-d _timestamp=1522081941 \
-d Attr1='attr1_val1_sent2nd_timestamp=1522081941(older)' \
-d Attr2='attr2_val2_sent2nd_timestamp=1522081941(older)'

And here is the final outcome:

Final outcome.
Final outcome.

Notice we did not drop the second request with the older _timestamp value. Instead, we still processed the second request but only updated the attribute (Attr2) that did not already exist from a call that had a newer _timestamp value.

Removing attributes

To remove unwanted attributes you’ll need to remove the attribute from all profiles. As soon as no one in your Peoples list is using the attribute, it will be effectively removed. You can remove the attribute from profiles in bulk by:

  1. Using our API to update every profile in your account to have a null/empty string ("") as their value for the unwanted attribute names, or
  2. Using our CSV import feature to overwrite the attribute data with empty values.
  3. Using an Attribute Update in a campaign to remove the attribute. Read more on how here.

If any of the deleted attributes belong to profiles that have been deleted, they may take 24 hours or more to completely disappear from your account.

If you notice they still persist even longer, please reach out to with examples so we can investigate.

Mobile device attributes

Devices have their own 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.. We collect last_status automatically. We also set a last_used attribute based on either the timestamp in your request to add or update a device, or the time of the request itself. When you add or update a device using our SDKs, we’ll set the platform automatically for you; otherwise, you must send the platform with each request to our API.

If you use our SDKs, you’ll automatically collect additional device attributes by default. Whether or not you use our SDKs, you can also set custom attributes for each device—similar to attributes you set for people, but specific to each mobile device token.

When you go to a person’s Devices tab, you’ll see each device’s PLATFORM, DEVICE LAST USED and LAST RESULT attributes. Click a device to reveal additional information and attributes attached to it.

You can use device attributes anywhere you would otherwise use a person’s other attributes—True/False branches, Action Conditions, or segmentsA segment is a group of people in your audience that you want to target with campaigns, messages, etc. You can join groups of people manually, or by attribues and event data.. But you cannot use device attributes with Liquid today.

See device attributes on the devices tab of a person's page
See device attributes on the devices tab of a person's page

Collect custom device attributes

When you identify or update a device, you can pass an attributes object containing additional attributes specific to a device. If you use our SDKs, we capture a number of predefined attributes automatically—unless you disable automatic attribute collection.

You can segment and filter audience members based on these attributes. However, device tokens can change—sometimes based on user behavior, like when a person uninstalls and reinstalls your app, and sometimes based on your messaging service (FCM or APNs). When you set attributes on a device, consider wether you need to retain an attribute past the life of the device token, and if an attribute is truly relevant to the device.

The following attributes are automatically collected by alpha versions of the SDK, set automatically by, or available to our APIs. If you disable automatic attribute collection in the SDK, we’ll stop automatically collecting properties other than platform, last_used, and last_status.

  • id string
    Required The device token.
    • _last_status string
      The delivery status of the last message sent to the device—sent, bounced, or suppressed. An empty string indicates that that the device hasn’t received a push yet.

      Accepted values:,bounced,sent,suppressed

    • app_version string
      The version of your app that a customer uses. You might target app versions to let people know when they need to update, or expose them to new features when they do.
    • cio_sdk_version string
      The version of the SDK in the app.
    • device_locale string
      The four-letter IETF language code for the device. For example, en-MX (indicating an app in Spanish formatted for a user in Mexico) or es-ES (indicating an app in Spanish formatted for a user in Spain).
    • device_model string
      The model of the device a person uses.
    • device_os string
      The operating system, including the version, on the device.
    • push_enabled string
      If "true", the device is opted-in and can receive push notifications.

      Accepted values:true,false

    • Custom Device Attributes* string
      Custom properties that you want to associate with the device.
  • last_used integer  (unix timestamp)
    The timestamp when you last identified this device. If you don’t pass a timestamp when you add or update a device, we use the time of the request itself. Our SDKs identify a device when a person launches their app.
  • platform string
    Required The device/messaging platform.

    Accepted values:ios,android

Copied to clipboard!
Is this page helpful?