audience-targeting
Original:🇺🇸 English
Translated
Build a targeted contact segment by filtering on lifecycle, engagement, jobtitle, geography, or firmographics — then export it as JSONL for a campaign or downstream tool.
10installs
Sourcehubspot/agent-cli-skills
Added on
NPX Install
npx skill4agent add hubspot/agent-cli-skills audience-targetingTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Foundation
Read first — pagination, JSONL piping, destructive-op safety. Reshape recipes in . Resource: is the filter-expression cookbook (lifecycle, lead status, email engagement, activity, deals, owner).
bulk-operations/SKILL.mdbulk-operations/resources/json-patterns.mdresources/contact-segmentation-filters.mdFilter syntax cheat sheet
Source of truth: .
hubspot objects search --help- One flag = one AND group:
--filter.--filter "lifecyclestage=lead AND !hubspot_owner_id" - Multiple flags are OR'd. Use for enum-OR-enum.
--filter - Operators: ,
=,!=,>,>=,<,<=(CONTAINS_TOKEN — whole-word, NOT substring).~ - HAS_PROPERTY: bare or
name. NOT_HAS_PROPERTY:name?. Dates:!name.YYYY-MM-DD
~jobtitle~directorjqProperties this skill turns on
Full live list: . Enum options aren't exposed by ; discover with .
hubspot properties list --type contactsproperties gethubspot objects list --type contacts --properties <name> --limit 100 --format json | jq -r '.data[].properties.<name> // empty' | sort -uCore fields used here: , (bare/ for owned/unowned; for IDs), ( excludes opted-out), / (recency), / / (string or ), (0 net-new, has-pipeline).
lifecyclestagehubspot_owner_id!hubspot owners lisths_email_optout!=truehs_email_last_open_datenotes_last_contactedjobtitlecountrycity=~num_associated_deals>=1Firmographics (, , ) live on companies — see cross-object section.
industrynumberofemployeesannualrevenueCommon segments
bash
# Recent leads (this quarter, not yet owned)
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND createdate>2026-01-01 AND !hubspot_owner_id" \
--properties email,firstname,lastname,createdate
# Decision-makers by jobtitle (OR across tokens)
hubspot objects search --type contacts \
--filter "jobtitle~director" --filter "jobtitle~vp" --filter "jobtitle~chief" \
--properties email,jobtitle,company
# Engaged but not yet MQL (opened recently, still lead, opted in)
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND hs_email_last_open_date>2026-04-01 AND hs_email_optout!=true" \
--properties email,firstname,hs_email_last_open_date
# Geographic — US contacts opted in
hubspot objects search --type contacts \
--filter "country=United States AND hs_email_optout!=true" \
--properties email,state,cityMore patterns (lead status, deals, owners, combined AND/OR) in .
resources/contact-segmentation-filters.mdCross-object: companies-in-industry → their contacts
industrynumberofemployeesannualrevenuexargs -I{} hubspot objects getassociations list{"id":"...","type":"company_to_contact"}objects getbash
# Step 1: target companies. Industry options are portal-specific — discover with:
# hubspot objects list --type companies --properties industry --limit 100 --format json \
# | jq -r '.data[].properties.industry // empty' | sort -u
hubspot objects search --type companies \
--filter "industry=SOFTWARE AND numberofemployees>=100" \
--properties name,industry,numberofemployees \
> target_companies.jsonl
# Step 2: gather association IDs (associations list has no batch --from), then ONE batched
# objects get for all contacts.
while read -r cid; do hubspot associations list --from "companies:$cid" --to contacts; done \
< <(jq -r '.id' target_companies.jsonl) \
| jq -c '{id}' | sort -u \
| hubspot objects get --type contacts --properties email,firstname,jobtitle,hs_email_optout \
> target_contacts.jsonl
# Optional: drop opted-out
jq -c 'select(.properties.hs_email_optout != "true")' target_contacts.jsonl > campaign_audience.jsonlSaving and reusing a segment
A segment is a JSONL file. Re-use for updates, exports, or re-fetches:
bash
# Save
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND hs_email_optout!=true" \
--properties email,firstname,lastname,jobtitle \
> segments/opted_in_leads.jsonl
# Assign owner (dry-run first per bulk-operations/SKILL.md)
jq -c '{id, properties:{hubspot_owner_id:"12345"}}' segments/opted_in_leads.jsonl \
| hubspot objects update --type contacts --dry-run
# Re-fetch with different properties later
jq -c '{id}' segments/opted_in_leads.jsonl \
| hubspot objects get --type contacts --properties email,lifecyclestage,hs_lead_statusDestructive ops on a saved segment follow the dry-run → digest → confirm flow in .
bulk-operations/SKILL.mdKnown limits
- No Lists API surface. Can't save as a HubSpot list or filter by list membership.
- is token-match, not substring. No regex operator.
~ - does not return enum options — discover via
properties get+objects list.jq - has no batch
associations list. Loop to gather IDs, batch the downstream--from.objects get - For >100 results, use the pagination loop in .
bulk-operations/SKILL.md