# App Churn Reason Miner (`gifted_wagon/app-churn-reason-miner`) Actor

Find why users may leave: turn App Store, Google Play, and support reviews into version-aware churn reasons, evidence, priority scores, and fixes.

- **URL**: https://apify.com/gifted\_wagon/app-churn-reason-miner.md
- **Developed by:** [Michael Olmos](https://apify.com/gifted_wagon) (community)
- **Categories:** AI, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 negative review mineds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## App Churn Reason Miner

Turn App Store, Google Play, Trustpilot, support, or survey review datasets into **version-aware churn reasons** with severity, recurrence, quoted evidence, confidence, and a recommended fix. No AI key or third-party enrichment service is required.

### What you get

The default dataset contains two record types:

- `review-analysis` — one successfully mined unique negative review, including its primary reason, version, severity, confidence, matched phrases, and evidence snippet. This is the primary pay-per-event unit.
- `churn-reason` — an uncharged aggregate with review frequency, affected versions, top version, recency, confidence, priority score, evidence examples, and recommended fix.

The `OUTPUT` key-value-store record is an uncharged run summary covering invalid, duplicate, non-negative, processed, and budget-limited counts.

### Quick start

Run with no input to use the built-in sample, or paste reviews:

```json
{
  "reviews": [
    {
      "id": "r-1",
      "text": "Since version 4.1 the app crashes every time I open a saved project.",
      "rating": 1,
      "version": "4.1.0",
      "appName": "Northstar Notes",
      "date": "2026-08-01"
    }
  ]
}
```

For an upstream Actor, choose its dataset in **Review dataset**. Inline and dataset records can be combined. Common snake\_case, camelCase, nested author, timestamp, and rating formats are normalized automatically; `fieldMap` supports dot paths for custom sources.

### How the deterministic analysis works

1. Normalize review text, ID, rating, date, app version, platform, app name, locale, author, URL, and helpful count.
2. Reject textless rows and remove exact normalized duplicates.
3. Keep low-rated rows and reviews containing explicit churn language.
4. Classify evidence into crashes, performance, access, billing, ads, usability, removed features, notifications, privacy, support, compatibility, or an explicit fallback.
5. Group by app and reason, then rank using recurrence (42%), severity (33%), recency (15%), and confidence (10%).

Scoring is deterministic and reproducible. It does not call an LLM, send review text to an external API, or fabricate evidence.

### Charging and budgets

The primary value event is `negative-review-mined`. Invalid rows, exact duplicates, positive/non-negative rows, and rows that do not produce a successful result are not charged as mined reviews. Aggregated reason rows and the `OUTPUT` summary are uncharged. The Actor checks the run's maximum charge limit before writing each paid batch and stops cleanly when the remaining event budget is exhausted.

The one-time `$0.0003` Actor-start event covers measured startup overhead, including invalid-input runs. Set an Apify maximum total charge when testing unfamiliar datasets.

### Privacy and limitations

`includeOriginalReview` defaults to `false`; only canonical fields are included by default. Reviews can contain personal data, so retain only what your purpose and policy permit.

Review text is directional evidence. A matched phrase does not prove why an individual churned, sarcasm and multilingual text can be misread, and Store reviews are not a representative retention cohort. Verify high-priority findings against cancellation, retention, support, and product telemetry before consequential decisions.

### Development

```bash
npm ci
npm run typecheck
npm test
npm run build
npm run benchmark
npm run launch:verify
```

See `launch/OPERATIONS.md` for release, monitoring, privacy, and rollback procedures.

# Actor input Schema

## `datasetId` (type: `string`):

Optional Apify dataset containing App Store, Google Play, Trustpilot, Amazon, or other review rows.

## `reviews` (type: `array`):

Review objects in common source formats. Text, rating, date, version, platform, and app-name aliases are detected automatically.

## `maxReviews` (type: `integer`):

Hard cap across inline and dataset sources. Invalid, duplicate, and non-negative rows are not charged as mined reviews.

## `negativeRatingThreshold` (type: `number`):

Reviews at or below this 1–5 rating are analyzed. Explicit churn language is still detected when a rating is absent.

## `recentWindowDays` (type: `integer`):

A review this old contributes half the maximum recency weight to priority scoring.

## `maxEvidencePerReason` (type: `integer`):

Maximum number of high-severity review snippets retained on each churn-reason record.

## `fieldMap` (type: `object`):

Optional canonical-field to source-path map, for example {"text":"feedback.body","version":"metadata.appVersion"}. Dot paths are supported.

## `includeNormalizedReview` (type: `boolean`):

Include the canonical review fields used by the classifier on each paid review-analysis record.

## `includeOriginalReview` (type: `boolean`):

Copy the complete source row into output. Enable only when the output dataset may safely retain it.

## `payload` (type: `object`):

Automatically supplied when connected to another Actor run.

## Actor input object example

```json
{
  "reviews": [],
  "maxReviews": 500,
  "negativeRatingThreshold": 3,
  "recentWindowDays": 180,
  "maxEvidencePerReason": 5,
  "fieldMap": {},
  "includeNormalizedReview": true,
  "includeOriginalReview": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

Paid review-analysis rows followed by uncharged aggregated churn-reason rows.

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

Source, data-quality, budget, version, and output counts. This record is not a primary value event.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("gifted_wagon/app-churn-reason-miner").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("gifted_wagon/app-churn-reason-miner").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 '{}' |
apify call gifted_wagon/app-churn-reason-miner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gifted_wagon/app-churn-reason-miner"
        }
    }
}

```

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/Rt9nLoyfjUNpF1zHb/builds/oFO2TpeWGLmxMUO7I/openapi.json
