Striking Distance Opportunity Finder
Surfaces "striking distance" keywords ranking in Search Console positions 11-20 with real impression demand, ranks them…
Updated
Use this skill
$ npx skills add seoskills.sh/striking-distance-finderAbout this skill
Striking Distance Opportunity Finder is a Analytics and Rank Tracking skill for AI agents, published in the seoskills.sh catalog. Reach for it when your work involves gA4, Search Console, event tracking, and rank monitoring. Install it with one command and it runs inside your own agent, so the work happens in your workflow, not a separate SEO tool.
SKILL.md
Striking Distance Opportunity Finder
AGENT ROLE: Autonomous opportunity-mining agent. Pull GSC query/page data, isolate page-two opportunities, quantify the click upside of reaching page one, optionally confirm the on-page gap, and emit the JSON in references/output.schema.json.
OBJECTIVE
Return a prioritized list of query→URL pairs whose average position is 11–20 and whose demand makes a page-one push worthwhile, each with a projected click uplift and a concrete optimization hint.
INPUTS
site_url(REQUIRED): as verified in GSC (sc-domain:...or URL-prefix).start_date,end_date(OPTIONAL): default last 28 complete days (respect GSC's ~3-day lag; never requesttoday).position_band(OPTIONAL): default[11, 20].min_impressions(OPTIONAL, default 100): demand floor over the window.target_position(OPTIONAL, default 7): the realistic position used to model the upside.verify_onpage(OPTIONAL bool, default false): IF true, fetch each candidate URL and check whether the query term is present in<title>and<h1>.
AUTHENTICATION (Search Console API)
- REQUIRE
GOOGLE_APPLICATION_CREDENTIALS(SA) OR OAuth token, scopehttps://www.googleapis.com/auth/webmasters.readonly.- IF absent THEN STOP
error.code="AUTH_MISSING_CREDENTIALS".
- IF absent THEN STOP
- Identity MUST be a verified user on
site_url. IF403THEN STOPerror.code="AUTH_NO_SITE_ACCESS". - Endpoint:
POST https://searchconsole.googleapis.com/webmasters/v3/sites/{urlEncoded}/searchAnalytics/query.
EXPECTED TOOL CALLS
- Run
scripts/striking_distance.py --site {site_url} --min-impr {n} --target {pos} [--verify]. - Query with
dimensions=["query","page"],dataState="final",rowLimit=25000, paging viastartRow. - IF
verify_onpageTHEN issue at most 1 GET per candidate URL, concurrency ≤ 5, honoringrobots.txt; timeout 10s each. NEVER submit forms or follow non-GET actions.
PROCEDURE
STEP 1 — FETCH query/page rows (paged).
STEP 2 — FILTER: keep rows where position_band[0] <= position <= position_band[1] AND impressions >= min_impressions.
STEP 3 — SCORE each candidate:
current_ctr= observedclicks / impressions(fallback to curve[position] IF clicks == 0).target_ctr=curve[target_position]fromreferences/ctr_curve.json.projected_uplift_clicks = max(0, round(impressions * (target_ctr - current_ctr))).effort_hint: IF position ≤ 15 THEN "low" ELSE "medium". STEP 4 — OPTIONAL ON-PAGE GAP (verify_onpage true):- Fetch URL; set
gap.title_missing_term/gap.h1_missing_termbooleans (case-insensitive, term tokens). - IF fetch fails/blocked THEN
gap = null,gap_status = "fetch_failed". Do NOT block the whole run on one URL. STEP 5 — DEDUPE by (query,page); IF a query maps to multiple pages in-band THEN keep the highest-impression page and addalso_ranking_urls. STEP 6 — EMIT JSON, sorted byprojected_uplift_clicksdesc, capped atlimit(default 100).
RATE LIMITS & ERROR HANDLING
- GSC:
429/RESOURCE_EXHAUSTED→ backoff2^attempt(max 5) then STOPerror.code="RATE_LIMITED". - On-page fetches: IF a host returns repeated
429/503THEN stop verifying that host and mark remaininggap_status="rate_limited_host"; the GSC result still returns. - Treat any position exactly at a band edge inclusively.
MISSING / INSUFFICIENT DATA
- IF 0 rows in band THEN
status="no_opportunities"; return empty list, no error (site may already rank page-one or lack impressions). - IF clicks are all zero for a candidate THEN use curve-based
current_ctr; markctr_basis="modeled". - Never claim an on-page gap without a successful fetch; absence of verification ⇒
gap = null.
OUTPUT
One JSON object per references/output.schema.json. No prose.
FILES
scripts/striking_distance.py— auth, paging, scoring, optional on-page check.references/ctr_curve.json— position→CTR lookup for uplift modeling.references/output.schema.json— output contract.
Not using the CLI? Copy the SKILL.md and paste it straight into ChatGPT, Claude, or any agent.
Embed a badge
Install into your agent
More in Analytics and Rank Tracking
GA4 Anomaly Detector
Detects statistically significant anomalies in GA4 organic traffic and conversions by pulling daily metrics from the GA…
GA4 Attribution Path Modeler
Reconstructs multi-touch conversion paths from the event-level GA4 BigQuery export and assigns credit across channels w…
BigQuery Log File Analyzer
Analyzes raw server and CDN access logs stored in BigQuery to quantify Googlebot crawl behavior, surface crawl-budget w…
Search Console Cannibalization Analyzer
Detects keyword cannibalization by pulling query-and-page data from the Google Search Console API and clustering querie…