# Company Buying Signal Report — Hiring, Tech & Contact (`m_ctim/company-buying-signal-report`) Actor

Give it a list of company domains. Get back one combined sales-trigger row per company: open roles from Greenhouse/Lever, tech stack fingerprint, best public contact, and a computed buying-signal score.

- **URL**: https://apify.com/m\_ctim/company-buying-signal-report.md
- **Developed by:** [Timothy Kelvin](https://apify.com/m_ctim) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Company Buying Signal Report — Hiring, Tech Stack & Contact in One Row

Give it a list of company domains. Get back one row per company combining
three sales-relevant signals that would otherwise mean stitching together
three separate tools:

- **Hiring signal** — open roles pulled from the company's own Greenhouse or
  Lever job board API (which roles, how many, whether any match your target
  titles)
- **Tech stack fingerprint** — CMS, ecommerce platform, analytics, payment,
  and live-chat tools detected from the homepage
- **Public contact info** — email, phone, and social profiles from the
  homepage and a linked contact/about page

...plus a computed **buying-signal score** (`low`/`medium`/`high`) with the
specific reasons behind it, so you're not just getting three raw feeds but a
sortable "who to call first" list.

Built for SDRs and sales teams prioritizing a target-account list, agencies
scoping prospects before outreach, and market researchers tracking
tech-adoption + hiring trends together.

### Input

```json
{
  "companies": [
    { "domain": "stripe.com", "greenhouseSlug": "stripe" },
    { "domain": "palantir.com", "leverSlug": "palantir" },
    { "domain": "some-startup.com" }
  ],
  "roleKeywords": ["sales", "account executive", "engineer", "growth"],
  "fetchContactPage": true
}
```

| Field | Type | Description |
|---|---|---|
| `companies` | array | One entry per company. `domain` is required. `greenhouseSlug`/`leverSlug` are optional — see below. |
| `roleKeywords` | array of strings | Open roles matching one of these count as a stronger hiring signal. |
| `fetchContactPage` | boolean | Also fetch a linked contact/about page to improve contact-info coverage (default `true`, adds one request per company). |

**On slugs:** if you omit `greenhouseSlug`/`leverSlug`, the actor guesses one
from the domain (`stripe.com` → `stripe`). This works when a company's board
slug matches their domain name and misses when it doesn't — pass the slug
explicitly (findable on their careers page URL) for a guaranteed hit.

### Output

One record per company:

```json
{
  "domain": "stripe.com",
  "hiring": {
    "ats": "greenhouse",
    "slug": "stripe",
    "openRolesCount": 142,
    "notableRoles": ["Account Executive, Bridge", "Senior Software Engineer"],
    "roles": [{ "title": "Account Executive, Bridge", "location": "London", "url": "https://stripe.com/jobs/..." }]
  },
  "techStack": {
    "cms": [],
    "ecommerce": [],
    "jsFrameworks": ["React"],
    "analytics": ["Google Analytics", "Segment"],
    "cdnHosting": ["Cloudflare"],
    "payment": ["Stripe"],
    "liveChat": ["Intercom"]
  },
  "contact": {
    "emails": ["press@stripe.com"],
    "phones": [],
    "socialProfiles": { "linkedin": "https://linkedin.com/company/stripe" }
  },
  "signalStrength": "high",
  "signalScore": 4,
  "signalReasons": [
    "142 open roles (actively scaling)",
    "2 role(s) match notable keywords",
    "uses paid ecommerce/payment/chat/analytics tooling",
    "public contact info found"
  ],
  "analyzedAt": "2026-08-07T00:00:00.000Z"
}
```

### How it works

Three passive, ToS-clean lookups per company — no proxy, no login, no
headless browser:

- **Hiring**: direct calls to `boards-api.greenhouse.io` / `api.lever.co`,
  the same public JSON APIs that power each company's own careers page.
- **Tech stack**: signature matching (response headers, meta tags, script
  sources) against the homepage HTML — the same technique tools like
  Wappalyzer use.
- **Contact info**: regex extraction over the homepage (and one linked
  contact/about page) for emails, phone numbers, and social links — nothing
  behind a login, nothing a browser wouldn't show any visitor.

### Pricing note

Billed per **company report**, not per sub-signal — one charge whether the
company has 3 open roles or 300, and regardless of how many tech-stack
signatures or contact fields matched. Priced above a single-source lookup
because it replaces three separate tool runs with one.

| Approach | Cost |
|---|---|
| Hiring-only actor + tech-stack actor + lead-extractor actor, run separately | 3 runs, 3 line items, manual joining |
| This actor | 1 run, 1 row per company, already joined |

### Related products

Need just one signal instead of the combined report? Same underlying
methods, standalone:

- [Company Hiring Tracker](https://github.com/timmKal01/company-hiring-tracker) — hiring signal only, full job list per board
- [Website Tech Stack Detector](https://github.com/timmKal01/website-tech-stack-detector) — tech fingerprint only, deeper signature set
- [Website Lead Extractor](https://github.com/timmKal01/website-lead-extractor) — contact info only, with configurable crawl depth

# Actor input Schema

## `companies` (type: `array`):

One entry per company. `domain` is required. `greenhouseSlug`/`leverSlug` are optional — if omitted, the actor guesses a slug from the domain, which works for some companies and not others.

## `roleKeywords` (type: `array`):

Open roles whose title contains one of these (case-insensitive) count as a stronger hiring signal. Leave empty to treat any open role the same.

## `fetchContactPage` (type: `boolean`):

If a link to a contact/about page is found on the homepage, fetch it too to improve contact-info coverage. Adds one extra request per company.

## Actor input object example

```json
{
  "companies": [
    {
      "domain": "stripe.com",
      "greenhouseSlug": "stripe"
    },
    {
      "domain": "palantir.com",
      "leverSlug": "palantir"
    }
  ],
  "roleKeywords": [
    "sales",
    "account executive",
    "engineer",
    "growth",
    "marketing"
  ],
  "fetchContactPage": true
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        {
            "domain": "stripe.com",
            "greenhouseSlug": "stripe"
        },
        {
            "domain": "palantir.com",
            "leverSlug": "palantir"
        }
    ],
    "roleKeywords": [
        "sales",
        "account executive",
        "engineer",
        "growth",
        "marketing"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("m_ctim/company-buying-signal-report").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": [
        {
            "domain": "stripe.com",
            "greenhouseSlug": "stripe",
        },
        {
            "domain": "palantir.com",
            "leverSlug": "palantir",
        },
    ],
    "roleKeywords": [
        "sales",
        "account executive",
        "engineer",
        "growth",
        "marketing",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("m_ctim/company-buying-signal-report").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    {
      "domain": "stripe.com",
      "greenhouseSlug": "stripe"
    },
    {
      "domain": "palantir.com",
      "leverSlug": "palantir"
    }
  ],
  "roleKeywords": [
    "sales",
    "account executive",
    "engineer",
    "growth",
    "marketing"
  ]
}' |
apify call m_ctim/company-buying-signal-report --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,m_ctim/company-buying-signal-report"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/GRLPOHB9NCflcXNQ1/builds/5ed74HQQcrK6T8rNB/openapi.json
