Finding Safe Personalization Fields with the Clay CLI
Finding Safe Personalization Fields with the Clay CLI
Before writing sequence copy that references a lead field, check which fields are actually reliably populated across the campaign's real audience, using Clay's real campaigns audience command, which samples real leads rather than just listing a schema.
What you will build
A read that returns the campaign's audience segment, its lead count, every referenceable field with a reliablyPopulated flag, and a few real sample leads with their values.
clay campaigns audience <campaign-id>
↓
{ segment, leadCount, availableFields: [{ id, reliablyPopulated }], sampleLeads }
AI Prompt
Using the Clay CLI, find which lead fields are safe to reference in sequence
copy for a specific campaign's audience.
Requirements:
- `clay campaigns audience <campaign-id>` returns { segment: { id, name,
entityType, segmentType }, leadCount, availableFields: [{ id, entityType,
displayName, fieldType, dataType, description, reliablyPopulated }],
sampleLeads: [{ id, fieldValues }], allSampleLeadsHaveEmail }.
- Reference a field in sequence copy by its "id", not its "displayName".
- "reliablyPopulated" is computed from the SAMPLED leads, not the field's
schema -- a field can exist and still be reliablyPopulated: false if it is
blank on at least one sampled lead. Prefer fields with reliablyPopulated:
true; copy referencing the others will read as broken for some recipients.
- entityType on a field is CONTACT (the lead's own column) or ACCOUNT (a
column on the lead's account) -- a contact segment surfaces both.
- This command 404s with "Campaign has no audience segment attached" if the
campaign has no audience yet -- attach one first via `clay campaigns
update <campaign-id> --input '{"leadBaseSegmentId":"<audience-id>"}'`
(draft campaigns only).
- If the audience segment has zero matching records, EVERY field comes back
reliablyPopulated: false and sampleLeads is empty -- this is real,
documented behavior for an empty audience, not an error.
- Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) jq- A campaign with an audience segment attached (see the error case above if it has none)
Note: JSON samples below are trimmed to the fields relevant to each step. Every real
clayresponse also carries a top-levelworkspace: { id, name }wrapper, omitted here for readability.
1. Attach an audience to a draft campaign (if it has none)
clay campaigns update cam_0tl84os74M6XWkVnp2s --input '{"leadBaseSegmentId":"audseg_0tjs3u3yAgacWPpe926"}'
2. Read the audience's available fields
clay campaigns audience cam_0tl84os74M6XWkVnp2s
Real output, an audience with zero matching records:
{
"segment": { "id": "audseg_0tjs3u3yAgacWPpe926", "name": "TPC Test Audience", "entityType": "CONTACT" },
"leadCount": 0,
"availableFields": [
{ "id": "first_name", "displayName": "First name", "dataType": "text", "reliablyPopulated": false },
{ "id": "email", "displayName": "Email", "dataType": "email", "reliablyPopulated": false },
{ "id": "linkedin_url", "displayName": "LinkedIn URL", "dataType": "url", "reliablyPopulated": false }
],
"sampleLeads": [],
"allSampleLeadsHaveEmail": false
}
With zero records in the audience, every field is honestly reported reliablyPopulated: false and sampleLeads is empty. Confirmed live. This is the real behavior for an empty audience, not an error state; the same call against a populated audience returns true for fields that are actually filled in on every sampled lead.
3. Filter to only the safe fields
clay campaigns audience cam_0tl84os74M6XWkVnp2s | jq -r '.availableFields[] | select(.reliablyPopulated) | .id'
Verify the result
Confirm the behavior above holds by re-running the key command and checking the result:
clay campaigns audience cam_0tl84os74M6XWkVnp2s | jq '.availableFields[] | select(.reliablyPopulated)'
Expected: The campaign's attached audience, its lead count, and every available field's reliablyPopulated flag are returned; on an empty audience every field is honestly false rather than erroring.
How it works
campaigns audience exists because a field can be schema-valid and still unsafe to reference: a CRM sync that only populates title for half your leads means copy using {{lead:title}} reads as broken for the other half. Rather than making you discover this at send time, the command samples real leads from the campaign's actual audience and reports which fields held up. reliablyPopulated is therefore a property of the campaign's CURRENT audience data, not a permanent property of the field; re-check it after a large CRM sync or audience change.
Common issues
404 "Campaign has no audience segment attached"
Cause: calling campaigns audience on a campaign that was created blank and never had an audience attached.
Fix: attach one first: clay campaigns update <campaign-id> --input '{"leadBaseSegmentId":"<audience-id>"}' (draft campaigns only; confirmed live, this field is not editable once a campaign leaves draft).
Assuming reliablyPopulated: false means the field doesn't exist
Cause: the flag is easy to misread as "invalid field."
Fix: it means "exists, but blank on at least one sampled lead" (or, on an empty audience, blank on all zero of them). The field is still valid to reference. It's just risky.
Next steps
- Once you've identified safe fields, reference them by
idinclay campaigns sequence edit. - Spam-check the resulting copy with
clay campaigns sequence spam-checkbefore activating.
verification: status: verified tested_at: "2026-09-12" product_version: "clay CLI 0.19.0" command: "clay campaigns audience cam_0tl84os74M6XWkVnp2s | jq '.availableFields[] | select(.reliablyPopulated)'" expected_result: "The campaign's attached audience, its lead count, and every available field's reliablyPopulated flag are returned; on an empty audience every field is honestly false rather than erroring."