List queries near page one
GET
/sites/{siteId}/search/near-page-one- Scope
search:read- MCP tool
near_page_one
Query + page pairs just off page one (striking distance) Search Console query + page pairs whose average position over the last stored 28-day pair window is from minPosition to maxPosition, with at least minImpressions, most impressions first. extraClicks estimates the extra clicks in 28 days at position 3 (typical click-through 10%). Reads the stored pairs (no new lookups). Parameters also work in snake_case (min_position).
Parameters
| Name | In | Details |
|---|---|---|
siteIdRequired | path | stringWebsite id, from GET /sites. |
minPosition | query | numberdefault 8, min 1, max 100Lowest average position kept. |
maxPosition | query | numberdefault 20, min 1, max 100Highest average position kept; at least minPosition. |
minImpressions | query | integerdefault 10, min 0, max 100000000Fewest impressions in the window. |
url | query | stringA full page URL (exact) or part of one. |
from | query | date (YYYY-MM-DD)With to: use the last stored window ending inside from..to (default: the latest). |
to | query | date (YYYY-MM-DD)Last day of the range to look for a stored window in. |
page | query | integerdefault 1, min 1Page number, from 1. |
per | query | integerdefault 50, min 1, max 500Rows per page, 1 to 500. |
Response
200 · application/json
| Field | Details |
|---|---|
window | object or null · required; The 28-day page × query window read (null: no pairs stored) |
window.from | date (YYYY-MM-DD) · required; First day |
window.to | date (YYYY-MM-DD) · required; Last day |
filters | object · required; Filters applied |
filters.minPosition | number · required; Lowest average position kept |
filters.maxPosition | number · required; Highest average position kept |
filters.minImpressions | integer · required; Fewest impressions kept |
filters.url | string or null · required; Page filter |
total | integer · required; Rows that match, over all pages |
page | integer · required; This page, from 1 |
per | integer · required; Rows per page |
hasMore | true or false · required; More rows after this page |
rows | list of object · required; Pairs, most impressions first |
rows[].query | string · required; Search query |
rows[].page | string · required; Page URL |
rows[].clicks | integer · required; Clicks in the window |
rows[].impressions | integer · required; Impressions in the window |
rows[].ctr | number · required; Clicks divided by impressions, a fraction (0.05 = 5%), computed from sums |
rows[].position | number · required; Average position in Google, weighted by impressions (1 is the top) |
rows[].extraClicks | integer · required; Estimated extra clicks in 28 days at position 3 |
note | string · required; How the list is made |
link | string · required; The Search screen in the app |
Errors
| Status | Meaning |
|---|---|
400 | Bad request. Codes: bad_minPosition, bad_maxPosition, bad_minImpressions, bad_period, bad_page, bad_per. |
401 | Missing, unknown or revoked key. Codes: missing_key, invalid_key. |
403 | The key lacks the scope, covers another website, or its owner lost access. Codes: missing_scope, other_site, owner_left, no_owner, forbidden. |
404 | Not found. Codes: not_found. |
429 | Too many requests this hour for this key. Codes: rate_limited. |
Example request
curl \
-H "Authorization: Bearer mr_ws_…" \
"https://app.monoranks.com/api/v1/sites/SITE_ID/search/near-page-one"const res = await fetch("https://app.monoranks.com/api/v1/sites/SITE_ID/search/near-page-one", {
headers: { Authorization: "Bearer mr_ws_…" },
});
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();import requests
res = requests.get(
"https://app.monoranks.com/api/v1/sites/SITE_ID/search/near-page-one",
headers={"Authorization": "Bearer mr_ws_…"},
)
res.raise_for_status()
data = res.json()<?php
$ch = curl_init("https://app.monoranks.com/api/v1/sites/SITE_ID/search/near-page-one");
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ["Authorization: Bearer mr_ws_…"],
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true);import axios from "axios";
const { data } = await axios.get("https://app.monoranks.com/api/v1/sites/SITE_ID/search/near-page-one", { headers: { Authorization: "Bearer mr_ws_…" } });Example response
{
"window": {
"from": "2026-09-04",
"to": "2026-10-01"
},
"filters": {
"minPosition": 8,
"maxPosition": 20,
"minImpressions": 10,
"url": null
},
"total": 86,
"page": 1,
"per": 50,
"hasMore": true,
"rows": [
{
"query": "gravel bike sizing chart",
"page": "https://acmebikes.com/guides/gravel-bike-size-guide",
"clicks": 38,
"impressions": 5120,
"ctr": 0.0074,
"position": 11.4,
"extraClicks": 474
},
{
"query": "carbon road bike for beginners",
"page": "https://acmebikes.com/bikes/road",
"clicks": 12,
"impressions": 1840,
"ctr": 0.0065,
"position": 14.2,
"extraClicks": 172
}
],
"note": "Search Console query + page pairs whose average position over window … is from minPosition to maxPosition, with at least minImpressions; most impressions first.",
"link": "https://app.monoranks.com/sites/3f6c2a1e-8b4d-4c7a-9e21-5d0b7a6f4c13/search"
}{
"error": {
"code": "bad_minPosition",
"message": "minPosition must be a number from 1 to 100."
}
}{
"error": {
"code": "missing_key",
"message": "Send the key as Authorization: Bearer mr_site_…"
}
}{
"error": {
"code": "missing_scope",
"message": "This key does not have the scope this call needs."
}
}{
"error": {
"code": "not_found",
"message": "Website not found."
}
}{
"error": {
"code": "rate_limited",
"message": "More than 1200 requests this hour for this key."
}
}The MCP server does the same with the tool near_page_one.