Company Tech Stack Monitor — Change Events + Firmographics avatar

Company Tech Stack Monitor — Change Events + Firmographics

Pricing

from $1.00 / 1,000 change events

Go to Apify Store
Company Tech Stack Monitor — Change Events + Firmographics

Company Tech Stack Monitor — Change Events + Firmographics

Buying signals for B2B sales: monitor company domains and get CHANGE EVENTS when a target adopts or removes a tool (Shopify, HubSpot, Marketo...) or switches email provider. Loaded-resource detection, no text-mention false positives. Pay per event written. Not affiliated with detected vendors.

Pricing

from $1.00 / 1,000 change events

Rating

0.0

(0)

Developer

Johnn Mottin

Johnn Mottin

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 days ago

Last modified

Share

A target that just adopted — or dropped — a tool is a company in motion, and that is when they buy. Today that signal costs $250/month at Wappalyzer or $295/month at BuiltWith, with no pay-per-use option. This Actor watches a batch of company domains and returns only the change events: STACK_ADDED (they started loading Klaviyo), STACK_REMOVED (Marketo is gone), MX_PROVIDER_CHANGE (they migrated Google Workspace → Microsoft 365). No login, no browser, no LLM.

Not affiliated with, sponsored by, or endorsed by any vendor detected (Shopify, HubSpot, Marketo, Intercom, Salesforce, etc.). All data comes from each company's public homepage, its HTTP response headers, and public DNS.

Who it's for:

  • B2B sales / SDR teams: "3 of my 80 target accounts changed their stack this week" straight to Slack or your CRM via Apify integrations — a timed reason to reach out.
  • Competitive & partner intel: track who is winning or losing accounts in your category, week over week.
  • Agencies: watch a prospect list for the platform migrations that create projects.

How it works

You provide domains. For each one, in order: robots.txt (a site that disallows everything is skipped as a controlled status), the homepage (one request), and an MX lookup over public DNS-over-HTTPS. Default mode is monitor: the first visit stores a free baseline; later runs diff against it and write one record per change. Every monitor run also writes one free RUN_SUMMARY with per-domain status — so a week with no changes still yields a non-empty dataset that says "monitored: 80 domains, 0 changes". snapshot mode is a one-shot export of the full detected stack plus firmographics.

You are only charged for events (or snapshot records) actually written.

Detection: loaded resources, never text mentions

This is the design decision that makes the product trustworthy. A signature only fires when the tool is actually loaded:

  • the URL of a script/link/iframe/img resource matches a vendor domain (js.hs-scripts.com, static.klaviyo.com, cdn.shopify.com…);
  • a response header identifies the CDN/host (server: cloudflare, x-vercel-id…);
  • a structural framework marker is present (__NEXT_DATA__, ng-version).

A blog post that writes about HubSpot and Marketo loads neither — and produces zero detections. There is a dedicated regression test for exactly that page: a false STACK_ADDED would be a charged event and a false buying signal to a salesperson, which is the worst failure this Actor could have.

The signature library is versioned (signaturesVersion travels in every record) and extensible — vendors change their script domains over time, so coverage is best-effort and the list evolves. When the library version changes between runs, removal events are suppressed for that run: a rewritten signature must never look like a customer who dropped a tool.

Input

{
"domains": ["stripe.com", "hubspot.com"],
"mode": "monitor"
}
FieldTypeDefaultDescription
domainsarrayrequired1–100 domains or URLs; protocol/www/path stripped
modestringmonitormonitor (change events + free summary) or snapshot (full export)
eventTypesarrayall 3STACK_ADDED, STACK_REMOVED, MX_PROVIDER_CHANGE
maxResultsinteger5000Cap on charged records. If it truncates a domain, that domain's state is not advanced
requestDelayMsinteger500Polite pacing per request (floor 250 ms, deliberate)

Output

{
"recordType": "CHANGE_EVENT",
"eventType": "STACK_ADDED",
"domain": "gymshark.com",
"signatureKey": "klaviyo",
"signatureLabel": "Klaviyo",
"category": "marketing",
"signaturesVersion": "2026-07-30.1",
"previousCheckedAt": "2026-07-23T06:00:00.000Z",
"detectedAt": "2026-07-30T06:00:00.000Z"
}

snapshot writes DOMAIN_RESULT records (full stack[] with labels and categories, mxProvider, mxRecords, title, meta description, resourcesScanned).

Stack changes are a weekly signal. Use Apify's own Schedules, not a local scheduler — set it once and it runs in the cloud whether or not your machine is on.

  1. Save your prospect list as a Task (Console → the Actor → Create task).
  2. Console → Schedules → Create schedule, add the Task, set the cron (e.g. Mondays 6am → 0 6 * * 1).
  3. Route the dataset to Slack/Sheets/your CRM via Apify integrations — new events only.

Honest limits (read before relying on it)

  • Homepage only. Detection reads the site's front page, not a deep crawl. A tool used only inside a checkout, a subdomain or a logged-in area will not be seen. This is not a BuiltWith-scale profiler and does not claim to be.
  • Tools injected by inline JavaScript are not detected. A signature fires only on statically loaded resources (script/link/iframe/img URLs, response headers, structural markers). A tool bootstrapped exclusively by inline JS — e.g. injected at runtime by a tag manager — leaves no static resource URL in the HTML and produces a documented false negative. Detection is strict by design: a false STACK_ADDED would be a charged event and a false buying signal to a salesperson, which is worse. Coverage is best-effort; the signature list evolves.
  • Best-effort coverage. ~40 curated signatures across e-commerce, CMS, marketing/CRM, support, analytics, payments, frameworks and CDN/hosting. Vendors change their delivery domains; the versioned library evolves, and signaturesVersion on every record tells you which vintage produced it.
  • Suspicious responses never produce removals. If the homepage comes back implausibly small (challenge/error page) or detection drops to zero when history had signatures, the domain is marked DETECTION_DEGRADED: no events, and the stored state is left untouched so the next healthy run compares against real data.
  • Per-domain robots respected. User-agent: * / Disallow: / means the domain is skipped (DOMAIN_ROBOTS_DISALLOWED), never fetched. A 403 becomes DOMAIN_BLOCKED — no proxy rotation, no evasion.
  • MX is enrichment, not gospel. A DNS failure leaves mxProvider: null instead of inventing a change; other means a provider outside the recognized list.
  • Not covered in v0.1 (measured and deliberately excluded): JSON-LD Organization data is unreliable (absent on 5/5 sampled sites) and the unauthenticated GitHub org API allows only 60 requests/hour, which cannot sustain batches. Both may return as opt-in enrichments later.

Ops notes

  • STATS: per-domain summary (status, stack size, MX, events), HTTP counters, degraded/suppressed counters, field-completeness check, warnings. ERRORS on failure.
  • Diff state lives in the named key-value store COMPANY-STACK-STATE, one key per domain. Delete a key to force a fresh baseline.
  • Cost drivers: up to 3 requests per domain per run (robots + homepage + DNS) plus records written.

FAQ

Do I need an account or API key for any of the detected vendors? No. The Actor reads each company's public homepage, its HTTP response headers and public DNS — no login anywhere.

Why did it miss a tool I know the company uses? Detection only fires on statically loaded resources. A tool injected exclusively by inline JavaScript (for example through a tag manager), or one used only in a checkout, a subdomain or a logged-in area, is a documented false negative — see "Honest limits" above. The Actor never guesses.

What exactly am I charged for? Per record written to the dataset (Pay Per Event) — everything discarded by filters or caps costs you nothing, and the RUN_SUMMARY record is free. The Pricing tab on this page is always the authoritative source for current rates and for any per-run fee.

Can I schedule it? Yes — that is the intended use. See "Schedule it" above.

Is this affiliated with the vendors it detects? No. This is an unofficial community Actor, not affiliated with, sponsored by or endorsed by any vendor detected.