What this workflow does
- HubSpot: contact created is n8n’s HubSpot Trigger subscribed to contact creation. Updates made by this workflow never fire it again, so there is no enrichment loop.
- HubSpot: get contact loads the email, company, website, country and the
lumeor_enriched_atflag. - Read domain cache loads past results from Google Sheets.
- Normalize and check cache lowercases the email, extracts the domain, skips about twenty common free and disposable providers, skips contacts already enriched, and reuses any successful cache entry younger than 90 days.
- Cached? sends cache hits straight to the HubSpot update and new domains to the lookup.
- Company data provider calls your provider’s company lookup by domain. Fetch homepage downloads the company’s homepage. Failures in either step continue with what is available.
- Build summary request maps the provider response (edit
mapProviderfor your provider), strips scripts, navigation and markup from the page, and caps it at 15,000 characters. - Claude: summarize company returns what they sell, who they sell to, a fit rating of strong, possible, weak or unknown, and a one-line reason, at low effort.
- Merge rules always updates the enrichment fields with source and date, and copies company, website and country into the main fields only when they are blank.
- HubSpot: update contact writes the properties. Save to domain cache stores the result, and HubSpot errors go to Post enrichment issue in Slack.
Before you import
- A current n8n version, reachable from the internet so HubSpot can call the trigger.
- A HubSpot developer account and app for the trigger credential, and a private app token with contact read and write scopes for the API calls.
- A company data provider with a lookup-by-domain endpoint and an API key sent in a header.
- A Google Sheet with a “Domain cache” tab (domain, fetched_at, result_json).
- An Anthropic API key and a Slack bot.
Setup
- Import the JSON file and connect the credentials. The two HubSpot HTTP nodes share the private app token credential.
- In HubSpot, create these contact properties:
lumeor_enrich_summary,lumeor_enrich_fit,lumeor_enrich_fit_reason,lumeor_enrich_industry,lumeor_enrich_employees,lumeor_enrich_sourceandlumeor_enriched_at. - In Company data provider, replace
REPLACE_WITH_PROVIDER_COMPANY_LOOKUP_URLand create a Header Auth credential with your provider’s key. - In Build summary request, replace
REPLACE_WITH_ICP_DESCRIPTIONwith two or three specific sentences and adjustmapProvider. - Replace
REPLACE_WITH_SHEET_IDandREPLACE_WITH_SLACK_CHANNEL.
Test it
Activate the workflow and create three contacts: one at a real company domain, one with a Gmail address, and a second person at the first company. The first should get enrichment fields and a cache row. The Gmail contact should be skipped. The second contact at the same company should be filled from the cache, with “(cache)” in its source field and no provider call. Edit the company name on one contact by hand and confirm a later run never overwrites it.
Make it production-ready
- Waterfall. Add a second provider after the first and call it only when key fields come back empty.
- Cache store. Move the cache to Postgres once it holds thousands of domains, and log provider cost per lookup.
- Rate limits. Provider and HubSpot APIs both throttle. Add batching before you backfill existing contacts.
- More pages. Fetch an about or pricing page as well when homepages are thin.
- Error workflow. Set one so a broken provider key is noticed quickly.
- Model choice.
claude-haiku-5-5is a cheaper option for summarizing many websites.
Read the full guide, how to automate lead enrichment, pair it with the AI lead qualification agent template, or talk to Lumeor.