agent skillverified 2026-10-30

SEO content gap plan from your competitors' keywords

Competitors get traffic on topics you have no pages for. What do you write next, in what order?

Skill apify-seo-content-gap-plan

2paid Apify Actors
v0.1.0release, 2026-10-30
Apache-2.0license
6ways to install

I wrote this skill for one question: which topics bring my competitors traffic while I have no page for them? You give the agent your domain, one to three competitors and one or two sentences about what you sell.

It finds the Google keywords those competitors rank for where you rank lower or not at all, and throws out brand and off-topic terms. Then it groups the rest into topics, scores every topic with a formula you can read and writes briefs for the top five. Two steps are paid Apify Actor runs, and the agent shows an estimate before either of them starts. The source is public in my skills repository on GitHub.

Example prompts

I wrote the skill to pick up prompts like these, copied from its SKILL.md:

My site is acme-crm.com. Pipedrive and Close outrank us everywhere.
What should we write next quarter, in priority order?

Run a content gap between mystore.com and allbirds.com for the US
and give me briefs for the top 5 topics.

Which keywords does ahrefs.com rank for that seobility.net doesn't?
Group them into topics for our blog.

When not to use it

The skill needs competitor domains. Its SKILL.md sends these jobs elsewhere:

  • Backlink or referring-domain gaps and link building: a different skill.
  • Tracking citations in Google AI Overviews or AI Mode: a different skill.
  • Volume, CPC or clustering for a keyword list you already have, with no competitor: a keyword-volume tool, or the clustering Actor on its own.
  • Writing an article without competitor data, site speed or technical audits: these jobs need no Actor.

How it works, step by step

FIG. 01 · live

From competitor domains to a ranked content plan

SKILL.md · v0.1.0 · 2026-10-30
Complete · replay anytime
  1. Inputs + estimate · your domain, 1 to 3 competitors and what the site sells; the agent reads each Actor's live pricing and input schema for free and shows the estimate before any paid call
  2. Keyword gap · a paid run of the competitor keywords Actor in gap mode: keywords a competitor ranks for where you rank lower or not at all
  3. Filter · drops keywords where you already rank better, brand and navigational terms and traffic unrelated to the business, with a count per rule
  4. Clustering · a paid run of the clustering Actor groups the kept keywords into topics with intent and a CORE or OUTER fit
  5. Score + briefs · priority = gap volume × (1 − difficulty/100) × intent weight × fit weight, then a seven-field brief for each of the top topics
  6. Deliver · a backlog CSV with 19 columns and a Markdown plan, with every run ID and dataset ID
  1. Inputs. The skill requires your domain, one to three competitors and the business context; the agent never guesses what you sell from a domain name. The market defaults to the United States and English, and keywords per competitor to 300 on a paid Apify plan and 100 on the free plan.
  2. Pricing and input schemas. The agent reads both Actors' live pricing and input schemas for free, and builds inputs only from fields in the fetched schema.
  3. Estimate and consent. The reply starts with “Estimated cost:” and the agent waits for a yes before the first paid call.
  4. Keyword gap. One paid run per competitor on a free plan, up to three competitors in one run on a paid plan. Volume, difficulty and rank filters apply inside the Actor, so rows you would throw away are never billed.
  5. Filter. Keywords where you already rank better go, then brand and navigational terms, then traffic far from what you sell. The reply lists every dropped keyword with a count per rule.
  6. Clustering. The kept keywords go to the clustering Actor in one paid run. It returns topics with an intent and a CORE or OUTER fit to your business.
  7. Score. Every topic gets a priority from the formula below, computed in a script when one is available.
  8. Briefs. Each top topic gets seven fields: title, target keyword, supporting keywords, intent and format, action, competitor page to beat with its rank, and four to six subheadings.
  9. Deliver. A backlog CSV with 19 columns and a Markdown plan, with every run ID and dataset ID.

The priority formula

gap_volume = volume of "missing" keywords + 0.5 × volume of "weaker" keywords
ease       = 1 − avg_difficulty / 100
priority   = gap_volume × ease × intent_weight × fit_weight

I count a “weaker” keyword half because you already have a page there; the upside is a better rank, not a new page. I set the default weights to 1.0 for transactional and commercial intent, 0.6 for informational, 0 for navigational, and 1.0 for a CORE topic against 0.5 for OUTER. Tell the agent to change them, for example to weight informational at 1.0 for a content-led brand.

The reference file checks one row by hand, with numbers it labels as invented. A cluster with 8,100 and 2,400 missing volume plus 6,600 weaker volume has a gap volume of 13,800. Its average difficulty is 36.0, with the difficulty-0 row left out because 0 means unknown, so ease is 0.640. As an informational CORE topic it scores 13,800 × 0.640 × 0.6 × 1.0 = 5,297.

A real run, 30 October 2026

The smoke test ran the skill in Claude Code with Claude Sonnet 5.5 on my Apify account: klaviyo.com as the site, mailchimp.com as the competitor, United States and English, 50 keywords. The test environment blocked file writes, so the whole plan came back in the reply instead of in a CSV.

FIG. 02 · replayed log

The two runs behind the plan, from the run records and the skill's reply

Complete · replay anytime

Keyword gap run

10:44:02 run WtC1E1BCnjHbAj2Eg started: mailchimp.com vs klaviyo.com, United States, English10:44:02 input: up to 50 keywords, minimum volume 100, competitor rank 20 or better10:44:10 SUCCEEDED in 7.2 s: Delivered 50 keyword(s) for 1 of 1 domain(s) (keyword gap vs klaviyo.com).— gap_type: 25 missing, 23 weaker, 2 stronger— top rows by volume, before filtering (brand and off-topic rows included):
keywordvolumeKDgaprank
advertisements550,00050missing20
google ad word550,00067missing9
chimpmail368,00023missing1
mailchimp368,00045missing1
e-newsletter201,00028missing5
social media en marketing110,00031missing18
Charged events: 50 × keyword (one per delivered row)

Times are UTC from the run record; lines marked — come from the dataset or the agent, not the run log. Rank = mailchimp.com's Google position; klaviyo.com did not rank for these rows.

Filter, cluster, score

— kept 31 of 50 rows; dropped 19— dropped: 2 where klaviyo.com already ranks better— dropped: 5 brand or navigational (chimpmail, chimp mail, mailchimp, mail.com login, newsletter site)— dropped: 12 off-topic (advertisements, google ad word, goo.gl analytics, fcc, billboards and 7 more)10:44:32 run 2ub33uG9ZLWANo7h6 started: 31 keywords, country us10:46:09 SUCCEEDED in 97.5 s: 31 kept keywords in 30 clusters, 910 related keywords added as supporting— priority = gap_volume × (1 − avg_KD/100) × intent × fit; supporting keywords not scored— warning from the skill: topic 2 is the weakest fit, ranked second only because it was tagged commercial
#topicgap vol.avg KDpriorityaction
1E-newsletter (CORE)402,00028.5172,458new page
2Social media marketing (OUTER)440,00039.5133,100new page
3Marketing emails (CORE)135,7505067,875improve existing page
Charged events: 1 × batch_1k_keywords (up to 1,000 input keywords)

Filter counts, the table and the warning are from the skill's reply; run times and charged events from the run records. Lines marked — happened in the agent, between and after the runs.

The gap run returned 50 rows in 7.2 seconds. The skill kept 31 and dropped 19: 2 where klaviyo.com already ranks better, 5 brand or navigational terms built on the competitor's name, and 12 off-topic terms such as “advertisements” and “website development”.

Those last ones were the top rows by volume, which is exactly why the filter runs before clustering. The clustering run took 97.5 seconds and put the 31 keywords into 30 clusters. It also added 910 related keywords; the plan lists them as supporting ideas and no score counts them.

#TopicGap volumeAvg KDPriorityAction
1E-newsletter (CORE)402,00028.5172,458new page
2Social media marketing (OUTER)440,00039.5133,100new page
3Marketing emails (CORE)135,75050.067,875improve existing page

The brief the skill wrote for topic 1, as it came back:

  • Title: How to Create an E-Newsletter for Your Online Store (with Examples)
  • Target keyword: e-newsletter
  • Supporting keywords: e newsletter, what is an e-newsletter, types of e-newsletters, how to create an e-newsletter, best e-newsletter platforms
  • Intent and format: informational how-to guide
  • Action: new page
  • Competitor to beat: mailchimp.com/resources/email/email-newsletter-examples/, rank 5
  • Subheadings: what an e-newsletter is for an online store; types of e-newsletters store owners send; how to build one step by step; examples to copy; choosing a platform; measuring results

The weak spot is topic 2, and the skill said so itself. Social media marketing sits next to email and SMS, not inside them; it ranked second only because the clustering Actor tagged it commercial. The reply suggested swapping it for “programs for email marketing” (priority 47,853) to stay on product. I would take that swap.

My takeaway: the formula ranks demand and ease well, but a topic's fit depends on one CORE or OUTER label. Check that label before you brief a writer.

Cost and safety

Both Actors are pay per event: the gap Actor charges per delivered keyword row, the clustering Actor per batch of up to 1,000 input keywords. Prices change, so I don't print unit prices here: the skill reads them live, and each Actor's Pricing tab in Apify Store has the current list. How pay per event works is in Apify pricing explained.

For the run above the agent estimated ~$1.85 as an upper bound, and the run records show 50 keyword events and one clustering batch charged. One competitor with 50 keywords came to about $2 at the list prices of 30 October 2026. Three competitors at 300 keywords each cost more, and the estimate tells you how much before anything runs.

  • Estimate first. The line that starts with “Estimated cost:” appears before the first paid call, also when you pre-approved a budget. Above $5 the agent warns you, and above $20 you confirm the amount itself. A rerun or wider settings need a new estimate.
  • Free Apify plan. The gap Actor takes one domain and at most 100 keywords per run, so the skill runs one competitor per call. The clustering Actor takes at most 200 keywords per run, and one batch uses most of the monthly free credit. The agent labels a free-plan result as a preview.
  • Tokens. The agent uses your Apify CLI login or the API token already in your environment, and never asks you to paste a token into the chat.
  • Scraped text is data. Keywords, URLs and cluster labels from a dataset are treated as data, never as instructions.

How it was tested

Before I released v0.1.0, the skill passed a static lint against the Agent Skills spec and the checks of the Apify skills catalog. Trigger tests on Haiku, Sonnet and Opus sent 20 queries: every one that should load the skill did, and none that shouldn't. Quality evaluations against a mocked Apify compared answers with and without the skill; the skill had to beat the baseline clearly and show a correct estimate before the first paid call.

Then came the one real run above. It covers one market, one competitor and 31 clustered keywords; nothing larger has run on Apify yet.

Drafted with an agent from the skill's files, the run records and the reply above; the runs were made by the agent in Claude Code on my account on 2026-10-30.

Reviewed by David S on 2026-10-30.

Install

The skill runs paid Apify Actors built by the author. Links carry no affiliate parameters.

WhereCommand or step
Any SKILL.md harnessnpx skills add doesaiknow/apify-skills works in Claude Code, Codex, Cursor, Gemini CLI and Copilot.
Claude Code plugin marketplace/plugin install apify-seo-content-gap-plan --marketplace doesaiknow/apify-skills
Codex$skill-installer https://github.com/doesaiknow/apify-skills/tree/main/skills/apify-seo-content-gap-plan
Gemini CLIgemini skills install https://github.com/doesaiknow/apify-skills.git --path skills/apify-seo-content-gap-plan
claude.ai and Claude Desktopapify-seo-content-gap-plan.zip from the v0.1.0 release, then Settings → Capabilities → Skills → Upload.
Clonegit clone https://github.com/doesaiknow/apify-skills the skills are also exposed under .claude/skills, .agents/skills and .github/skills.

The skill runs paid Apify Actors built by the author.

Sources

Last updated 10 November 2026.