FullVision
Reports

SEO Opportunities

gethttps://d1iwal3igywepk.cloudfront.net/seo-opportunities

How much more revenue your pages would earn if they ranked higher on Google. Use it to decide which posts to improve first: the list is ranked by money, not by position.

The question it answers: "Which pages bring paying customers from Google but are not #1, and what is ranking higher worth?"

What you get

FieldWhat it means
rows[].organic_new_customer_revenue_centsRevenue from new customers whose first touch was this page through Organic Search, in the window
rows[].revenue_per_click_centsThat revenue divided by the page's organic Search Console clicks
rows[].upside_cents_at_1 … _at_3Extra revenue per window if the page's top queries ranked #1, #2 or #3
rows[].upside_clicks_at_1 … _at_3The same in extra clicks
rows[].upside_range_at_1 … _at_3Low and high bounds for clicks and revenue
rows[].queries[]The page's top 5 non-brand queries by impressions, with position and per-target revenue gain (null when the query already ranks there)
insufficient_dataPages with no organic click in Search Console: listed, not sized (top 5 by revenue; insufficient_data_total gives the full count)
currencyThe workspace display currency: every *_cents field is integer cents in it
curveClick-through rate by position 1-10, with how much of it is your own data (own_weight)
windowThe calculation window: it starts at gsc_data_from when Search Console data begins later than the requested window
notesWhy something is missing or estimated differently

How the estimate works

The report blends your own click-through rate at each position with a published benchmark (First Page Sage, September 2026). Each position leans on your data in proportion to your impressions there: 2,000 impressions at a position weigh as much as the benchmark. A better position never gets fewer clicks than a worse one.

For a query with clicks, the gain scales its own clicks by the ratio of the target position's rate to its current one. For a query with no clicks, the gain is impressions times the difference in rates. Gains in revenue use the page's current revenue per organic click.

Brand queries and zero-click queries (500+ impressions, 0 clicks over the window, typical of AI Overview citations and rank-tracking bots) are excluded. Revenue is first-touch Organic Search, new customers only, and assumes today's conversion rate.

Parameters

ParameterWhat it doesWhen you'd use it
from, to / rangeThe window. Defaults to the last 90 daysCompare a quarter
page_searchKeep only pages whose path matches these wordspage_search=blog to rank blog posts only
limitPages to return, 1-100, default 20limit=5 for a short list
page_url_scopemarketing (default), product or allInclude product-site pages

To see every query of one page, call page-report with page_path and gsc_breakdown=query.

Authorization

AuthorizationBearer <token>

API key as Bearer token

In: header

Query Parameters

limit?integer

Pages to return, ranked by revenue upside at #1. Default 20, max 100.

Range1 <= value <= 100
page_url_scope?string

Which host to scope to. Defaults to marketing. all removes the host predicate entirely (every host in the workspace).

Value in

  • "marketing"
  • "product"
  • "all"
range?string

Preset date range. Canonical names (last_30_days, last_7_days, last_3_months, last_6_months, last_year, all_time, …) and dashboard short keys (30d, 7d, 3m, 6m, 1y, all) are both accepted. Mutually exclusive with from/to.

Value in

  • "last_7_days"
  • "last_14_days"
  • "last_28_days"
  • "last_30_days"
  • "last_90_days"
  • "current_month"
  • "this_month"
  • "last_3_months"
  • "last_6_months"
  • "last_year"
  • "all_time"
  • "7d"
  • "14d"
  • "28d"
  • "30d"
  • "90d"
  • "3m"
  • "6m"
  • "1y"
  • "all"
from?string

Custom start date (YYYY-MM-DD). Ignored if range is set.

Match^\d{4}-\d{2}-\d{2}$
to?string

Custom end date (YYYY-MM-DD). Ignored if range is set.

Match^\d{4}-\d{2}-\d{2}$

Responses

Pages ranked by the revenue upside of ranking #1, #2 or #3

get/seo-opportunities
curl -X GET "https://d1iwal3igywepk.cloudfront.net/seo-opportunities?limit=5&page_search=blog"
Example Responses
{  "range": {    "from": "string",    "to": "string"  },  "window": {    "from": "string",    "to": "string"  },  "gsc_data_from": "string",  "currency": "eur",  "curve": [    {      "position": 0,      "ctr": 0,      "own_ctr": 0,      "own_impressions": 0,      "own_weight": 0,      "benchmark_ctr": 0    }  ],  "benchmark": {    "source": "string",    "url": "string",    "published": "string"  },  "rows": [    {      "page_path": "string",      "organic_new_customer_revenue_cents": 0,      "organic_new_customers": 0,      "organic_clicks": 0,      "revenue_per_click_cents": 0,      "upside_cents_at_1": 0,      "upside_cents_at_2": 0,      "upside_cents_at_3": 0,      "upside_clicks_at_1": 0,      "upside_clicks_at_2": 0,      "upside_clicks_at_3": 0,      "upside_range_at_1": {        "low_cents": 0,        "high_cents": 0,        "low_clicks": 0,        "high_clicks": 0      },      "upside_range_at_2": {        "low_cents": 0,        "high_cents": 0,        "low_clicks": 0,        "high_clicks": 0      },      "upside_range_at_3": {        "low_cents": 0,        "high_cents": 0,        "low_clicks": 0,        "high_clicks": 0      },      "excluded_zero_click_queries": 0,      "queries": [        {          "query": "string",          "position": 0,          "clicks": 0,          "impressions": 0,          "gain_cents": {            "at_1": 0,            "at_2": 0,            "at_3": 0          }        }      ]    }  ],  "insufficient_data": [    {      "page_path": "string",      "organic_new_customers": 0,      "organic_clicks": 0,      "organic_new_customer_revenue_cents": 0    }  ],  "insufficient_data_total": 0,  "notes": [    "string"  ],  "is_cached": true,  "age_s": 0,  "last_refresh": "string"}
application/json