Object Type Attributes

Prev Next

Object Type is a user attribute type that allows you to store a whole real-world entity as one connected attribute instead of scattering it across separate, unrelated attributes.

In real-life use cases, the things you care about are rarely a single value. They are entities made of several fields that only mean something together:

  • An order with its total, currency, status and shipping address

  • A subscription with its plan, status and renewal date

  • A booking with its reference, destination and lead passenger

  • A membership with its tier, join date and points

With flat attributes, each of those fields becomes its own standalone attribute and the link between them is lost. For example, membership_name, membership_status, and membership_renewal_date end up as three attributes with nothing connecting them. With Object Type, all of them live inside one object, under one attribute.

Object keys can also contain sub-object keys, and those can contain one further level, so a structure such as last_order.address.city is stored as it is. This keeps the relationships inside your data intact and makes the whole entity usable in segmentation, personalization, expressions, and export.

How Object Type Attributes Work

Object Type attributes follow the same principles as Array of Objects attributes, with two important differences: an object attribute holds exactly one object, not a list, and it supports three levels of nesting instead of two.

Structure is defined in the panel first

The object attribute and its object keys, sub-object keys and secondary sub-object keys must be created in the panel before data is sent. Auto-detection from incoming traffic is not supported. This keeps ingestion predictable and guarantees that every stored object follows a known schema.

Only registered keys are accepted

Object data must be sent through the dedicated object_attributes.custom field. Keys that are not registered in the panel are dropped during ingestion. Sending an object through the plain attributes field is rejected with an explicit error, because attributes accepts flat scalar values only.

Updates deep-merge

A payload that carries a subset of sub-keys updates only those sub-keys and leaves the rest of the object untouched, so you never have to re-send the whole object to change one field. This follows RFC 7386 merge-patch semantics, with "<null>" as the sentinel that clears a single sub-key.

One bad sub-key does not fail the payload

A sub-key that fails validation is dropped on its own. The rest of the object is still ingested, and the drop is recorded so it can be surfaced per field in the Onboarding Center rather than disappearing silently.

Data becomes segmentable in near real time

Object attributes follow the same availability behavior as flat attributes. Data is typically available for segmentation within seconds of ingestion.

Example Use Case: Last Order

Business Scenario

A retail partner migrating wants to:

  • Store the customer's last order as one attribute instead of six separate ones

  • Keep the order's total, currency, status and shipping address connected to each other

  • Segment customers whose last order shipped, was over 50, and went to a specific city

  • Personalize the message with a field from that same order

Before you begin

To follow this article end to end, make sure you have:

  • Access to the Attributes and Events page in the InOne panel, with permission to create custom attributes.

  • Your partner name and request token for the Insider One APIs. For more information, see the API Authentication article.

  • At least one free Object Type attribute slot on your panel. Each panel supports 20 Object Type attributes.

Note: Object Type is available on custom attributes only. Default attributes currently cannot use the Object data type.

Step 1. Create the Object Type Attribute

Before you can send and activate structured data, define the object attribute in the Attributes and Events section. Object attributes cannot be used in ingestion or segmentation until they are registered.

Navigate to Audience > Attributes and Events, open the Attributes tab, and click Create. The Create Custom Attribute drawer opens, where you set a system name and a display name that appears on the listing pages.

In the drawer:

  1. Enter the Attribute System Name and the Attribute Display Name.

  2. Select Object as the Data Type.

  3. Add your object keys.

  4. Set the PII, segmentation, tag, and note options as needed.

  5. Click Create Attribute.

A last_order object attribute, for example, holds these keys:

Key Name

Type

total

Number

currency

String

status

String

ordered_at

Date

is_gift

Boolean

address

Object

The Data Type selector is searchable and offers: Array of Objects, Boolean, Date, Number, Number Array, Object, String, String Array and URL.

When Object is selected, an Object Key section appears below the Data Type field, and the drawer grows as keys are added.

The full drawer, top to bottom, is:

  1. Attribute System Name and Attribute Display Name

  2. Data Type

  3. One or more Object Key blocks, followed by + Add Object Key

  4. Mark as Personally Identifiable Information (PII)

  5. Use in Segmentation

  6. Tags

  7. Notes

  8. Cancel and Create Attribute

Object Keys

  • Each Object Key block contains:

    • Object Key Name

    • Data Type

    • Sample of Data (optional)

    • Mark as Personally Identifiable Information (PII)

    • + Add Sub-Object Key and Delete Object Key

  • Use + Add Object Key below the last block to add another key.

  • PII is configured per key as well as at attribute level, and the checkbox is available at every level, so a single object can mix PII and non-PII fields under the existing UCD PII policy. For example, booking.lead_passenger.name can be marked as PII while booking.destination is not.

  • Use in Segmentation controls whether the attribute is available in the segment builder. It is set at attribute level, not per key.

Supported Data Types

Object keys support the following data types:

Data Type

Description

Order Example

String

Text values

status: "shipped"

Number

Numeric values

total: 2499

Date

ISO-8601 datetime

ordered_at: "2026-04-01T14:30:00Z"

Boolean

True/False values

is_gift: true

URL

Valid web link

invoice_url: "https://cdn.example.com/inv.pdf"

String Array

List of text values

tags: ["sale", "new"]

Number Array

List of numeric values

sizes: [38, 39, 40]

Object

Nested structured object

address: { city: "Istanbul", country: "TR" }

Object-Type Keys and Nesting

If you select Object as the data type for an object key:

  • A Sub-Object Keys section appears under that key, with its own Sub-Object Key Name, Data Type, Sample of Data and Mark as PII fields, plus a delete action

  • + Add Sub-Object Key adds further sub-keys under the same object key

  • If a sub-object key is itself typed as Object, a Secondary Sub-Object Keys section appears under it, added with + Add 2nd Level Sub-Object Key

The three levels are named as follows in the panel: Object Key (level 1), Sub-Object Key (level 2) and Secondary Sub-Object Key (level 3), which gives you three addressable levels:

last_order                 (root object attribute)
├─ total                   L1
├─ status                  L1
└─ address                 L1   (object)
   ├─ city                 L2
   └─ geo                  L2   (object)
      ├─ latitude          L3   <- deepest
      └─ longitude         L3   <- deepest

In this structure, address.geo.latitude sits at level 3 and uses the full allowance. A fourth object inside geo is rejected, and an array of objects currently cannot be used as a sub-key. Keys are stored as dot paths, for example address.geo.latitude.

Naming Rules

  • Object Key and Sub-Object Key names must start with a lowercase letter and can contain letters, numbers and underscores.

  • Spaces are automatically converted to underscores and names are lowercased while typing (for example, Unit Price becomes unit_price).

  • Names must be at least 3 characters.

  • An object key name cannot be the same as another object key name in the same attribute. It can be the same as an object key in a different attribute.

  • A sub-object key name cannot be the same as another sub-object key name in the same attribute. It can be the same as a sub-object key in a different attribute.

  • An object key and a sub-object key can share the same name under the same attribute.

  • action and value are reserved and cannot be used as key names, because they are used to detect the update envelope during ingestion.

Limit Behavior

When you reach a limit, the relevant option is disabled and a tooltip explains why:

Condition

Behavior

Panel has reached the object attribute limit

The Object option is disabled in the Data Type list with the tooltip "Object Limit Reached — You have already added the maximum of 20 of Objects attributes."

Panel has reached the total custom parameter limit

All data types are disabled with the tooltip "Custom Parameters Limit Reached — You have already added the maximum of [X] Custom Parameters."

Panel has reached the Array of Objects limit but not the object limit

Only Array of Objects is disabled, with "Array of Objects Limit Reached — You have already added the maximum of 20 Array of Objects attributes." Object remains selectable.

Attribute has reached the key limit

+ Add Object Key and + Add Sub-Object Key are disabled with the tooltip "You have already added the maximum of 50 Object and Sub-Object Keys. Remove one or more of them to add new ones."

Default and Configurable Limits

Limit

Default

Configurable

Sub-keys per object, counted across all levels

20

Yes, up to 50, raised per partner

Object type attributes per panel

20

Not configurable at launch

Nesting levels

3

Not configurable

String length per value

500 characters

Not configurable

Payload size per request

5 MB

Not configurable

The Object Type limit is tracked separately from the Array of Objects limit and from the general Custom Attributes limit, so registering an object attribute does not consume an Array of Objects slot. You can follow all three in the Key Metrics section at the top of the Attributes and Events page, where Array of Objects and Object each appear as their own sub-metric under Custom Attributes, for example Object 3 / 20.

Edit an Object Type Attribute

After you create an object attribute, its structure is locked. The edit drawer reuses the create drawer, so the same fields and validations apply, with parts of it disabled.

Editable

Not Editable

Attribute Display Name

Attribute System Name

Sample of Data, at every level

Attribute Data Type

Adding new Object Keys

Existing Object Key names

Adding new Sub-Object Keys and Secondary Sub-Object Keys

Existing Sub-Object Key names

Mark as PII

Existing key data types

Tags, Notes

Deleting existing keys

Newly added keys follow the same rules and validations as the create flow, including the total key limit.

  • When the attribute is already in use

If the attribute is used anywhere, a further set of fields locks: Attribute System Name, Data Type, Object Key Data Type, Delete Object Key, Delete Sub-Object Key, and Use in Segmentation. If it is used in a campaign surface, the drawer becomes read-only.

  • Converting an existing attribute is not possible

The Object data type can only be selected when you create a new attribute. On an attribute of another type, the option is disabled with the tooltip "Data Type Unavailable. Object data type can only be selected when creating a new attribute."

Step 2. Send Object Data

After you define the attribute, start sending data. Object data must be sent inside the dedicated object_attributes.custom field, which is the only accepted location:

  • POST /api/user/v1/upsert

Keep sending flat attributes in attributes. Flat and object attributes can coexist in the same payload. An object sent inside attributes is rejected with an explicit error.

Create the object (Upsert API)

Sample request:

curl --location --request POST 'https://unification.useinsider.com/api/user/v1/upsert' \
--header 'X-PARTNER-NAME: PARTNER_NAME_GOES_HERE' \
--header 'X-REQUEST-TOKEN: TOKEN_GOES_HERE' \
--header 'Content-Type: application/json' \
--data-raw '{
  "users": [
    {
      "insider_id": "u-12345",
      "object_attributes": {
        "custom": {
          "last_order": {
            "total": 2499,
            "currency": "TRY",
            "status": "shipped",
            "address": { "city": "Istanbul", "country": "TR" }
          }
        }
      }
    }
  ]
}'

Sample response:

{
    "data": {
        "successful": {
            "count": 1
        },
        "fail": {}
    }
}

Nested sub-keys (3 levels)

A sub-key typed as Object carries its own nested object, up to three levels in total:

"object_attributes": {
  "custom": {
    "last_order": {
      "total": 2499,
      "address": {
        "city": "Istanbul",
        "geo": { "latitude": 41.0082, "longitude": 28.9784 }
      }
    }
  }
}

Partial update (deep-merge)

Sending a subset of sub-keys updates only those sub-keys. Everything else in the stored object is preserved. Only last_order.status changes here:

{
  "users": [
    {
      "insider_id": "u-12345",
      "object_attributes": {
        "custom": {
          "last_order": { "status": "delivered" }
        }
      }
    }
  ]
}

If you need to overwrite the whole object rather than merge into it, use the action envelope form:

"last_order": { "action": "replace", "value": { "total": 199, "status": "pending" } }

The envelope supports merge (identical to the bare form), replace (whole-object set) and remove. add is rejected, because an object attribute holds exactly one object and has no array semantics.

Clear a sub-key and clearing the object

Clear a single sub-key with the "<null>" sentinel. Here last_order.currency is emptied and the rest of the object is preserved:

{
    "delete_null": true,
    "users": [
        {
            "insider_id": "u-12345",
            "object_attributes": {
                "custom": {
                    "last_order": { "currency": "<null>" }
                }
            }
        }
    ]
}

Clear the whole object value for a user. The registered schema stays in place:

{
  "partner": "acme",
  "source": "all",
  "users": [
    {
      "insider_id": "u-12345",
      "delete": ["last_order"]
    }
  ]
}

How Values Are Handled

  • Date values are normalized to UTC on ingestion. Send them in ISO 8601 format, for example "2026-04-01T14:30:00Z".

  • String values are stored as sent, including case. Comparisons in segmentation are case-sensitive.

  • Nested objects are stored against the dot path defined in the panel, for example address.geo.latitude.

  • Array values inside an object are replaced wholesale on update, not appended.

  • Multiple object attributes can be sent in the same payload, for example last_order and account together.

  • Reserved names (action, value, and internal field names) cannot be used as keys and are rejected.

Ingestion Behavior

Ingestion separates two classes of problems. Structural violations fail the record, and schema mismatches drop only the offending sub-key.

  • Structural violations, rejected

Input

Behavior

Nesting deeper than 3 levels

Rejected, with the path named in the response

An array of objects used as a sub-key

Rejected

An object sent inside attributes instead of object_attributes

Rejected with an explicit error

A string value longer than 500 characters

Rejected

A reserved name used as a key

Rejected

"action": "add" in the envelope form

Rejected

Schema mismatches, the bad sub-key is dropped, the rest is stored

Input

Behavior

Sub-keys that are not defined in the attribute schema

Only the keys defined in the schema are stored. Undefined keys are dropped.

A value whose type does not match the key's data type

That key is dropped. The rest of the object is stored.

An attribute that is not registered in the panel

Not stored. Register the attribute first, then send the data.

A dropped sub-key is never silent. Each drop is recorded per field so it can be surfaced in the Onboarding Center, where an integration developer can see exactly which field was rejected and why.

Error Message Example

Nesting deeper than three levels

Registering a key deeper than three levels fails at schema creation with an HTTP 400 response. At ingestion, the request returns HTTP 200 with a per-path error in the body:

{
    "data": {
        "successful": {},
        "fail": {
            "count": 1,
            "errors": {
                "users.0.object_attributes.custom.last_order.address.geo.coords.lat": [
                    "nested object depth cannot exceed 3 levels"
                ]
            }
        }
    }
}

Step 3. View Object Type Attributes in the User Profile

After you send the data, confirm that the object is stored correctly from the InOne panel.

Open the User Profile and click View All User Attributes in the Basic Information section. The All User Attributes panel opens, with a tab per attribute family: Array of Objects Attributes, Object Attributes, Expressions and so on.

On the Object Attributes tab, each attribute is listed by name with its keys underneath:

  • Level 1: object keys and their values appear directly under the attribute name.

  • Level 2: an object-typed key appears as an expandable row that opens to reveal its sub-object keys.

  • Level 3: a sub-object key that is itself an object expands again to reveal its secondary sub-object keys.

Profile reads return the object in its original nested structure with all three levels preserved, so what you see here matches what you sent. Use this view to verify the structure and the values stored on each user.

Step 4. Use Object Type Attributes in Segmentation

Once the object is ingested, its keys are available directly in the segment builder.

Build the condition

Navigate to Audience > Dynamic Segments > New Segment and add an Attributes condition. The row has four parts:

  • Segment: the object attribute, for example Pets

  • Object Keys: the key inside the object

  • Operator

  • Value

Select the key

The Object Keys dropdown is searchable and cascading. Selecting an object key that is typed as Object opens a submenu with its sub-object keys, and a sub-object key that is itself an object opens one more submenu with its secondary sub-object keys.

You navigate the structure the same way you defined it, and the selected key is labeled in the field: Sub-Object Key for a level 2 selection, and 2nd Sub-Object Key for a level 3 selection.

Step 5. Export

Raw Export V2

Select the whole object, which exports as structured JSON preserving all three levels, or select individual keys by dot path, for example last_order.currency and last_order.address.city. Exported key columns follow the flatten convention, so last_order.address.city becomes last_order_address_city. Requested paths are validated against the registered schema, and an unknown path returns a per-column error. See Export Raw User Data V2 for details.

S3 export

The object is exported as structured JSON with all levels preserved.

Filtering on object keys in export uses the same segmentation conditions described in Step 4.

Limitations

Structure

  • Each panel can have a maximum of 20 object type attributes, tracked separately from the Array of Objects and general Custom Attributes limits.

  • Each object can contain up to 20 sub-keys by default, raisable per partner up to 100. The count is combined across all levels.

  • A maximum of 3 nesting levels is supported. Anything deeper is rejected, not silently truncated.

  • An array of objects cannot be used as a sub-key. Object-type keys are allowed, but a collection inside an object is out of scope for this release.

  • String values cannot exceed 500 characters.

  • Payload size is limited to 5 MB per request.

  • action and value are reserved and cannot be used as key names.

Lifecycle

  • Object attributes must be registered in the panel before ingestion. Auto-detection from incoming traffic is not supported.

  • Object key and sub-object key names and data types cannot be renamed or deleted after creation. New keys can be appended.

  • Object data can only be sent through object_attributes.custom. An object sent inside attributes is rejected.

  • The Object data type can only be chosen when creating a new attribute, never by converting an existing one.

Use Cases

Retail and ecommerce: order context

A single order carries a total, a currency, a status, and a shipping address that only mean something together.

Why Object Type helps

  • Keep the whole order in one attribute instead of six.

  • Preserve the relationship between total, status, and destination.

  • Segment on combinations inside the same order.

Example campaigns

  • Target customers whose last order shipped, was above a value you set, and went to a given city.

  • Personalize a delivery message with the order status and destination.

  • Compute net order value from total minus discount and use it for a high-value segment.

Subscription and telco: plan and renewal

A subscription is a plan, a status, and a renewal date that belong together.

Why Object Type helps

  • Store plan, status, and renewal as one entity.

  • Act on the renewal without maintaining three separate attributes.

  • Personalize with the plan name from the same record.

Example campaigns

  • Target active subscribers whose renewal falls within the next seven days.

  • Promote an upgrade based on the current plan.

  • Suppress win-back messaging for customers who already renewed.

Travel and airlines: booking context

One booking carries a reference, a status, a destination, and a lead passenger with their own details.

Why Object Type helps

  • Keep booking and passenger details connected, including the nested passenger object.

  • Segment on destination and personalize with the passenger name.

  • Model the second and third level naturally, for example booking.lead_passenger.seat_pref.

Example campaigns

  • Greet the lead passenger by name in a pre-flight message.

  • Target travelers flying to a given destination who have not selected a seat.

  • Promote extra baggage based on the fare type in the same booking.

Insurance: policy records

A policy has a type, a coverage level, a premium, and an expiry date.

Why Object Type helps

  • Capture the policy as one entity.

  • Keep type, coverage, and expiry connected.

  • Segment on combinations within the same policy.

Example campaigns

  • Target customers with a policy expiring in the next 30 days above a coverage threshold.

  • Cross-sell based on the policy type held.

  • Personalize a renewal notice with the premium and expiry from the same record.

Pet and specialty retail: profile records

A pet profile carries a name, a breed, a birth date, and a food plan.

Why Object Type helps

  • Store the whole profile as one attribute rather than four.

  • Personalize with the pet name and segment on the food plan together.

  • Keep the profile readable on the user profile page.

Example campaigns

  • Target owners whose pet food plan is due for a refill.

  • Personalize with the pet name in a birthday campaign.

  • Segment by breed and age band from the same profile.

FAQ

Object Type compared to Array of Objects

Q: What is the difference between an Object Type attribute and an Array of Objects attribute?

A: An Object Type attribute stores exactly one structured record, such as the last order or the current subscription. An Array of Objects attribute stores many structured records under one attribute, such as every subscription a customer has ever held.

Two other differences matter in practice. Object Type supports three levels of nesting against Array of Objects' two, and Object Type keys can be used in expressions, which Array of Objects sub-keys cannot.

Q: Which one should I use?

A: If the entity is singular by nature, such as the last order, the current subscription, or the account, use Object Type. If you need a collection, such as all orders, all policies, or all pets, use Array of Objects.

If you need both, for example an order and its line items, model the order as an Object Type attribute, keep the line items in an Array of Objects attribute, and relate the two in segmentation. Array of objects as a sub-key is currently unavailable.

Q: Does registering an object attribute use up my Array of Objects slots?

A: No. Object Type attributes have their own dedicated pool of 20, independent of the 20 Array of Objects slots and of the general Custom Attributes limit.

Setup and ingestion

Q: Do I have to create the structure before sending data?

A: Yes. Define the object attribute and its keys in the panel before ingestion. Keys that are not registered are dropped, and an attribute that is not registered is not stored at all.

Q: Where do I put the object in the payload?

A: Inside object_attributes.custom, next to attributes. This is the only accepted location. An object placed inside attributes is rejected, because attributes accepts flat scalar values only.

Q: If I send only one field, does it overwrite the whole object?

A: No. Updates deep-merge by default. A payload carrying a subset of keys updates only those keys and leaves the rest untouched. To overwrite the whole object deliberately, use the "action": "replace" envelope form.

Q: How do I clear a single field without clearing the object?

A: Send that key with the "<null>" sentinel and "delete_null": true. The key is emptied and every other key in the object is preserved.

Q: How do I clear the whole object?

A: Send the attribute name in the delete array. The stored value is cleared and the registered schema stays in place, so you can start sending data again without re-creating the attribute.

Q: What happens if I send keys that are not defined in the panel?

A: Only the keys defined in the schema are stored. Undefined keys are dropped, the rest of the object is ingested, and the drop is recorded per field so you can review it in the Onboarding Center.

Editing and limits

Q: Can I rename or delete keys after creation?

A: No. Object key and sub-object key names and data types are fixed after creation. You can append new keys, including new sub-object keys under an existing object-type key. The display name, sample data, and PII flag stay editable.

Q: Why can I not edit my attribute at all?

A: Because it is in use. When the attribute is used anywhere, the fields that would change its meaning lock: system name, data type, key data types, the delete actions, and Use in Segmentation. When it is used in Web Templates, Single Mobile Campaigns, or Dynamic Content, the whole drawer becomes read-only, and the edit screen lists every campaign holding it with its status and product so you know what to stop first.

Q: Can I convert an existing attribute to Object?

A: No. The Object data type can only be chosen when creating a new attribute. On an existing attribute of another type the option is disabled, with the tooltip "Object data type can only be selected when creating a new attribute."

Q: How deep can I nest?

A: Three levels: object key, sub-object key, and secondary sub-object key. A fourth level is rejected. An array of objects currently cannot be placed inside an object.

Q: What are the system limits?

Limit

Value

Object type attributes per panel

20

Sub-keys per object

20 by default, raisable to 100

Nesting levels

3

String length per value

500 characters

Payload size per request

5 MB

Q: Can the limits be raised?

A: The sub-key limit is configured per customer and can be raised by the Insider One team on request. The attribute count per panel and the nesting depth are fixed in this release.

Activation

Q: How are multiple conditions evaluated in segmentation?

A: They are combined with AND and evaluated against the same stored object. Because an object attribute holds exactly one object, no ambiguity arises about which record matched, unlike Array of Objects where conditions must be satisfied within a single object of the array.

Q: Can I use object keys in campaign personalization?

A: Yes. Object keys are available as dynamic content with a fallback, and they can also feed expressions whose result is then used in segments and messages.

Q: Can I trigger a journey when an object field changes?

A: Hook triggers and filters on object keys are currently unavailable.

Q: Can I export object data?

A: Yes. Raw Export V2 supports selecting the whole object as structured JSON or selecting individual keys by dot path, and S3 export preserves the full structure.

Next steps

Object Type gives you one attribute per real-world entity, three addressable levels of structure, and a single dot path that works the same way across segmentation, personalization, expressions, and export. Register the attribute first, send data through object_attributes.custom, and verify the result on the user profile before you build campaigns on it.