# Switch-Intent Finder — Unhappy Competitor Reviewers as Leads (`inovaflow/switch-intent-finder`) Actor

Name a competitor and get its unhappy customers as leads: critical reviews across software directories, the launch community and the App Store, with reviewer name, title and company where public, rating, complaint tags, churn language, a switch-intent score and who to sell to. No login, MCP-ready.

- **URL**: https://apify.com/inovaflow/switch-intent-finder.md
- **Developed by:** [inovaflow](https://apify.com/inovaflow) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 switch signals

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Switch-Intent Finder — Unhappy Competitor Reviewers as Leads

**The best lead in your market just gave your competitor two stars.** They have the budget (they are paying), the
problem (they wrote it down) and the timing (they are angry today). Every other signal — hiring, funding, tech stack —
is a proxy for intent. A critical review of the tool you replace *is* intent.

This Actor collects those reviews for the competitors you name — across business software directories, the launch
community and the App Store — and turns each into a **switch signal**: who wrote it (name, title, company where the
platform shows them), how they rated it, what they complain about, the churn language they used, a 0–100
**switch-intent score** with its reasons, and **who to sell to**.

***

### Who it is for

- **SDRs and AEs** — a ranked list of your competitor's unhappy customers, with the complaint to open with. The
  ones from directories come with the reviewer's title and company.
- **AI / GTM agents** — one call, a flat dataset, no login and no key. `reviewerCompany`, `switchIntentScore`,
  `complaintTags`, `churnSignals`, `sellTo` on every row; chain `reviewerCompany` into your enrichment.
- **Product marketing** — what people leave your competitor for, tagged and counted (`topComplaints` in the summary).
- **Customer success** — run it on your own product to catch churn before it happens.
- **Founders and investors** — read a market's pain in its own words.

***

### What you get per signal

```jsonc
{
  "competitorProduct": "Zoho CRM",
  "reviewer": "Davin Joseph",
  "reviewerTitle": "CEO",
  "reviewerCompany": "My Enamel Pins",
  "rating": 2,
  "date": "2026-09-01",
  "daysSince": 16,
  "reviewTitle": "Too expensive for what it does",
  "reviewExcerpt": "Pricing and support",
  "complaintTags": ["pricing", "support", "bugs", "mobile"],
  "churnSignals": ["switching", "too expensive"],
  "switchIntentScore": 100,
  "scoreReasons": ["2★ rating (+40)", "churn language: switching, too expensive (+20)", "4 complaints named (+15)", "16 days old (+15)", "dislikes stated (+5)", "company named (+15)"],
  "switchedFrom": null,
  "sellTo": ["Davin Joseph — CEO at My Enamel Pins (the reviewer)", "My Enamel Pins: the reviewer signs — go direct"],
  "platform": "directory-a",
  "sourceUrl": "…"
}
```

Two dataset views are built in: **Switch signals** (who to call) and **Complaints** (what to say).

***

### How to use it

| You want | Set |
| --- | --- |
| A competitor's unhappy customers | `competitors`: `Zoho CRM`, `HubSpot`, … — that is all |
| Only reviewers with a named company | `requireCompany`: true |
| Only the hottest signals | `minSwitchScore`: 60 |
| Very recent complaints only | `daysBack`: 90 |
| Your own churn language | `churnKeywords`: add phrases; the built-in list stays |
| One platform | `platforms`: `directories` / `launch-community` / `app-store` |

A review counts as a signal when it is rated at or below `maxRating` (default 3) **or** uses churn language at any
rating. Each reviewer appears once per competitor (their strongest review; `reviewsByThisReviewer` keeps the count).

***

### Accuracy, on purpose

- Reviewer, title and company are exactly what the platform shows. Directories name the company; the launch community
  names the person; the App Store shows a handle — the row says which (`platform`), and `requireCompany` filters.
- Complaint tags are assigned only when the review's own words match; `reviewExcerpt` is the reviewer's text, not a
  summary. The score is arithmetic on the row's own fields, and `scoreReasons` shows every point.
- `sellTo` is built only from the reviewer's title and company — never a guessed contact.
- No login, no API key, no browser. A few pages per competitor; directories are read lowest-rated first, so the
  unhappy reviewers come first however big the product.

***

### Cost

Pay per switch signal delivered, plus the platform's start fee. Duplicate reviews, reviews outside your window or
below your score and empty runs are never charged; `maxLeadsPerCompetitor` caps both rows and spend.

### Pairs well with

- **Software Category Finder** — every vendor in the category, to pick which competitors to watch.
- **Company Enrichment**, **Decision-Maker Finder** and **Email Finder & Verifier** — from `reviewerCompany` to a
  verified inbox at the account.
- **Buying Signals Monitor** — stack the switch signal with hiring, funding and tech signals.

# Actor input Schema

## `competitors` (type: `array`):

One per line — `Zoho CRM`, `HubSpot`, `Pipedrive`. A product page URL on a review platform works too.

## `platforms` (type: `array`):

Empty = every platform. Business software directories name the reviewer's title and company; the App Store names only the reviewer's handle.

## `maxRating` (type: `integer`):

Reviews rated at most this many stars count as critical. Higher-rated reviews are still included when they use churn language.

## `daysBack` (type: `integer`):

Only reviews dated within this window (a reviewer who complained three years ago has moved on). Reviews without a date are kept.

## `churnKeywords` (type: `array`):

Phrases that flag a review as switch-ready even above the rating threshold. Leave empty for the built-in list (switching, cancelled, too expensive, moving to, looking for an alternative, …); add your own to extend it.

## `minSwitchScore` (type: `integer`):

0–100. Drop signals below this score. 0 keeps every critical review; 40 keeps the ones with churn language or very low ratings.

## `requireCompany` (type: `boolean`):

Keep only rows where the platform names the reviewer's company (directories do; the App Store does not).

## `maxLeadsPerCompetitor` (type: `integer`):

Cap on delivered rows per competitor, highest switch-intent score first. Also caps what you pay: 25 is a quick sample of the hottest leads, 100 (the default when unset) a full list.

## `maxConcurrency` (type: `integer`):

Concurrent page reads. Lower it if you see rate-limit warnings in the log.

## `proxyConfiguration` (type: `object`):

Review pages are public; the default Apify proxy is enough. The launch community is read through a residential session automatically.

## Actor input object example

```json
{
  "competitors": [
    "Zoho CRM",
    "HubSpot"
  ],
  "platforms": [],
  "maxRating": 3,
  "daysBack": 365,
  "churnKeywords": [
    "switching",
    "cancelled",
    "too expensive"
  ],
  "minSwitchScore": 0,
  "requireCompany": false,
  "maxLeadsPerCompetitor": 25,
  "maxConcurrency": 4,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per unhappy reviewer: competitor, reviewer, title, company, rating, complaint tags, churn signals, switch-intent score, who to sell to.

## `complaints` (type: `string`):

The complaint view: what each reviewer dislikes, quoted, with tags, rating and date.

## `summary` (type: `string`):

Signals per competitor and platform, complaint-tag totals, what could not be found.

# 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 = {
    "competitors": [
        "Zoho CRM",
        "HubSpot"
    ],
    "maxLeadsPerCompetitor": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("inovaflow/switch-intent-finder").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 = {
    "competitors": [
        "Zoho CRM",
        "HubSpot",
    ],
    "maxLeadsPerCompetitor": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("inovaflow/switch-intent-finder").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 '{
  "competitors": [
    "Zoho CRM",
    "HubSpot"
  ],
  "maxLeadsPerCompetitor": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call inovaflow/switch-intent-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inovaflow/switch-intent-finder"
        }
    }
}
```

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/fYuigRyu0SrOK7K7B/builds/ffmOqd8U5rA9FXYJa/openapi.json
