Skip to main content

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. 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:
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.

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:
A custom trait that passes the check works the same way, for example custom_attribute.plan_tier equals enterprise. The CDP audiences guide 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 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