Find and refresh the Ghost posts quietly losing traffic

By General Input

See every published post ranked by how much search traffic it has lost, then let an agent draft a refreshed version you approve before publishing.

Integrations

  • Ghost
  • Google Search Console
  • Google Analytics

Type

App

Categories

  • Marketing

Build me a content decay desk for my Ghost blog. Most of my traffic comes from posts I wrote a year ago and I have no idea which of them are quietly dying, so I want one screen: a ranked table of my published posts, worst decay first, that tells me what each post used to earn from search versus what it earns now.

Discover the account identifiers instead of asking me to paste them. Use Google Search Console List Sites and use the returned siteUrl string verbatim, because an inexact property string silently returns empty data rather than an error. Use Google Analytics List Account Summaries to find the numeric GA4 property id. If either credential can reach more than one property, let me pick from a dropdown and remember the choice.

Get the post inventory from Ghost with Browse Posts (Admin API), filtered to published posts, capturing slug, title, url, published_at, updated_at, tags and author for each one. Ghost 6.0 removed support for limit=all and caps results at 100 items per page, so request 100 per page and keep paging by reading meta.pagination.next and passing it as the next page until it comes back null. Do not assume one request covers the whole blog.

Get the search data from Google Search Console with Search Analytics Query, called twice with the page dimension: a current window of the last 90 days and a prior window covering the 90 days immediately before it. End the current window three days before today rather than at today, because Search Console data lags two to three days and the freshest days come back artificially low. For each page, compare the two windows to produce clicks now versus clicks before, impressions now versus impressions before, the absolute and percentage change in each, and the drift in average position, where a rising position number means the post has slipped down the results.

Get pageviews and engagement per page path from Google Analytics with Run Report (GA4), using pagePath as the dimension and screenPageViews plus engagement metrics such as userEngagementDuration and engagementRate, over the same current window. This is the supporting signal that separates a post that lost its ranking from a post that people still find but no longer read.

Join the three sources by matching the Ghost slug to the page URL that Search Console and Google Analytics report. Normalise both sides before comparing: strip the protocol and domain, drop query strings and fragments, and treat trailing slashes as equivalent. Show me a small count of rows that failed to match so I can see the coverage rather than silently losing posts.

Bake in three business rules. Exclude any post published within the last 90 days, since a new post has not stabilised and would clutter the top of the list with normal early movement. Exclude posts below a minimum impression floor in the prior window, defaulting to around 100 impressions and adjustable in the UI, so statistical noise does not outrank real problems. Rank by absolute clicks lost, descending, not by percentage, so a post that fell from 4,000 clicks to 2,000 sits above a post that fell from 20 clicks to 2.

The main table shows one row per post with title linking to the live post, clicks now versus prior with the delta, impressions now versus prior with the delta, average position and its drift, pageviews and engagement, days since the post was last updated based on updated_at, publish date, and tags. Make the decay severity visually obvious at a glance and let me sort by any column and filter by tag, author and date range.

Each row expands to show the query-level detail for that post. Call Search Analytics Query again scoped to that single page with the query dimension, for both the current and prior windows, then split the results into terms the post is holding, meaning it appears in both windows, and terms it has lost, meaning it had meaningful impressions in the prior window and has fallen away or dropped out entirely. Show clicks, impressions and average position for each term in both windows. Note in the UI that Search Console only returns rows with at least one impression, so a query disappearing means it fell below that floor rather than proving the post was deindexed.

Every row gets a Refresh this post button that starts a background agent for that post. The agent reads the full current post with Ghost Read Post (Admin API), pulls the queries that post is losing with Search Analytics Query, then writes an updated version of the article that genuinely addresses those lost queries: updating stale facts, dates and examples, strengthening or adding the sections that map to the lost terms, and tightening the introduction, while keeping my voice and the existing structure where it still works. It saves the result with Ghost Create Post (Admin API) as a draft, using ?source=html when sending HTML, carrying over the original tags, and titling it so I can tell it apart from the original.

The agent must always create a new draft and must never overwrite, edit or publish the live post. Nothing goes live from this app. Alongside the draft it writes a plain English changelog explaining what it changed and why, tied back to the specific queries the post was losing, in language I could forward to a colleague with no API or SEO jargon.

That output lands back in the app next to the original so I can compare before publishing anything: the original post and the new draft side by side, the changelog above them, and a link out to the draft in Ghost admin. Show the agent run state on the row as queued, running, done or failed with the error reason, and persist both the run state and the finished result so I can close the app, come back later, and still see the drafts and changelogs from earlier runs.

Related prompts

Explore more prompts
Content decay review board for your WordPress pagesAgency reporting board that builds each client's Slides deckOne console for every SEO client's search performanceCheck in bulk which of your pages Google has actually indexedGhost editorial calendar: drag your month into shapeBuild every client's monthly marketing report in one clickSell and invoice Ghost newsletter sponsor slots in one boardGravity Forms conversion dashboard with dead form alertsMerchandising board for products people view but never buyMulti-site GA4 dashboard with one-click client reports