# Tech Stack Adoption Monitor from Job Posts (`dev_web_col/tech-adoption-monitor`) Actor

See which companies start or stop requiring Snowflake, Kubernetes, Rust and 70+ tools, read from job posts. Backend stack no website scanner sees.

- **URL**: https://apify.com/dev\_web\_col/tech-adoption-monitor.md
- **Developed by:** [Diseño Web de Colombia](https://apify.com/dev_web_col) (community)
- **Categories:** Lead generation, Developer tools, Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 signal detecteds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## 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

## Tech Stack Adoption Monitor from Job Posts

**Find out which companies just started asking for your product's category — before their website shows any sign of it.**

Every tech-stack detector on the market scans a company's **website**. That only reveals the front end: CMS, analytics, pixels, chat widgets.

It cannot see the backend. Nobody puts Snowflake, Kubernetes, Kafka, Terraform or Rust in their HTML. Engineers declare those in one place only: **the job posts they write to hire for them**.

| Signal | What it means for you |
|---|---|
| 🟢 **Company adopted** | They just started requiring the tool. **That is a buying signal** |
| 🔴 **Company dropped** | They stopped asking. They migrated to something else |
| 📈 **Market demand up** | The technology is gaining ground across companies |
| 📉 **Market demand down** | It is losing ground |

If nothing changed, you get nothing and you pay nothing per result.

### What a run looks like

```
6,655 job posts across 60 companies → 1,224 company/technology pairs → 4 signals:

[tech_adopted] Stripe started asking for Snowflake (2 job posts)
[tech_dropped] Brex stopped asking for Datadog
[demand_up   ] Kubernetes up 105% across the market (18 → 37 companies)
[demand_down ] Terraform down 50% (68 → 34 companies)
```

Every adoption signal ships with a **sample job post and its URL**, so you can open it and see the exact wording before you reach out.

### No company list needed

Ships with a validated index of **872 companies** across Greenhouse, Lever, Ashby and Workable. Point it at your own list instead if you prefer:

```json
{
  "companyTokens": ["greenhouse:stripe", "ashby:ramp"],
  "technologies": ["Snowflake", "Databricks", "dbt"],
  "monitorKey": "data-stack-watch"
}
```

### Watch only your category

70+ technologies across 10 categories: languages, frontend, cloud, infrastructure, data, databases, observability, AI/ML, business SaaS and security.

Sell a data warehouse? Watch `data`. Sell observability? Watch `observability`. Far less noise than watching everything.

### Built for schedules

Run it weekly. Adoption moves in weeks, not hours — a daily schedule mostly returns nothing.

- **Dev-tool and data vendors** — account targeting by real stack, not guesses
- **Sales teams** — reach out the week a prospect starts hiring for your category
- **Investors** — track technology adoption curves across a portfolio
- **Analysts** — build a demand time series per technology

### First run is free

The first run records the baseline and **charges nothing** — there is nothing to compare against yet. From the second run onward you get adoption changes only.

### Just need the current stack right now?

Set **`oneShot: true`** and it returns **which technologies each company asks for today**, instead of what changed.

```json
{ "oneShot": true, "companyTokens": ["greenhouse:stripe"], "categories": ["data"] }
```

This is the mode to use for a one-off lookup or from an AI agent. As a pure monitor the first run returns nothing, because there is no history to compare against yet. It never touches your saved monitoring history.

### Honest limits

- **This measures what companies *say they want to hire for*,** not what they run in production. A job post asking for Kubernetes is strong evidence, not proof.
- **Ambiguous names are handled carefully, and some are deliberately strict.** `Segment` only matches "Twilio Segment" or "Segment CDP", because bare "Segment" matched job titles like *"Startup Segment"* in testing. `Rust`, `Swift` and `Go` require capitalisation or an unambiguous alias like `Golang`. This trades a little recall for far fewer false positives.
- Keep `maxCompanies` and your technology list **stable** between runs. Changing them changes what is being watched and shows up as a burst of false adoptions.
- Market demand signals need at least 3 companies and a 20% shift, to avoid noise from tiny samples.
- Greenhouse job posts carry full descriptions; coverage is best there.

### Where the data comes from

The public, unauthenticated JSON endpoints that Greenhouse, Lever, Ashby and Workable publish so companies can embed job boards on their own sites. No login walls, no headless browser. Only job content is read — no personal data about recruiters or applicants.

# Actor input Schema

## `oneShot` (type: `boolean`):

Return which technologies each company asks for right now, instead of what changed. Use this for a single lookup or from an AI agent — as a monitor, the first run returns nothing because there is no history to compare against yet.

## `technologies` (type: `array`):

Watch only these, by exact name: Snowflake, Kubernetes, Rust, Databricks, Datadog... Leave empty to watch all 70+. Watching only your own category gives far less noise.

## `categories` (type: `array`):

Watch every technology in these groups instead of naming them one by one.

## `monitorKey` (type: `string`):

Keep this the same across runs — it is how the actor remembers what it already saw. Use a different name for an independent watchlist.

## `trackSignals` (type: `array`):

Leave empty to get all. Adoption is the buying signal; market demand is the trend.

## `companyTokens` (type: `array`):

Only if you want named companies instead of the built-in index of 872. Accepts "greenhouse:stripe" or a job board URL.

## `maxCompanies` (type: `integer`):

Keep this stable across runs. Changing it changes which companies are watched and produces a burst of false adoptions.

## `minMentions` (type: `integer`):

How many of a company's job posts must mention the technology before it counts as adoption. Raise it to 2 to cut noise from one-off mentions.

## `maxSignals` (type: `integer`):

Safety cap. You are charged per signal returned.

## `resetBaseline` (type: `boolean`):

Forget everything seen before and take a fresh baseline. The baseline run is never charged.

## Actor input object example

```json
{
  "oneShot": false,
  "technologies": [
    "Snowflake",
    "Databricks",
    "dbt"
  ],
  "categories": [],
  "monitorKey": "default",
  "trackSignals": [],
  "companyTokens": [
    "greenhouse:stripe",
    "ashby:ramp"
  ],
  "maxCompanies": 300,
  "minMentions": 1,
  "maxSignals": 5000,
  "resetBaseline": false
}
```

# Actor output Schema

## `signals` (type: `string`):

One dataset item per signal.

# 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 = {
    "technologies": [
        "Snowflake",
        "Databricks",
        "dbt"
    ],
    "companyTokens": [
        "greenhouse:stripe",
        "ashby:ramp"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dev_web_col/tech-adoption-monitor").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 = {
    "technologies": [
        "Snowflake",
        "Databricks",
        "dbt",
    ],
    "companyTokens": [
        "greenhouse:stripe",
        "ashby:ramp",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("dev_web_col/tech-adoption-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "technologies": [
    "Snowflake",
    "Databricks",
    "dbt"
  ],
  "companyTokens": [
    "greenhouse:stripe",
    "ashby:ramp"
  ]
}' |
apify call dev_web_col/tech-adoption-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=dev_web_col/tech-adoption-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/84eWeAWAIiaRYlXxl/builds/v8z7G24nILNGqG7ux/openapi.json
