---
name: enrich-company-name
description: "Populate missing contact company name fields from associated company records using a HubSpot workflow with optional API backfill. Ensures contacts inherit their company name for segmentation, personalization, and ICP classification."
license: MIT
metadata:
  author: tomgranot
  version: "1.1"
  category: data-enrichment
---

# Enrich Contact Company Name from Associated Company

Populate missing contact-level company name fields by copying the value from the associated company record. Uses a HubSpot workflow for ongoing enrichment and optionally an API backfill script for immediate results.

## Why This Matters

Contacts missing a company name cannot be matched to ICP-classified companies, break email personalization tokens, and are invisible to company-based segmentation. In a typical neglected CRM, 40-60% of contacts may be missing this field even though the vast majority have a company association.

## Prerequisites

- HubSpot Marketing Hub Professional or Sales Hub Professional (for Workflows)
- A HubSpot service key (`HUBSPOT_ACCESS_TOKEN` in `.env`; an existing legacy private app token also works) with contact read/write scopes (for the scripted stages)
- Python 3.10+ with [`uv`](https://github.com/astral-sh/uv)
- Phase 1 hygiene processes completed (invalid/deleted contacts removed first)
- **HubSpot auto-association enabled:** Settings > Objects > Companies > "Create and associate companies with contacts" toggle must be ON. This lets HubSpot automatically create company records from email domains and associate them.

## Scripts

Script paths are relative to this skill's directory. Run them from your project directory so `.env`, `data/`, and `reports/` resolve there: prefix each path with wherever this skill is installed (`skills/enrich-company-name/` in a clone of the repo).

| Stage | Script | Run with |
|-------|--------|----------|
| Before | [`scripts/before.py`](./scripts/before.py) | `uv run scripts/before.py` |
| After | [`scripts/after.py`](./scripts/after.py) | `uv run scripts/after.py` |

There is no execute script: the enrichment itself runs as a HubSpot workflow (see Execute below), which handles both the backlog and future contacts.

## Plan

1. Enable auto-association if not already on
2. Audit how many contacts are missing company name (before state)
3. Build a workflow that copies company name from the associated company record
4. Optionally run an API backfill script for immediate results
5. Verify enrichment results (after state)

## Before

Run the before-state audit to capture the baseline: `uv run scripts/before.py`

The core query it runs:

```python
resp = requests.post(f"{BASE}/crm/v3/objects/contacts/search", headers=HEADERS, json={
    "filterGroups": [{"filters": [
        {"propertyName": "company", "operator": "NOT_HAS_PROPERTY"},
    ]}],
    "limit": 1,
})
print(f"Contacts missing company name: {resp.json()['total']}")
```

**Manual approach:** Go to Contacts > filter by Company name > is unknown. Record the count.

Save the count. This is your baseline for measuring success.

## Execute

### Method 1: HubSpot Workflow (Recommended — Handles Backlog + Future)

1. Go to **Automation > Workflows > Create workflow**
2. Select **Contact-based > Blank workflow**
3. Name: `AUTO-ENRICH: Copy Company Name from Association`

**Enrollment trigger:**
- Contact property > Company name > **is unknown**

**Re-enrollment:**
- Enable re-enrollment when **associated company** changes. This is the safety net: if an association forms after the workflow already ran, the contact gets re-enrolled.

**Action 1: Delay 10 minutes**
- This delay is critical. When a new contact enters HubSpot, the auto-association engine needs time to parse the email domain, find or create a matching company, and create the association. Without this delay, the workflow checks for an association before one exists.

**Action 2: If/then branch**
- Condition: Associated company > Company name (or Name) > **is known**
- **YES branch:** Add a **Copy property** action:
  - Copy FROM: Company > Name
  - Copy TO: Contact > Company name
- **NO branch:** Leave empty (contact exits). These are typically contacts with personal email addresses (gmail, yahoo, etc.) where no company can be determined.

**Activate:**
- Click Review > Turn on
- When prompted, select **Yes, enroll existing contacts**. This enrolls the entire backlog.

### Method 2: API Backfill Script (Optional — Immediate Results)

Use this if you need the data populated immediately rather than waiting for workflow processing.

```python
# Pattern: fetch contacts missing company name,
# look up their associated company, copy the name.
# 1. POST /crm/v3/objects/contacts/search  (company NOT_HAS_PROPERTY)
# 2. POST /crm/v4/associations/contacts/companies/batch/read  (get associations)
# 3. POST /crm/v3/objects/companies/batch/read  (fetch company names)
# 4. POST /crm/v3/objects/contacts/batch/update  (write the contact's company property)
```

**Key API notes:**
- Use the Search API to find contacts where `company` NOT_HAS_PROPERTY
- Search API caps at 10,000 results. Segment by `createdate` ranges if needed.
- Use Associations API v4 to get contact-to-company associations
- Batch update contacts via `POST /crm/v3/objects/contacts/batch/update` (100 per call)
- Respect rate limits: 100 requests per 10 seconds per app on Free/Starter, 190 on Professional/Enterprise; the Search API has its own cap of 5 requests per second

### Why Do Both?

- The **workflow** handles both backlog (enrolled on activation) AND future contacts automatically. It is the long-term solution.
- The **API backfill** provides immediate results if you cannot wait for workflow processing (which may take hours for large databases).
- If you only do the workflow, that is perfectly fine. It will process the backlog since existing contacts meeting the trigger criteria get enrolled on activation.

## After

Wait 1-2 hours after activating the workflow (longer for very large databases), then verify: `uv run scripts/after.py` (re-runs the before-state query and compares against the baseline).

**Verification checklist:**

1. The "missing company name" count should have dropped dramatically (typically from 40-60% to under 10%)
2. Remaining contacts without company names should primarily be those with personal email addresses (gmail.com, yahoo.com, etc.)
3. Spot-check 10-20 contacts to confirm the company name matches their associated company record
4. Check workflow history for errors:
   - Property type mismatch (copying to wrong field type)
   - Multiple associated companies (HubSpot uses the primary company)
5. Verify the workflow continues processing new contacts by checking for recent enrollments

## Rollback

- Turn off the workflow to stop further enrichment (Automation > Workflows > toggle off).
- The workflow only fills empty fields, so there is nothing to "restore" — but if bad values were copied (e.g., from wrong primary associations), filter contacts by the workflow's enrollment history and clear the `company` property, or restore values from each contact's property history.

## Key Technical Learnings

- **The 10-minute delay is a balance.** Auto-association typically completes in a few minutes, but 10 minutes provides a comfortable buffer. If many contacts go down the NO branch and later get associations, increase to 15-20 minutes.
- **Re-enrollment is the safety net.** Even if the delay is not long enough, re-enrollment on "associated company changes" catches late associations. The delay handles the common case; re-enrollment handles edge cases.
- **Primary company wins.** If a contact is associated with multiple companies, HubSpot copies from the primary associated company. Verify primary associations are correct for key contacts.
- **This workflow does NOT overwrite existing values.** The enrollment trigger requires "Company name is unknown", so contacts with an existing company name are never touched.
- **Property type matters.** Contact "Company name" is a single-line text field by default. If someone changed it to a dropdown, the copy action may fail. Check in Settings > Properties before running.
- **Personal email domains exit on the NO branch.** Contacts with gmail.com, yahoo.com, hotmail.com, outlook.com, etc. will not get enriched. This is expected. They need manual enrichment or an external provider — see `/waterfall-enrich-contacts` for the provider-agnostic path.
- **Company name is a prerequisite for ICP Tier classification.** Run this enrichment before creating ICP Tier workflows.
- **Schedule the "after" verification script.** Workflow processing for large databases takes time. Do not check results immediately — schedule the verification for 2-4 hours after activation.


---
Source attribution: TomGranot
Original project: https://github.com/TomGranot/HubSpot-admin-skills/blob/15db04633834a089d7314410fe8928228e561703/skills/enrich-company-name/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Mega AI Hub.

## Upstream license notice

MIT License

Copyright (c) 2026 Tom Granot

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



# Mega AI Hub resource metadata

Creator / publisher: TomGranot
Original project: https://github.com/TomGranot/HubSpot-admin-skills/blob/15db04633834a089d7314410fe8928228e561703/skills/enrich-company-name/SKILL.md
Attribution basis: Source repository record

Fields of work: Marketing, Sales
Roles: Email Marketer, Growth Marketer, Marketing Analyst, Product Marketer, Sales Development Rep (SDR)
Specialties: Specialty not specified
Tools: HubSpot
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: e16a610a8bbc8bb64f534a97c1d4633b81b790425db73edca984ec59fe1e865a
