فهرست موضوع ها
/sites/{siteId}/topics- Scope
search:read- ابزار MCP
topics
Pages grouped into topics, with search totals per topic The website's pages grouped by the folder of their address and the words their Search Console queries share. Groups smaller than minPages go to ungrouped (with search data) or uncovered (crawled content pages without impressions). Pages are matched without scheme, www. and trailing slash. Deterministic: the same data gives the same ids and names. Kept for an hour per website and period; computed at most 2 times per website per minute.
توضیح ها از سند OpenAPI می آیند و انگلیسی اند.
پارامترها
| نام | محل | توضیح |
|---|---|---|
siteIdاجباری | path | stringWebsite id, from GET /sites. |
start | query | date (YYYY-MM-DD)First day, YYYY-MM-DD (from works too); with end. Default: the last 28 days of final data (ending 3 days ago). At most 16 months. |
end | query | date (YYYY-MM-DD)Last day, YYYY-MM-DD (to works too), not in the future. Alone: the 28 days ending there. |
sort | query | clicksopportunitypagesimpressionsdefault clicksopportunity: topics with many pages but weak clicks first (largest clicksShort). |
minPages | query | integerdefault 2, min 1, max 50Smallest topic, in pages (min_pages works too). |
limit | query | integerdefault 50, min 1, max 200Most topics returned, 1 to 200. |
پاسخ
200 · application/json
| فیلد | توضیح |
|---|---|
period | object · required; The period asked for |
period.from | date (YYYY-MM-DD) · required; First day |
period.to | date (YYYY-MM-DD) · required; Last day |
queriesWindow | object or null · required; The 28 days the top queries cover; null when no page × query pairs are stored |
queriesWindow.from | date (YYYY-MM-DD) · required; First day |
queriesWindow.to | date (YYYY-MM-DD) · required; Last day |
sort | clicks | opportunity | pages | impressions · required; Order of topics |
minPages | integer · required; Smallest topic, in pages |
searchData | true or false · required; Any page had Search Console impressions in the period |
pagesCapped | true or false · required; More than 20,000 Search Console pages: the 20,000 with the most impressions were grouped |
totalTopics | integer · required; Topics of at least minPages pages |
topics | list of object · required; Topics, in the asked order, at most limit |
topics[].id | string · required; Stable id: the same data gives the same id |
topics[].name | string · required; Readable name |
topics[].nameFrom | queries | section | page · required; What the name comes from: shared query words, the address folder, or one page |
topics[].section | string or null · required; The address folder all pages share, if one |
topics[].words | list of string · required; The shared query words the name is made of (empty unless nameFrom is queries) |
topics[].pageCount | integer · required; Pages in the topic |
topics[].pagesWithoutSearchData | integer · required; Pages without impressions in the period |
topics[].pages | list of object · required; Its pages, most clicks first (at most 50) |
topics[].pages[].url | string · required; Page address |
topics[].pages[].clicks | integer · required; Clicks in the period |
topics[].pages[].impressions | integer · required; Impressions in the period |
topics[].pages[].position | number or null · required; Average position; null without impressions |
topics[].pagesTruncated | true or false · required; More than 50 pages |
topics[].clicks | integer · required; Clicks in the period |
topics[].impressions | integer · required; Impressions in the period |
topics[].ctr | number · required; Clicks divided by impressions, a fraction (0.05 = 5%), computed from sums |
topics[].position | number or null · required; Average position weighted by impressions; null without impressions |
topics[].clicksPer28Days | number · required; Clicks scaled to 28 days |
topics[].strength | strong | weak | no_clicks · required; strong: at least 5 clicks per page per 28 days; weak: fewer; no_clicks: none |
topics[].clicksShort | number · required; Clicks per 28 days short of strong (0 when strong) |
topics[].topQueries | list of object · required; Top queries of the topic (at most 10), from the stored page × query pairs |
topics[].topQueries[].query | string · required; Query |
topics[].topQueries[].clicks | integer · required; Clicks |
topics[].topQueries[].impressions | integer · required; Impressions |
topics[].topQueries[].ctr | number · required; Clicks divided by impressions, a fraction (0.05 = 5%), computed from sums |
topics[].topQueries[].position | number · required; Average position in Google, weighted by impressions (1 is the top) |
ungrouped | object · required; Pages with search data that are in no listed topic |
ungrouped.pageCount | integer · required; Pages with search data in groups smaller than minPages |
ungrouped.clicks | integer · required; Their clicks |
ungrouped.impressions | integer · required; Their impressions |
ungrouped.pages | list of object · required; Those pages, most clicks first (at most 50) |
ungrouped.pages[].url | string · required; Page address |
ungrouped.pages[].clicks | integer · required; Clicks in the period |
ungrouped.pages[].impressions | integer · required; Impressions in the period |
ungrouped.pages[].position | number or null · required; Average position; null without impressions |
uncovered | object · required; Crawled content pages Google does not show |
uncovered.pageCount | integer · required; Crawled content pages with no impressions, in groups smaller than minPages |
uncovered.pages | list of object · required; Those pages (at most 200) |
uncovered.pages[].url | string · required; Page address |
uncovered.pages[].section | string or null · required; Its address folder |
uncovered.truncated | true or false · required; More than 200 |
cached | true or false · required; Answered from the hour-long cache |
computedAt | string · required; When the grouping was computed |
note | string · required; How topics are built |
link | string · required; The Pages screen in the app |
نکته ها
GET /sites/{siteId}/topics صفحه های سایت را در موضوع ها دسته بندی می کند: صفحه هایی که در آدرسشان پوشه مشترکی دارند، یا عبارت های جست وجوی Search Console آن ها کلمه های مشترک دارند. فقط از صفحه های کراول شده و داده های Search Console که MonoRanks از قبل ذخیره کرده استفاده می کند.
هر موضوع این ها را دارد: id، name، pageCount، حداکثر 50 مورد pages (هرکدام با url، clicks، impressions، position)، clicks، impressions، ctr، position (وزن دهی شده با نمایش)، clicksPer28Days، strength و حداکثر 10 مورد topQueries. پاسخ همچنین صفحه های ungrouped (در گروه هایی کوچک تر از minPages) و صفحه های uncovered (صفحه های محتوایی کراول شده که در این دوره هیچ نمایشی نداشته اند) را فهرست می کند.
| مورد | توضیح |
|---|---|
strength |
strong یعنی دست کم 5 کلیک برای هر صفحه در هر 28 روز، weak یعنی کمتر، و no_clicks یعنی هیچ کلیکی. clicksShort می گوید یک موضوع چند کلیک در 28 روز کم دارد تا قوی حساب شود. |
sort |
clicks (پیش فرض)، opportunity (اول موضوع هایی که صفحه زیاد ولی کلیک کم دارند)، pages یا impressions. |
| دوره | start و end (YYYY-MM-DD؛ from و to هم کار می کنند). پیش فرض: 28 روز آخر داده نهایی Search Console که 3 روز پیش تمام می شود. end نمی تواند در آینده باشد. |
minPages |
کوچک ترین موضوع، از 1 تا 50 صفحه (پیش فرض 2). min_pages هم کار می کند. |
- داده یکسان همیشه همان موضوع ها، idها و اسم ها را می دهد. هر پاسخ برای هر سایت و دوره یک ساعت نگه داشته می شود.
خطاها
| کد | معنی |
|---|---|
400 | Bad request. Codes: bad_period, period_too_long, bad_sort, bad_limit, bad_min_pages. |
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 | A limit is reached. rate_limited: too many requests this hour for this key. Codes: rate_limited. |
نمونه درخواست
curl \
-H "Authorization: Bearer mr_ws_…" \
"https://app.monoranks.com/api/v1/sites/SITE_ID/topics"const res = await fetch("https://app.monoranks.com/api/v1/sites/SITE_ID/topics", {
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/topics",
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/topics");
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/topics", { headers: { Authorization: "Bearer mr_ws_…" } });نمونه پاسخ
{
"period": {
"from": "2026-09-06",
"to": "2026-10-03"
},
"queriesWindow": {
"from": "2026-09-04",
"to": "2026-10-01"
},
"sort": "clicks",
"minPages": 2,
"searchData": true,
"pagesCapped": false,
"totalTopics": 14,
"topics": [
{
"id": "t_8f3a2c1d",
"name": "gravel bike",
"nameFrom": "queries",
"section": null,
"words": [
"gravel",
"bike"
],
"pageCount": 6,
"pagesWithoutSearchData": 1,
"pages": [
{
"url": "https://acmebikes.com/guides/how-to-choose-a-gravel-bike",
"clicks": 912,
"impressions": 24300,
"position": 6.8
},
{
"url": "https://acmebikes.com/bikes/gravel",
"clicks": 655,
"impressions": 18120,
"position": 9.1
}
],
"pagesTruncated": false,
"clicks": 1840,
"impressions": 51200,
"ctr": 0.0359,
"position": 8.3,
"clicksPer28Days": 1840,
"strength": "strong",
"clicksShort": 0,
"topQueries": [
{
"query": "best gravel bike under 1500",
"clicks": 214,
"impressions": 8650,
"ctr": 0.0247,
"position": 7.9
}
]
}
],
"ungrouped": {
"pageCount": 9,
"clicks": 140,
"impressions": 6100,
"pages": [
{
"url": "https://acmebikes.com/about",
"clicks": 31,
"impressions": 420,
"position": 3.4
}
]
},
"uncovered": {
"pageCount": 3,
"pages": [
{
"url": "https://acmebikes.com/bikes/kids/balance-bike-12",
"section": "bikes"
}
],
"truncated": false
},
"cached": false,
"computedAt": "2026-10-06T08:14:02.311Z",
"note": "Pages grouped into topics by their address and their Search Console queries. …",
"link": "https://app.monoranks.com/sites/3f6c2a1e-8b4d-4c7a-9e21-5d0b7a6f4c13/pages"
}{
"error": {
"code": "bad_period",
"message": "Send start and end as YYYY-MM-DD, end alone for the 28 days ending there, or neither for the last 28 days of final data."
}
}{
"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": "Topics for this website were computed for 2 other periods in the last minute. Try again in a minute; a period asked before is answered from the cache."
}
}سرور MCP همین کار را با ابزار topics انجام می دهد.