Enrich HubSpot companies with technographic data from BuiltWith using n8n

medium complexityCost: $0-24/mo

Prerequisites

Prerequisites
  • n8n instance — n8n cloud or self-hosted
  • HubSpot private app token with crm.objects.companies.read and crm.objects.companies.write scopes
  • 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.

Weekly is better for technographics

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 key
    • LOOKUP: {{ $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
BuiltWith response is deeply nested

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] }}"
  }
}
Create custom properties first

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:

  1. Retry on Fail on the BuiltWith HTTP node (2 retries, 5-second wait) — handles temporary API errors
  2. A separate Error Workflow to alert on failures

Step 7: Test and activate

  1. Click Execute Workflow with a small batch (set limit to 5)
  2. Check the BuiltWith response — verify the Technologies array contains expected tools
  3. Check the Code node output — verify categorization is correct
  4. Open a company in HubSpot to confirm tech stack properties were written
  5. 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.
BuiltWith is expensive per-call

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_crm boolean property for easy segmentation
  • Re-enrich quarterly — modify the search filter to also include companies where tech_enrichment_date is 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.