# Content Decay Audit - Google Search Console Traffic Drop (`cygnix_labs/content-decay-audit`) Actor

Compare two Google Search Console page exports. First 25 pages free, then $0.001/page. Flags LOST, DECAYING, CTR_DROP, RANK_SLIP, STRIKING_DISTANCE, GROWING or STABLE, ranked by clicks lost, with a refresh plan per page. No API key.

- **URL**: https://apify.com/cygnix_labs/content-decay-audit.md
- **Developed by:** [Umair Saleem Mohammad Saleem](https://apify.com/cygnix_labs) (community)
- **Categories:** SEO tools, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 page analyzeds

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

## Content Decay Audit - Google Search Console Traffic Drop

**Answer first:** this actor is a **content decay audit for Google Search Console**. Give it two GSC Pages exports (previous vs current period) or one compare export. It labels every page **LOST, RANK_SLIP, DECAYING, CTR_DROP, STRIKING_DISTANCE, NEW, GROWING or STABLE**, ranks pages by **clicks lost** and writes a **content refresh plan** for the biggest losers. **First 25 pages free every run, then $0.001 per page.** No Google login, no API key.

| Quick facts | |
|---|---|
| Best for | Content decay audits, finding pages losing Google traffic, GSC traffic drop diagnosis, content refresh planning |
| Input | Two GSC Pages CSVs (or one compare CSV), pasted or as public CSV URLs |
| Output | One row per page: `status`, `clicksLost`, click / impression / position changes, `refreshPlan` |
| Price | First 25 pages free every run, then $0.001 per page. No start fee |
| Needs | No Google login, no API key, no crawl |
| Not included | Live GSC API connection, content rewriting |

Unlike dashboards that only show % change, it **names the failure mode** (lost vs rank slip vs CTR drop vs shrinking demand) so you know what kind of fix each page needs.

### How the labels work

| Status | Meaning |
|---|---|
| LOST | Had enough previous clicks, now zero or gone from the report |
| RANK_SLIP | Clicks down 30%+ and average position worse by 3+ |
| DECAYING | Clicks down 30%+ and impressions down 20%+ (demand or coverage shrinking) |
| CTR_DROP | Clicks down 30%+ while rankings/impressions held (SERP features, weak title) |
| STRIKING_DISTANCE | Position 8–20 with ≥100 impressions: quick-win refresh |
| GROWING | Clicks up 20%+ |
| NEW | Present only in the current period |
| STABLE | No action needed |

Thresholds match the Actor code (`minPrevClicks` default **10**; pages below that are only checked for striking distance). Label priority when several rules could match: LOST → RANK_SLIP → DECAYING → CTR_DROP → STRIKING_DISTANCE → GROWING → NEW → STABLE.

### Input example

Paste two GSC Pages exports (or one compare export in **Current period CSV** and leave Previous empty):

**Current period**

```
page,clicks,impressions,ctr,position
https://example.com/seo-guide,420,15000,2.8%,6.1
https://example.com/keyword-research,90,9000,1.0%,9.4
```

**Previous period**

```
page,clicks,impressions,ctr,position
https://example.com/seo-guide,800,21000,3.8%,4.2
https://example.com/keyword-research,210,9300,2.3%,8.9
```

Columns are detected automatically (page, clicks, impressions, CTR, position). A GSC **compare** export with “previous / current” column names in one file also works. Public CSV URLs also work. Optional: `minPrevClicks` (default 10), `maxRefreshPlans` (default 25).

### Output sample

```json
[
  {
    "page": "https://example.com/seo-guide",
    "status": "DECAYING",
    "clicksLost": 380,
    "clicksPrev": 800,
    "clicksNow": 420,
    "clickChangePct": -47.5,
    "impressionsPrev": 21000,
    "impressionsNow": 15000,
    "impressionChangePct": -28.6,
    "positionPrev": 4.2,
    "positionNow": 6.1,
    "positionChange": 1.9,
    "refreshPlan": [
      "Demand or coverage is shrinking: check if the topic moved to new queries in GSC",
      "Re-target the page at the growing queries; update title/H1 and add an answer-first summary",
      "Consider merging with an overlapping page"
    ]
  }
]
```

Dataset rows are ranked by clicks lost (then status severity, then impressions). A `SUMMARY` key-value record gives `pagesAnalyzed`, `totalClicksLost`, and `byStatus` counts. Refresh plans are attached to the top N pages by clicks lost (`maxRefreshPlans`, default 25).

### Pricing (pay per event)

| Pages compared | You pay |
|---|---|
| First **25** pages every run | **Free** |
| 100 pages | **$0.075** (75 × $0.001) |
| 500 pages | **$0.475** |
| 1,000 pages | **$0.975** |
| 5,000 pages | **$4.975** |

- Event charged: `page-analyzed` at **$0.001** per page after the free tier.
- Refresh plans are included in the page price. No actor-start fee.
- You are not charged for pages that were not successfully analyzed. Compute is CSV parse only, so platform compute cost stays near zero even on large exports.
- Cap spend with Apify run options / account spend limits if you want a hard ceiling.

### Cost vs value

A weekly GSC compare on a 500-URL site costs under $0.50 and surfaces the pages that lost the most clicks — cheap enough to schedule, specific enough to act on.

### How it compares (live Apify Store prices, verified 18 Oct 2026)

List prices on the Apify Free plan, read from the Apify Store API on 18 October 2026.

| Actor | What you get | Price | Cost for ~1,000 pages |
|---|---|---|---|
| **cygnix_labs/content-decay-audit** (this) | GSC CSV compare → status label + refresh plan | **$0.001 / page, first 25 free, no start fee** | **~$0.98** |
| junipr/content-decay-signal-auditor | Crawl + decay signals + recommendations | $0.0115 / page + $0.035 start (signals, recommendations, $0.40 report extra) | ~$11.50+ |
| kuantum/seo-decay-radar | Content monitoring observations | $0.015 / observation | ~$15 |
| siteverdict/siteverdict-gsc-ga4-analyst | Live GSC + GA4 property analysis | $0.35 / property + $0.005 / URL inspected | Different job (API connection) |
| alizarin_refrigerator-owner/gsc-data-analyzer | General GSC insights | $0.10 start + $0.08 / analysis + extras | Not page-level decay rows |

**Honest take.** For "which pages are losing clicks and why", this is about 10x cheaper than the other page-level decay tools. It works from GSC exports you provide; if you want an actor that connects to the live GSC and GA4 APIs for you, siteverdict does that.

### For AI agents / MCP

**When an agent should call this actor:** the user asks which pages are losing Google traffic, about content decay, a traffic drop in Search Console, or which old posts to refresh first, and can provide GSC Pages exports.

Connect the Apify MCP server with only this actor enabled (works in Claude, ChatGPT, Cursor, VS Code, Codex and any MCP client):

```
https://mcp.apify.com?tools=cygnix_labs/content-decay-audit
```

Or search for it with the default server: `search-actors` keywords such as `content decay`, `Search Console`, `traffic drop`.

Example `call-actor` input:

```json
{
  "currentCsvUrl": "https://example.com/gsc-pages-current.csv",
  "previousCsvUrl": "https://example.com/gsc-pages-previous.csv",
  "minPrevClicks": 10,
  "maxRefreshPlans": 10
}
```

**What to read from the result:** rows are sorted by clicks lost; each has `page`, `status`, `clicksLost`, `clickChangePct`, `positionPrev` / `positionNow` and `refreshPlan` (for the top `maxRefreshPlans` pages). `SUMMARY` gives `pagesAnalyzed`, `totalClicksLost` and `byStatus`. Use `currentCsvText` / `previousCsvText` to paste data inline.

**Cost control for agents:** Sites with 25 pages or fewer are free; 500 pages cost under $0.50. Pass `maxTotalChargeUsd` in `callOptions` to hard-cap spend. This actor is pay-per-event, so it also works with Apify agentic payments (no Apify account needed for the agent).

Example prompt: *"Compare my last 3 months vs the previous 3 months of GSC pages and give me a refresh plan for the 10 pages that lost the most clicks."*

### FAQ

**Which periods should I compare?** Last 3 months vs the previous 3 months, or year-over-year for seasonal sites.
**Does it rewrite content?** No. It tells you what to fix and in what order. Pair with [Keyword Clusterer + Content Brief](https://apify.com/cygnix_labs/keyword-clusterer-brief) for briefs.
**Do I need a Google login or API key?** No. Export CSV from Search Console → Performance → Pages and paste it (or give a public CSV URL).
**What if I only have one compare export?** Paste it in Current and leave Previous empty — the Actor detects compare columns (`clicks … previous` / current).
**Why are some low-traffic pages STABLE?** Pages with previous clicks below `minPrevClicks` (default 10) are only evaluated for STRIKING_DISTANCE; otherwise they stay STABLE so noise does not flood the report.
**Can I cap spend?** Set a max total charge in Apify run options / your account spend limits. The run stops when the event charge limit is reached.
**Errors / empty CSV?** You are not charged for pages that were not successfully analyzed. An empty current CSV fails the run before any charge.

**What is content decay?** A page that used to earn steady search traffic and is now losing clicks, because rankings slipped, the SERP changed (lower CTR) or demand for the topic shrank. This actor separates those causes because each needs a different fix.

### Integrations

Run via the Apify API, schedule weekly runs, or send results to Google Sheets, Make, Zapier, n8n, Slack or webhooks.

### Changelog

- **0.1.6** (2026-10-18): README rewritten answer-first for search and AI agents: quick facts, comparison re-verified on 18 Oct 2026, "For AI agents / MCP" section with example input. Price unchanged ($0.001/page, first 25 free).
- **0.1.1** (2026-10-16): Store comps, cost table, default memory 1024 MB.

### More SEO and AEO tools by Cygnix Labs

- [Website SEO Audit + AEO/GEO Checker (full-site crawl)](https://apify.com/cygnix_labs/site-seo-aeo-audit)
- [AEO & GEO Audit + llms.txt Checker (URL list)](https://apify.com/cygnix_labs/aeo-readiness-checker)
- [Internal Link Audit & Orphan Page Finder](https://apify.com/cygnix_labs/internal-link-audit)
- [Keyword Cannibalization Checker (Search Console)](https://apify.com/cygnix_labs/keyword-cannibalization-finder)
- [Keyword Clustering + Content Briefs](https://apify.com/cygnix_labs/keyword-clusterer-brief)
- [Search Intent Classifier](https://apify.com/cygnix_labs/serp-intent-mapper)
- Free local SEO MCP server: [cygnix-seo-mcp](https://github.com/cygnixlabs-cmd/cygnix-seo-mcp) (`npx -y cygnix-seo-mcp`)

Questions or a feature request? Open an issue on this actor's Issues tab. We answer within 24 hours.

# Actor input Schema

## `currentCsvText` (type: `string`):

Search Console > Performance > Pages export for the recent period (page, clicks, impressions, CTR, position). Or a GSC 'compare' export with both periods in one file.

## `previousCsvText` (type: `string`):

Same export for the earlier period. Leave empty if the current CSV is a compare export.

## `currentCsvUrl` (type: `string`):

Public CSV link (e.g. Google Sheets published CSV).

## `previousCsvUrl` (type: `string`):

Public CSV link for the earlier period.

## `minPrevClicks` (type: `integer`):

Pages below this are only checked for striking distance.

## `maxRefreshPlans` (type: `integer`):

Detailed refresh plan for the pages with most clicks lost.

## Actor input object example

```json
{
  "currentCsvText": "page,clicks,impressions,ctr,position\nhttps://example.com/seo-guide,420,15000,2.8%,6.1\nhttps://example.com/keyword-research,90,9000,1.0%,9.4\nhttps://example.com/link-building,35,4000,0.9%,14.2\nhttps://example.com/technical-seo,300,8000,3.8%,4.0\nhttps://example.com/new-ai-seo,150,3000,5.0%,5.2",
  "previousCsvText": "page,clicks,impressions,ctr,position\nhttps://example.com/seo-guide,800,21000,3.8%,4.2\nhttps://example.com/keyword-research,210,9300,2.3%,8.9\nhttps://example.com/link-building,140,6000,2.3%,8.1\nhttps://example.com/technical-seo,290,7800,3.7%,4.1\nhttps://example.com/old-checklist,120,3000,4.0%,5.5",
  "minPrevClicks": 10,
  "maxRefreshPlans": 25
}
```

# Actor output Schema

## `results` (type: `string`):

No description

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

No description

# 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 = {
    "currentCsvText": `page,clicks,impressions,ctr,position
https://example.com/seo-guide,420,15000,2.8%,6.1
https://example.com/keyword-research,90,9000,1.0%,9.4
https://example.com/link-building,35,4000,0.9%,14.2
https://example.com/technical-seo,300,8000,3.8%,4.0
https://example.com/new-ai-seo,150,3000,5.0%,5.2`,
    "previousCsvText": `page,clicks,impressions,ctr,position
https://example.com/seo-guide,800,21000,3.8%,4.2
https://example.com/keyword-research,210,9300,2.3%,8.9
https://example.com/link-building,140,6000,2.3%,8.1
https://example.com/technical-seo,290,7800,3.7%,4.1
https://example.com/old-checklist,120,3000,4.0%,5.5`
};

// Run the Actor and wait for it to finish
const run = await client.actor("cygnix_labs/content-decay-audit").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 = {
    "currentCsvText": """page,clicks,impressions,ctr,position
https://example.com/seo-guide,420,15000,2.8%,6.1
https://example.com/keyword-research,90,9000,1.0%,9.4
https://example.com/link-building,35,4000,0.9%,14.2
https://example.com/technical-seo,300,8000,3.8%,4.0
https://example.com/new-ai-seo,150,3000,5.0%,5.2""",
    "previousCsvText": """page,clicks,impressions,ctr,position
https://example.com/seo-guide,800,21000,3.8%,4.2
https://example.com/keyword-research,210,9300,2.3%,8.9
https://example.com/link-building,140,6000,2.3%,8.1
https://example.com/technical-seo,290,7800,3.7%,4.1
https://example.com/old-checklist,120,3000,4.0%,5.5""",
}

# Run the Actor and wait for it to finish
run = client.actor("cygnix_labs/content-decay-audit").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 '{
  "currentCsvText": "page,clicks,impressions,ctr,position\\nhttps://example.com/seo-guide,420,15000,2.8%,6.1\\nhttps://example.com/keyword-research,90,9000,1.0%,9.4\\nhttps://example.com/link-building,35,4000,0.9%,14.2\\nhttps://example.com/technical-seo,300,8000,3.8%,4.0\\nhttps://example.com/new-ai-seo,150,3000,5.0%,5.2",
  "previousCsvText": "page,clicks,impressions,ctr,position\\nhttps://example.com/seo-guide,800,21000,3.8%,4.2\\nhttps://example.com/keyword-research,210,9300,2.3%,8.9\\nhttps://example.com/link-building,140,6000,2.3%,8.1\\nhttps://example.com/technical-seo,290,7800,3.7%,4.1\\nhttps://example.com/old-checklist,120,3000,4.0%,5.5"
}' |
apify call cygnix_labs/content-decay-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,cygnix_labs/content-decay-audit"
        }
    }
}
```

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/cub9PSrFReSbdM2QO/builds/DSmeJCa5VVesiyCD5/openapi.json
