From hubspot-admin
Assign an owner to marketing contacts that have no owner. Ensures every marketable contact has accountability for follow-up, proper lead routing, and accurate owner-based reporting.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hubspot-admin:assign-unowned-contactsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Assign an owner to all marketing contacts that currently have no owner. Unowned contacts create gaps in reporting, prevent proper lead routing, and mean no one is accountable for follow-up on marketing-generated responses.
Assign an owner to all marketing contacts that currently have no owner. Unowned contacts create gaps in reporting, prevent proper lead routing, and mean no one is accountable for follow-up on marketing-generated responses.
Marketing contacts without an owner are a blind spot. They receive campaigns but no one sees their responses. They appear in aggregate metrics but not in individual pipeline views. In owner-based dashboards and reports, they simply do not exist. For teams using round-robin or territory-based routing, unowned contacts bypass the entire system.
Before executing, collect the following information from the user:
Q1: Who should unowned contacts be assigned to?
Q2: Should we use territory-based routing, round-robin, or a single catch-all owner?
CLEANUP: Unowned Marketing Contactsimport os
from hubspot import HubSpot
from dotenv import load_dotenv
load_dotenv()
api_client = HubSpot(access_token=os.getenv("HUBSPOT_API_TOKEN"))
# Count unowned marketing contacts
result = api_client.crm.contacts.search_api.do_search(
public_object_search_request={
"filterGroups": [{
"filters": [
{
"propertyName": "hs_marketable_status",
"operator": "EQ",
"value": "true"
},
{
"propertyName": "hubspot_owner_id",
"operator": "NOT_HAS_PROPERTY"
}
]
}],
"limit": 0
}
)
print(f"Unowned marketing contacts: {result.total}")
Choose one of these approaches (requires team lead approval):
Option A: Catch-All User (Simplest)
Option B: Territory/Region Rules
Option C: Round-Robin
# Pattern for API-based assignment
# Useful for territory-based rules or when UI bulk edit times out
OWNER_ID = "your-owner-id" # Get from Owners API
# 1. Search for unowned marketing contacts (paginate through all)
# 2. Build batch update payload with hubspot_owner_id = OWNER_ID
# 3. Submit in batches of 100 via crm.contacts.batch_api.update
# For territory-based routing:
# 1. Search for unowned marketing contacts
# 2. For each contact, determine territory based on country/state/industry
# 3. Map territory to owner ID
# 4. Batch update with the appropriate owner per contact
API notes:
api_client.crm.owners.owners_api.get_page()emailWait 5-10 minutes for HubSpot to finish processing, then verify.
# Re-run the same search
result = api_client.crm.contacts.search_api.do_search(
public_object_search_request={
"filterGroups": [{
"filters": [
{
"propertyName": "hs_marketable_status",
"operator": "EQ",
"value": "true"
},
{
"propertyName": "hubspot_owner_id",
"operator": "NOT_HAS_PROPERTY"
}
]
}],
"limit": 0
}
)
print(f"Unowned marketing contacts: {result.total} (should be 0)")
Verification checklist:
npx claudepluginhub tomgranot/hubspot-admin-skillsReassign contacts and companies from deactivated team members to active owners. Fully automated via the HubSpot Owners API and Batch Update API. Includes territory analysis for informed reassignment decisions.
Imports leads into CRM with deduplication, scoring, consent tracking, and lifecycle staging. Works with CSV, JSON, or manual entry for Salesforce, HubSpot, Zoho, or Pipedrive.
Automates Lemlist multichannel outreach: manage campaigns, enroll leads, add personalization variables, export campaign data, and handle unsubscribes via the Composio MCP integration.