Enrich HubSpot companies with technographic data from BuiltWith using n8n
Prerequisites
- n8n instance — n8n cloud or self-hosted
- HubSpot private app token with
crm.objects.companies.readandcrm.objects.companies.writescopes - BuiltWith API key (Pro plan or above — API access is not available on free or Basic plans)
- Custom HubSpot company properties created for tech stack data (e.g.,
tech_stack_crm,tech_stack_marketing,tech_stack_analytics) - n8n credential configured for HubSpot
Step 1: Create the trigger
You have two options for triggering technographic enrichment:
Option A — Trigger on new companies: Add a HubSpot Trigger node → Watch Companies (new companies only).
Option B — Scheduled batch (recommended): Add a Schedule Trigger → Weekly, Sunday at 22:00. This enriches all companies that haven't been looked up yet, in a single batch.
Tech stacks change slowly (quarterly at most). A weekly batch is more efficient than enriching every new company immediately. It also helps you stay within BuiltWith's monthly API call limits.
Step 2: Fetch companies from HubSpot
Add an HTTP Request node to search for companies missing tech stack data:
- Method: POST
- URL:
https://api.hubapi.com/crm/v3/objects/companies/search - Authentication: HubSpot credential
- Body:
{
"filterGroups": [{
"filters": [{
"propertyName": "tech_stack_crm",
"operator": "NOT_HAS_PROPERTY"
}]
}],
"properties": ["domain", "name", "tech_stack_crm"],
"limit": 50
}Step 3: Loop through companies and call BuiltWith
Add a Split In Batches node (batch size: 1) to iterate over the search results.
Add an HTTP Request node for BuiltWith:
- Method: GET
- URL:
https://api.builtwith.com/v21/api.json - Query Parameters:
KEY: Your BuiltWith API keyLOOKUP:{{ $json.properties.domain }}
The BuiltWith response contains a Results[0].Result.Paths[0].Technologies[] array. Each technology object has:
Name— e.g., "Salesforce", "Google Analytics"Tag— category tag like "analytics", "crm", "marketing-automation"Categories[]— array of category strings
The technology data is buried several levels deep: Results[0].Result.Paths[0].Technologies[]. If a domain isn't found, Results may be empty or the Paths array may not contain technologies. Always add null checks.
Step 4: Parse the tech stack with a Code node
Add a Code node to extract and categorize the technologies:
const response = $input.first().json;
const technologies = response?.Results?.[0]?.Result?.Paths?.[0]?.Technologies || [];
const categories = {
crm: [],
marketing: [],
analytics: [],
ecommerce: [],
hosting: [],
};
const categoryMap = {
"crm": "crm",
"marketing-automation": "marketing",
"email": "marketing",
"analytics": "analytics",
"web-analytics": "analytics",
"ecommerce": "ecommerce",
"shopping-cart": "ecommerce",
"hosting": "hosting",
"cdn": "hosting",
};
for (const tech of technologies) {
const tag = tech.Tag?.toLowerCase() || "";
for (const [pattern, category] of Object.entries(categoryMap)) {
if (tag.includes(pattern) || (tech.Categories || []).some(c => c.toLowerCase().includes(pattern))) {
categories[category].push(tech.Name);
break;
}
}
}
return [{
json: {
tech_stack_crm: categories.crm.join(", ") || "None detected",
tech_stack_marketing: categories.marketing.join(", ") || "None detected",
tech_stack_analytics: categories.analytics.join(", ") || "None detected",
tech_stack_all: technologies.map(t => t.Name).join(", "),
tech_count: technologies.length,
}
}];Step 5: Update the HubSpot company
Add an HTTP Request node:
- Method: PATCH
- URL:
https://api.hubapi.com/crm/v3/objects/companies/{{ $('Split In Batches').item.json.id }} - Authentication: HubSpot credential
- Body:
{
"properties": {
"tech_stack_crm": "{{ $json.tech_stack_crm }}",
"tech_stack_marketing": "{{ $json.tech_stack_marketing }}",
"tech_stack_analytics": "{{ $json.tech_stack_analytics }}",
"tech_stack_all": "{{ $json.tech_stack_all }}",
"tech_enrichment_date": "{{ new Date().toISOString().split('T')[0] }}"
}
}Before running this workflow, create the custom company properties in HubSpot: tech_stack_crm, tech_stack_marketing, tech_stack_analytics, tech_stack_all, and tech_enrichment_date. Set them as single-line text fields (or multi-line for tech_stack_all).
Step 6: Add a Wait node and error handling
Add a Wait node (2 seconds) after the BuiltWith HTTP Request to stay within API rate limits.
Add error handling:
- Retry on Fail on the BuiltWith HTTP node (2 retries, 5-second wait) — handles temporary API errors
- A separate Error Workflow to alert on failures
Step 7: Test and activate
- Click Execute Workflow with a small batch (set limit to 5)
- Check the BuiltWith response — verify the
Technologiesarray contains expected tools - Check the Code node output — verify categorization is correct
- Open a company in HubSpot to confirm tech stack properties were written
- Toggle the workflow to Active
Cost
- n8n cloud: Starts at $24/mo. Each company lookup uses ~5 executions.
- BuiltWith Pro plan: $295/mo with 500 API calls. Enterprise: $495/mo with 2,000 calls.
- Per company: 1 BuiltWith API call. At $295/mo for 500 calls, that's ~$0.59 per company lookup.
- HubSpot: Free within API rate limits.
At $0.59+ per lookup on the Pro plan, BuiltWith is one of the more expensive enrichment APIs. Be selective about which companies you enrich — filter for high-value prospects, target accounts, or companies above a certain size threshold. Don't enrich your entire database.
Next steps
- Add lead scoring — use the tech stack data in HubSpot workflows to score companies. Competitor CRM users get +20 points, complementary tool users get +10.
- Detect competitors — add specific checks for competitor products and set a
uses_competitor_crmboolean property for easy segmentation - Re-enrich quarterly — modify the search filter to also include companies where
tech_enrichment_dateis older than 90 days
Need help implementing this?
We build and optimize automation systems for mid-market businesses. Let's discuss the right approach for your team.