Find CTR opportunities
Queries or pages whose actual CTR falls well below what the site's own position-based CTR curve predicts for their rank.
Tool name: find_ctr_opportunities
Cost: Free - not billed, and does not draw on a plan quota.
Read-only
This tool only reads. It never creates or changes anything, so an assistant may call it without asking you first.
Queries or pages whose actual CTR falls well below what the site's own position-based CTR curve predicts for their rank. The benchmark is site-wide only - there is no per-country or per-device curve (see unsupportedInputs). Google stores only about 5,000 rows per day per single-dimension breakdown once a day is more than roughly three days old, so on a large site these rows are a top-N by impressions rather than a complete list. When that applies to the window you asked for, the response says so in unsupportedInputs with the dates - there is nothing to fetch, so read a missing row as 'not in the top ~5,000', never as 'zero'.
Parameters
| Parameter | Type | Required | Notes |
|---|---|---|---|
site | string | Yes | The site to look up, as a bare domain ("example.com") or a URL - scheme, www., path and trailing slash are all stripped. Must resolve to a workspace the caller owns; call list_sites first if unsure of the exact domain. |
by | "query" | "page" | No | Dimension to read /breakdown by. Defaults to "query". |
windowDays | integer | No | Length of the current window, in days. Defaults to 28. |
to | string | No | Last day of the current window (YYYY-MM-DD). Defaults to the most recent date either engine has data for. |
minImpressions | integer | No | Minimum current-window impressions to consider a row. Defaults to 10. |
underperformanceRatio | number | No | How far below the expected CTR (as a fraction of it) a row must fall to be flagged, e.g. 0.3 = at least 30% below. Defaults to 0.3. |
limit | integer | No | Maximum rows to return, sorted by relevance. Defaults to 50. |
searchVertical | "web" | "image" | "video" | No | Which Google search vertical to read: web (default), image, or video. Google-only - Bing Webmaster Tools does not split verticals on any traffic endpoint, so anything other than 'web' returns Google alone, with Bing excluded and declared in unsupportedInputs. A null or absent Bing figure then means 'not measurable', never 'zero'. Defaults to "web". |
Full input JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"site": {
"type": "string",
"minLength": 1,
"description": "The site to look up, as a bare domain (\"example.com\") or a URL - scheme, www., path and trailing slash are all stripped. Must resolve to a workspace the caller owns; call list_sites first if unsure of the exact domain."
},
"by": {
"default": "query",
"description": "Dimension to read `/breakdown` by.",
"type": "string",
"enum": ["query", "page"]
},
"windowDays": {
"default": 28,
"description": "Length of the current window, in days.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 365
},
"to": {
"description": "Last day of the current window (YYYY-MM-DD). Defaults to the most recent date either engine has data for.",
"type": "string"
},
"minImpressions": {
"default": 10,
"description": "Minimum current-window impressions to consider a row.",
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"underperformanceRatio": {
"default": 0.3,
"description": "How far below the expected CTR (as a fraction of it) a row must fall to be flagged, e.g. 0.3 = at least 30% below.",
"type": "number",
"exclusiveMinimum": 0,
"maximum": 1
},
"limit": {
"default": 50,
"description": "Maximum rows to return, sorted by relevance.",
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 500
},
"searchVertical": {
"default": "web",
"description": "Which Google search vertical to read: web (default), image, or video. Google-only - Bing Webmaster Tools does not split verticals on any traffic endpoint, so anything other than 'web' returns Google alone, with Bing excluded and declared in `unsupportedInputs`. A null or absent Bing figure then means 'not measurable', never 'zero'.",
"type": "string",
"enum": ["web", "image", "video"]
}
},
"required": ["site"]
}Response
Full output JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"site": {
"type": "string"
},
"workspaceId": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"searchVertical": {
"type": "string",
"enum": ["web", "image", "video"]
},
"by": {
"type": "string"
},
"currentWindow": {
"type": "object",
"properties": {
"start": {
"type": "string"
},
"end": {
"type": "string"
}
},
"required": ["start", "end"],
"additionalProperties": false
},
"rows": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": {
"type": "string"
},
"google": {
"anyOf": [
{
"type": "object",
"properties": {
"position": {
"type": "number"
},
"impressions": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"clicks": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"ctr": {
"type": "number"
},
"expectedCtr": {
"type": "number"
},
"residual": {
"type": "number"
}
},
"required": [
"position",
"impressions",
"clicks",
"ctr",
"expectedCtr",
"residual"
],
"additionalProperties": {}
},
{
"type": "null"
}
]
},
"bing": {
"anyOf": [
{
"type": "object",
"properties": {
"position": {
"type": "number"
},
"impressions": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"clicks": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"ctr": {
"type": "number"
},
"expectedCtr": {
"type": "number"
},
"residual": {
"type": "number"
}
},
"required": [
"position",
"impressions",
"clicks",
"ctr",
"expectedCtr",
"residual"
],
"additionalProperties": {}
},
{
"type": "null"
}
]
}
},
"required": ["label", "google", "bing"],
"additionalProperties": {}
}
},
"unsupportedInputs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"field": {
"type": "string"
},
"engine": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"reason": {
"type": "string"
}
},
"required": ["field", "reason"],
"additionalProperties": {}
}
},
"lastSyncedAt": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
}
},
"required": [
"site",
"workspaceId",
"searchVertical",
"by",
"currentWindow",
"rows",
"unsupportedInputs"
],
"additionalProperties": false
}