User Attributes

There are two types of attributes in Customer and Event attributes.

With Customer attributes, you’re sending us information about your users: things like first_name, is_account_manager or num_projects—any information that is important for your business. Event attributes are information that’s included in your event data, such as the information specific to a particular purchase.

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.

Every customer attribute is stored under a customer object, so you can access any attribute with {{customer.ATTRIBUTE_NAME}}.

Every event attribute is stored under an event object, so to access those attributes in your event triggered emails you’ll use {{event.ATTRIBUTE_NAME}} (the actual word event, not your event name).

How do I send you user attribute data?

Pass customer attributes through the _cio.identify() function in the JavaScript snippet. Alternatively, you can send user attributes using the REST API.

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 emailWe support valid RFC 5322 email addresses.
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.OptionalWe support:
- unix epoch
- unix 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

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.

 Attributes are stored as strings

If an attribute value is a number or an integer, you might want to use it in a math operation, but you’ll need to convert the value to a number/integer first. You can do this with plus: 0. For example, if you have an attribute called “number”, you could reformat it for math operations with {{assign number = customer.number | plus: 0}}—and then use {{number}} in the rest of your liquid.

Attribute data types

Currently, attribute values in are only simple strings, booleans or numbers.

We do, however, make your strings available as arrays or JSON objects inside your email templates for convenience (if they are correctly formatted as such), but we do not currently distinguish them as being different data types such as arrays and dictionaries, etc. You can use Liquid templating in your email templates to output values from your JSON values like: {{ }} but you cannot access these nested values in the same manner when segmenting or filtering.

Formatting your attributes

Let booleans be booleans, not strings. For example:

Good: is_account_manager: true
Bad: is_account_manager: 'true'

The boolean (true/false) shouldn’t have quotation marks around it.

Also, let numbers be numbers, not strings:

Good: num_projects: 15
Bad: num_projects: '15'

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—like their name, the date they were created in your workspace, etc. Use attributes to target people and personalize messages.. 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.

 Custom device attributes are only set by our Alpha-version SDKs

Custom device attributes are a new feature. Attributes beyond the default platform, last_used, and last_status are only set by our Alpha SDKs today. We’ll extend support to an official release in the near future.

    • _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.
    • app_version string
      The version of your app that a customer users. 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.
    • Custom Device Attributes* string
      Custom properties that you want to associate with the device.
  • id string
    Required The device token.
  • 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.
Copied to clipboard!