> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# CDP Attribute Explorer: check segment feasibility before you write a rule

> A console walkthrough of the Trait explorer tab on Integrations to CDP: read each attribute's fill rate, cardinality, and value-frequency histogram, and know whether it is a workable segment facet before you build the rule.

# CDP Attribute Explorer: segment feasibility

A segment rule is only as good as the attribute it filters on. Before you write a predicate, you want three numbers for the attribute: how many contacts carry a value at all (fill rate), how many distinct values it has (cardinality), and how those values are distributed (the histogram). The **Trait explorer** tab on **Integrations → CDP** shows all three for any explorable attribute and flags the ones whose cardinality makes them unusable as segment facets.

This guide walks the tab end to end: when to reach for it, how to read a distribution, how the high-cardinality warning is computed, and how to turn the read into a segment predicate or a computed trait.

## 1. Why read attribute stats before writing a segment rule

A segment built on an unexamined attribute fails in one of three ways:

* **Empty or thin segments.** An attribute with a low fill rate excludes every contact that has no value for it. A rule on a trait only 10% of contacts carry can never match the other 90%, no matter which operator you use.
* **Singleton segments.** An attribute whose values are near-unique (one value per contact) produces audiences of one. The rule "works" and targets nobody.
* **Unmaintainable facets.** An attribute with thousands of distinct values gives you a value list no operator can scan, and each value matches a handful of contacts.

Checking feasibility first is a one-click read: pick the attribute, look at the fill rate and the cardinality, and decide whether the attribute groups your audience meaningfully. The tab also computes a segment-facet verdict for you: every snapshot carries a **good facet** or **high cardinality** badge, and a warning panel explains the verdict when an attribute is a poor facet, so the feasibility call is consistent across your team instead of re-derived by hand per rule.

## 2. Open the surface

In the dashboard, open **Integrations → CDP** and select the **Trait explorer** tab. The tab is one surface in the CDP console; the full tab-by-tab tour lives in [CDP integration console overview](/guides/cdp-integration-console-overview).

The trait picker at the top lists two groups:

* **Contact fields** — a curated set of low-PII categorical columns: Lifecycle stage, Country code, Language, Timezone, Company, Carrier (MCCMNC), Do-not-call, Blocked, and Memory enabled.
* **Custom attributes** — the keys actually present in your contacts' custom attribute data, ranked by how many contacts carry each key, with the populated count shown next to the key. The most-used traits surface first.

The picker also shows the total number of live contacts in the workspace, so you can read every fill rate against the same denominator.

## 3. Pick an attribute and read the distribution

Select a trait. The panel renders four stats and a histogram:

* **Fill rate** — the share of live contacts with a non-empty value, with the raw counts beneath it ("42,984 of 48,210 contacts have a value").
* **Distinct values** — the cardinality: how many different non-null values exist.
* **Missing** — the contacts with no value, the population any predicate on this attribute silently excludes.
* **Segment facet** — the verdict badge: `good facet` or `high cardinality`.

Below the stats, the value-frequency histogram lists the most frequent values with each value's contact count, its share of non-null contacts, and its share of all contacts. The API returns the top 20 values by default and accepts `top_n` from 1 to 100. A long-tail row aggregates every value outside the top list as "+N other values", and the footnote under the table states how much of the populated population the shown values cover.

Two special states are worth knowing:

* **No values yet.** If no live contact carries a value for the trait, the tab says so instead of rendering an empty histogram. There is no distribution to judge; ingest or backfill the trait first.
* **Estimated from a sample.** For workspaces above 50,000 live contacts, the snapshot is computed from a bounded sample to stay fast, and an "Estimated from a sample" note tells you the fill rate, distinct-value count, and value shares are approximate. The facet verdict and the shape of the histogram are still reliable reads at that size.

The same snapshot is available over the API. `GET /api/v1/cdp/attribute-distribution/attributes` returns the picker catalog (the curated columns plus your populated custom-attribute keys), and `GET /api/v1/cdp/attribute-distribution?attribute=<selector>` returns one attribute's snapshot:

```bash theme={null}
curl -X GET "https://api.orbit.devotel.io/api/v1/cdp/attribute-distribution?attribute=lifecycle_stage" \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

Curated columns are selected by key (`lifecycle_stage`, `country_code`, …); custom traits use the `attributes.<key>` form, for example `attributes.plan_tier`. The raw response contract, including `fill_rate`, `distinct_count`, `high_cardinality`, `top_values`, and the long-tail coverage fields, is documented in the [CDP API reference](/api-reference/endpoints/cdp).

## 4. Cardinality warning tripwires

The `high_cardinality` verdict trips on either of two conditions:

* **Too many distinct values.** 1,000 or more distinct values makes a poor faceting dimension regardless of workspace size: the value list is unusable and each value matches only a handful of contacts. The warning suggests bucketing or a range rule instead.
* **Near-unique values.** When distinct values make up 90% or more of the non-null contacts (and at least 20 contacts carry a value, so a tiny workspace where every value differs is not spuriously flagged), the values behave like identifiers. The warning says the trait looks like an identifier rather than a groupable trait.

When either condition trips, the tab shows the `high cardinality` badge and a warning panel with the reason, and the histogram confirms it visually: the top values each cover a sliver of contacts and the "+N other values" long-tail row carries most of the population. That collapse into singletons is the signature of an unworkable segment facet.

Neither condition is a value judgment on your data; it is a facet judgment. An identifier is a fine join key and a terrible segment facet.

## 5. Apply the signal

**Good facet, healthy fill rate: write the predicate.** An attribute like Lifecycle stage with four distinct values and an 89% fill rate is a direct segment filter:

```json theme={null}
{ "field": "lifecycle_stage", "op": "equals", "value": "customer" }
```

A custom trait that passes the check works the same way, for example `custom_attribute.plan_tier` equals `enterprise`. The [CDP audiences guide](/guides/cdp-segments) covers the full filter grammar, behavioral operators, and activation.

**High cardinality: derive a trait instead of faceting on the raw value.** If the attribute you actually care about is the high-cardinality one, bucket it into a categorical trait and segment on the bucket:

* A per-contact identifier or token should never be a facet; if it marks something meaningful, express that meaning as a boolean or category (for example "has an external id").
* A numeric attribute with thousands of values becomes a range band ("spend under 100 / 100 to 500 / over 500").
* A free-form text attribute becomes a classified tag.

[Computed traits](/guides/computed-traits) is the authoring surface for exactly this: a deterministic rule stamps the derived tag onto every matching contact, and the tag then behaves like any other low-cardinality attribute, segmentable here and everywhere else. Re-check the derived tag in the Trait explorer before you build the segment on it; a good bucketing rule shows a handful of well-populated values.

## 6. PII hygiene

The picker is deliberately narrow. Contact-detail and free-text columns (email addresses, phone numbers, names, and messaging identifiers) are absent from the explorable set: they are near-unique identifiers, so their top values would expose personal data and would never make useful facets. Only the curated categorical columns listed in section 2 and your own custom-attribute keys are explorable, and the same guard applies to the API: a request for an excluded column is rejected.

The histogram does show real attribute values for the attributes it serves, so the surface requires the same access level as reading contact data (section 7). If a custom trait you ingest is itself identifying, treat its distribution as personal data and keep explorer access to the roles that need it.

## 7. Roles and scope

The tab and both endpoints require the **owner**, **admin**, or **developer** role together with the `contacts:read` scope. An API key whose role passes but whose scope excludes `contacts:read` is still rejected, because the response embeds contact attribute values. Members with other roles do not see the tab.

## See also

* [CDP API reference](/api-reference/endpoints/cdp) — the `attribute-distribution` and `attribute-distribution/attributes` endpoint contracts.
* [CDP integration console overview](/guides/cdp-integration-console-overview) — the parent tour of every tab on Integrations → CDP.
* [CDP audiences](/guides/cdp-segments) — turning a feasible facet into a saved, activated segment.
* [Computed traits](/guides/computed-traits) — bucketing a high-cardinality attribute into a segmentable tag.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.