Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Added "build_edge_rules", "build_seo_dashboard", "check_sitemap" and 12 more; changed the definition of "ai_crawler_policy", "analyze_layout", "analyze_logs" and 52 more (55 tools before, 70 now)
⟨18 unchanged words⟩ description":"Any page of the site.","maxLength":2048,"type":"string"}},"required":["url ⟨3 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨49 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨3 unchanged words⟩
⟨7 unchanged words⟩ log lines, one request per line.","maxLength":819200,"type":"string"},"sitemap_urls":{"description" ⟨8 unchanged words⟩ find pages bots never crawl.","items":{"maxLength":2048,"type":"string"},"maxItems":2000," ⟨6 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨14 unchanged words⟩ A bare domain like example.com also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨90 unchanged words⟩ call again with the same arguments until complete. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨10 unchanged words⟩ rank for the question.","items":{"maxLength":2048,"type":"string"},"maxItems":3,"minItems ⟨11 unchanged words⟩ 'how long does a passport renewal take'.","maxLength":2000,"type":"string"},"url":{"description":"Full address of the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":[ ⟨5 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}Quick check of the cookie banner setup from the HTML. To see what GA4 really sends before and after accepting, use check_ga4_tracking. Check a page's cookie consent setup from its ⟨62 unchanged words⟩
⟨8 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨9 unchanged words⟩ https://example.com/blog/post. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨11 unchanged words⟩ rank for, for example 'running shoes'.","maxLength":2000,"type":"string"},"url":{"description" ⟨8 unchanged words⟩ //example.com/pricing. A bare domain like example.com also works.","maxLength":2048,"type":"string"}},"required":[ ⟨4 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}Use when GA4 numbers look wrong or consent may not reach GA4. For a quick check of the banner setup from the HTML, use check_consent. Debug Google Analytics 4 on a live page ⟨108 unchanged words⟩
⟨8 unchanged words⟩ the page, for example https://example.com/.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨7 unchanged words⟩ of one language version of the page.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨9 unchanged words⟩ location page or the locations overview page.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨4 unchanged words⟩ description":"Full address of the page.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨8 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨120 unchanged words⟩ call again with the same arguments until complete. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨11 unchanged words⟩ rank for the topic.","items":{"maxLength":2048,"type":"string"},"maxItems":2,"type ⟨10 unchanged words⟩ ask for the topic.","items":{"maxLength":2000,"type":"string"},"maxItems":25,"minItems ⟨8 unchanged words⟩ main query, for example 'passport renewal'.","maxLength":2000,"type":"string"},"url":{"description":"Full address of the page.","maxLength":2048,"type":"string"}},"required":[ ⟨5 unchanged words⟩
before
—
{"description":"The same result as the text, as structured data.","type":"object"}⟨117 unchanged words⟩ the hardest sentences and paragraphs to rewrite first. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨8 unchanged words⟩ results for the keyword.","items":{"maxLength":2048,"type":"string"},"maxItems":8,"type ⟨3 unchanged words⟩ Optional: the search term, for context.","maxLength":2000,"type":"string"},"url":{"description":"Your page.","maxLength":2048,"type":"string"}},"required":[ ⟨3 unchanged words⟩
⟨4 unchanged words⟩ ":{"description":"Proposed meta description.","maxLength":2000,"type":"string"},"title":{"description":"Proposed title tag text.","maxLength":2000,"type":"string"}},"required":[ ⟨3 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ , or any page of the site.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨12 unchanged words⟩ in the same order.","items":{"maxLength":2000,"type":"string"},"maxItems":20,"type ⟨2 unchanged words⟩ description":"Addresses to check.","items":{"maxLength":2048,"type":"string"},"maxItems":20," ⟨8 unchanged words⟩
⟨8 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨56 unchanged words⟩ ,"type":"number"},"url":{"maxLength":2048,"type":"string"}},"required":["url ⟨26 unchanged words⟩
⟨4 unchanged words⟩ {"description":"HTML after the change.","maxLength":921600,"type":"string"},"before":{"description":"HTML before the change.","maxLength":921600,"type":"string"},"url":{"description":"Optional address the page lives at.","maxLength":2048,"type":"string"}},"required":[ ⟨4 unchanged words⟩
⟨94 unchanged words⟩ the same arguments until the comparison is complete. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨5 unchanged words⟩ ":"Competitor page addresses.","items":{"maxLength":2048,"type":"string"},"maxItems":3,"minItems ⟨5 unchanged words⟩ Optional search term to compare keyword use.","maxLength":2000,"type":"string"},"url":{"description" ⟨3 unchanged words⟩ example https://example.com. A bare domain also works.","maxLength":2048,"type":"string"}},"required":[ ⟨4 unchanged words⟩
⟨108 unchanged words⟩ page to get only what it is missing. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨8 unchanged words⟩ site audit, for internal link suggestions.","maxLength":2000,"type":"string"},"competitors":{"description":"Pages that rank for the term.","items":{"maxLength":2048,"type":"string"},"maxItems":3,"minItems ⟨6 unchanged words⟩ search term the page should rank for.","maxLength":2000,"type":"string"},"url":{"description":"Optional: your existing page for this term.","maxLength":2048,"type":"string"}},"required":[ ⟨4 unchanged words⟩
One page, every measurement by section: use it when scan_page is not detailed enough. For a whole site use start_site_audit. Everything OnPage.dev measures on a page, by section ⟨55 unchanged words⟩
⟨33 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨10 unchanged words⟩ start_site_audit, to export the whole site.","maxLength":2000,"type":"string"},"slack_webhook_url":{"description" ⟨6 unchanged words⟩ Teams) to post the summary to.","maxLength":2048,"type":"string"},"url":{"description":"Page to export the findings of.","maxLength":2048,"type":"string"}},"type":"object"}
⟨11 unchanged words⟩ 'how long does shipping take to Germany'.","maxLength":2000,"type":"string"},"url":{"description" ⟨6 unchanged words⟩ example https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"}},"required":[ ⟨4 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ the site, for example https://example.com.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}Writes validated JSON-LD for Article, Product, FAQPage, Organization or BreadcrumbList. For LocalBusiness use check_local_seo; to check JSON-LD you wrote yourself use validate_schema. Generate a JSON-LD block for a page from ⟨52 unchanged words⟩
⟨27 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ : your agency name for the header.","maxLength":2000,"type":"string"},"fix_log_id":{"maxLength":2000,"type":"string"},"format":{"description" ⟨24 unchanged words⟩ For the report: YYYY-MM. Default: all fixes.","maxLength":2000,"type":"string"},"verify":{" ⟨17 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}Use after a scan to get the fixes as code. Set platform to how the user ships: html (default), wordpress, git for a pull request, or cloudflare for an edge Worker. Generate ready-to-paste fixes for the issues on a ⟨129 unchanged words⟩
⟨105 unchanged words⟩ A bare domain like example.com also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨4 unchanged words⟩ description":"The id returned by start_site_audit.","maxLength":2000,"type":"string"}},"required":["audit_id ⟨2 unchanged words⟩
{"additionalProperties":false,"properties":{"watch_id":{"maxLength":2000,"type":"string"}},"required":["watch_id ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ existing log. Leave out to start one.","maxLength":2000,"type":"string"},"fixes":{"items" ⟨48 unchanged words⟩ , used to check it stays live.","maxLength":2048,"type":"string"},"note":{"description":"Optional short note, e.g. the issue code it fixed.","maxLength":2000,"type":"string"},"old":{"description" ⟨5 unchanged words⟩ for rollback. Empty if there was none.","maxLength":2048,"type":"string"},"ref":{"description":"Optional link, e.g. the pull request.","maxLength":2000,"type":"string"},"url":{"description" ⟨7 unchanged words⟩ a redirect: the old URL).","maxLength":2048,"type":"string"},"via":{"description" ⟨29 unchanged words⟩ went live, YYYY-MM-DD. Defaults to today.","maxLength":2000,"type":"string"},"webhook":{"description" ⟨12 unchanged words⟩ the restore code when a fix is undone.","maxLength":2048,"type":"string"}},"required":[ ⟨3 unchanged words⟩
—
⟨11 unchanged words⟩ (start_site_audit, then get_site_audit until complete).","maxLength":2000,"type":"string"},"important_urls":{"description" ⟨8 unchanged words⟩ pages by clicks or revenue.","items":{"maxLength":2048,"type":"string"},"maxItems":50," ⟨6 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨9 unchanged words⟩ finished site audit of the same site.","maxLength":2000,"type":"string"},"rows":{"description" ⟨13 unchanged words⟩ {"type":"number"},"page":{"maxLength":2048,"type":"string"},"position":{"type":"number"},"query":{"maxLength":2000,"type":"string"}},"required":[" ⟨14 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨132 unchanged words⟩ same query and pages that attract mixed intents. No SEO data tool connected? Ask the user for the pages that rank for the keyword.
⟨10 unchanged words⟩ keyword, in ranking order.","items":{"maxLength":2048,"type":"string"},"maxItems":8,"type ⟨2 unchanged words⟩ ":{"description":"The search term.","maxLength":2000,"type":"string"},"queries":{"description" ⟨17 unchanged words⟩ {"type":"number"},"page":{"maxLength":2048,"type":"string"},"position":{"type":"number"},"query":{"maxLength":2000,"type":"string"}},"required":["query ⟨7 unchanged words⟩ },"url":{"description":"Your page.","maxLength":2048,"type":"string"}},"type":"object"}
Use to answer "did our fixes win traffic?" with before and after numbers. For the score change of one page use rescan_and_compare. Show whether SEO fixes paid off, using numbers ⟨99 unchanged words⟩ The numbers are used for this answer only,andunlessnotyoustored.pass fix_log_id: then the result per page is saved in that fix log.
⟨19 unchanged words⟩ "Date the fixes went live, YYYY-MM-DD.","maxLength":2000,"type":"string"},"fix_log_id":{"description" ⟨19 unchanged words⟩ rollback plan for fixes that did worse.","maxLength":2000,"type":"string"},"pages":{"items" ⟨80 unchanged words⟩ : what was fixed on this page.","maxLength":2000,"type":"string"},"url":{"maxLength":2048,"type":"string"}},"required":["url
⟨27 unchanged words⟩ to read its sitemap instead of new_urls.","maxLength":2048,"type":"string"},"new_urls":{"items":{"maxLength":2048,"type":"string"},"maxItems":500,"type ⟨6 unchanged words⟩ to read its sitemap instead of old_urls.","maxLength":2048,"type":"string"},"old_urls":{"items":{"maxLength":2048,"type":"string"},"maxItems":500," ⟨4 unchanged words⟩
Use when Search Console, GA4, Ahrefs or Semrush data is available, also to explain a traffic drop (pass clicks_previous): ranks the fixes by the traffic or revenue they can win. Rank SEO fixes by how much traffic they ⟨178 unchanged words⟩
⟨12 unchanged words⟩ , so pages are not scanned again.","maxLength":2000,"type":"string"},"currency":{"description" ⟨119 unchanged words⟩ ,"type":"number"},"query":{"maxLength":2000,"type":"string"},"volume":{"description" ⟨48 unchanged words⟩ 0,"type":"number"},"url":{"maxLength":2048,"type":"string"}},"required":[" ⟨28 unchanged words⟩
Use to see what visitors and crawlers without JavaScript (GPTBot, ClaudeBot, PerplexityBot) get on the first screen. Load a page in a real browser on ⟨132 unchanged words⟩
⟨8 unchanged words⟩ the page, for example https://example.com/pricing.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨49 unchanged words⟩ until the score is where you want it. For traffic before and after a fix, use measure_impact.
⟨12 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨7 unchanged words⟩ HTML document, up to 900 KB.","maxLength":921600,"type":"string"},"url":{"description" ⟨7 unchanged words⟩ used for relative links and the canonical check.","maxLength":2048,"type":"string"}},"required":[ ⟨3 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨62 unchanged words⟩ a page performs in Google or AI search. For what crawlers without JavaScript see, use render_page; for a whole site, start_site_audit.
⟨14 unchanged words⟩ A bare domain like example.com also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨25 unchanged words⟩ description":"Full address of the page.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨9 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨27 unchanged words⟩ https://example.com. A bare domain also works.","maxLength":2048,"type":"string"}},"required":["url ⟨2 unchanged words⟩
⟨18 unchanged words⟩ it out to get a new one.","maxLength":2000,"type":"string"},"urls":{"description":"The changed URLs, all on one host.","items":{"maxLength":2048,"type":"string"},"maxItems":100," ⟨8 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨5 unchanged words⟩ :"Id of a completed site audit.","maxLength":2000,"type":"string"},"target_url":{"description" ⟨8 unchanged words⟩ new URL that is not live yet.","maxLength":2048,"type":"string"},"topic":{"description" ⟨10 unchanged words⟩ a new page; optional for an audited page.","maxLength":2000,"type":"string"}},"required":[ ⟨3 unchanged words⟩
⟨8 unchanged words⟩ to test instead of the live file.","maxLength":524288,"type":"string"},"url":{"description" ⟨7 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"},"user_agents":{"description" ⟨11 unchanged words⟩ and the main AI crawlers.","items":{"maxLength":2000,"type":"string"},"maxItems":20," ⟨6 unchanged words⟩
{"additionalProperties":false,"properties":{"watch_id":{"maxLength":2000,"type":"string"}},"required":["watch_id ⟨2 unchanged words⟩
before
—after
{"description":"The same result as the text, as structured data.","type":"object"}⟨8 unchanged words⟩ to validate instead of the live file.","maxLength":1048576,"type":"string"},"url":{"description" ⟨3 unchanged words⟩ example https://example.com/blog/post. A bare domain also works.","maxLength":2048,"type":"string"}},"required":[ ⟨3 unchanged words⟩
⟨9 unchanged words⟩ , with or without the <script> tag.","maxLength":1048576,"type":"string"}},"required":["jsonld ⟨2 unchanged words⟩
⟨28 unchanged words⟩ change writes the counter-move for your page.","maxLength":2048,"type":"string"},"url":{"description" ⟨4 unchanged words⟩ https://example.com/pricing. A bare domain also works.","maxLength":2048,"type":"string"},"webhook_url":{"description" ⟨11 unchanged words⟩ for example a Slack or Discord incoming webhook.","maxLength":2048,"type":"string"}},"required":[ ⟨3 unchanged words⟩
Site-wide fixes at the edge — Use when the same SEO problem repeats across a section of a site (all product pages, all blog posts) and the CMS or templates are hard to change: from a finished site audit, writes one Cloudflare Worker with a rule per section that fixes missing or badly sized titles and meta descriptions, missing canonicals and missing social tags on every matching page as it is served, with a preview of the changes. Only fills what is missing or out of range, never touches noindex, headings or content. For one page use get_fix_pack with platform cloudflare. Needs the domain on the user's own Cloudflare acco…
Blueprint for an SEO command center — Use when the user wants a live SEO dashboard in Claude (Claude Dashboards or an artifact): returns a complete blueprint that combines a realtime block from the user's own GA4 connection (active users per minute, pages, events, countries, devices), traffic from GA4 or Search Console, and SEO health, fixes, speed and AI visibility from an OnPage.dev feed. Includes the exact GA4 realtime fields, ready BigQuery SQL for the GA4 and Search Console exports, and the prompt to build it. With format html it returns a finished, designed dashboard page (light and dark) filled with the feed's data, with a…
Check the XML sitemap — Use to check a site's XML sitemap the way Google reads it: finds it through robots.txt or the usual locations, follows a sitemap index, and checks the format, the 50,000 URL and 50 MB limits, URLs on another host or protocol, and lastmod dates (missing, in the future, or all the same date, which Google then ignores). Then checks a sample of the listed URLs and flags the ones that do not belong in a sitemap: redirects, errors, noindex and pages whose canonical points elsewhere, with the corrected entries. Reads 4 sample URLs per call: call again with the same arguments until complete.
Parameters, filters and crawl traps — Use when a site has filter, sort, tracking or search URLs that waste crawl budget or create duplicates: classifies every query parameter found in a site audit's internal links (and in URLs you pass from server logs or Search Console) as tracking, session, internal search, sort, pagination or filter, counts the URLs per parameter, flags internal links that carry tracking or session parameters, crawlable search results and filter combinations, and paginated pages that canonicalise to page 1. Returns the robots.txt rules and canonical advice to fix it. Give audit_id, urls or both.
Core Web Vitals over time — Use to see whether speed changed for real users and since when, for example after a performance fix: Core Web Vitals (LCP, INP, CLS, FCP, TTFB) at the 75th percentile from Google's Chrome UX Report history, weekly for about 9 months, on phone and desktop. With change_date it compares the weeks before and after that date. Falls back to the whole site when the page has too little traffic. For the latest snapshot only, use check_web_vitals.
Start an SEO dashboard feed — Use when the user wants an SEO dashboard or client report that stays up to date: OnPage.dev then checks the site's key pages every day and keeps the history (score, AI readiness, errors and warnings with their codes, AI crawler access, and Core Web Vitals per week), ready for get_dashboard_data and build_seo_dashboard. Give the home page and up to 10 key pages (or leave pages out to take them from the sitemap). Optionally link a fix log to show shipped fixes. One feed per connection; replace: true swaps it for a new site. Returns a private feed_id: keep it.
Why did traffic drop? — Use when organic traffic dropped: fetch two periods of equal length from the user's Search Console (before and after the drop), per page or per page and query, and pass them here. Separates the causes per page: lost rankings, lower search demand or seasonality, a lower click-through rate at the same position (an AI Overview or new SERP feature, or a weaker snippet) and pages that disappeared from search. Ranks the losses by clicks and gives the next tool for each cause. With a fix_log_id it also flags losing pages whose logged fix was undone. The numbers are used for this answer only.
Why Google does not index a page — Use when pages are missing from Google: turns Search Console URL Inspection results (or rows from the Pages report: URL plus reason) into causes, fixes and the next OnPage.dev tool to run. Fetch them with the user's Search Console tool: for each URL its coverageState, verdict, indexingState, robotsTxtState, pageFetchState, googleCanonical, userCanonical and lastCrawlTime, or the reason column of the Pages report. Groups the URLs by cause, most serious first: noindex, blocked by robots.txt, Google chose a different canonical, crawled or discovered but not indexed, soft 404, not found, redirect…
Pull one value from many pages — Use to check a template change or a data point across many pages at once, like custom extraction in a crawler: give up to 20 URLs and one of a CSS selector (with an optional attribute, for example meta[property='og:image'] with content), a regular expression, or a JSON-LD path such as Product.offers.price. Returns the values per page, which pages have none, and how many distinct values there are. Reads 5 pages per call: call again with the same arguments until complete.
Pages that rank but do not get clicked — Use to find quick wins without ranking changes: from the user's Search Console rows (page, or page and query, with impressions, clicks or CTR and position), finds results on page 1 whose click-through rate is well below normal for their position, and estimates the clicks a better title and meta description could win. Next: check_snippet to test new titles, get_fix_pack to ship them. Brand searches and results under an AI Overview can have a naturally lower CTR. The numbers are used for this answer only.
Near-duplicate pages — Use to find pages that say almost the same thing, which compete with each other and make Google pick one: groups the pages of a finished site audit by text similarity (near-duplicates from about 75% the same), with their titles, word counts and canonicals, and per group the page to keep and what to do with the others: a canonical, a merge with a 301 redirect (plan_redirects writes the rules) or a rewrite for a different search intent.
Queries almost on page 1 — Use to find the fastest ranking wins: from the user's Search Console rows by query and page, finds queries ranking at positions 8 to 20 with real impressions, groups them per page, estimates the clicks a move into the top 5 could win, and flags queries where two pages compete. Next per page: check_focus_keyword with the query, check_question_coverage, compare_pages and suggest_internal_links. The numbers are used for this answer only.
SEO history as dashboard tables — Use to fill an SEO dashboard or report from a feed made with create_dashboard_feed: returns one dataset as a clean table with a date column (YYYY-MM-DD) and full page URLs, so it joins with GA4 and Search Console data or their BigQuery exports. Datasets: overview (site score, AI readiness, errors and warnings per day), pages (per page per day), issues (pages per issue code per day), open_issues (what is wrong now, per page), vitals (Core Web Vitals per week, phone and desktop), ai_access (AI crawlers allowed per day) and fixes (from the linked fix log). Claude Dashboards can chart and refresh…
Make a JavaScript app readable for AI crawlers — Use when a site is built in the browser (React, Vue, Angular) and AI crawlers such as GPTBot, ClaudeBot and PerplexityBot, which do not run JavaScript, see an empty page. Checks the page first, then writes a Cloudflare Worker that serves those crawlers the rendered HTML (made with Cloudflare Browser Rendering in the user's own account and cached for a day), while visitors and Google get the normal page. Says so when the page already sends its text and nothing is needed. Server-side rendering stays the better long-term fix; use get_fix_pack with platform git for that. Needs the domain on the u…
Did the fixes win AI citations? — Use to prove AI visibility gains: pass how often AI assistants cited each page before and after the fixes (from Ahrefs Brand Radar or another AI-visibility tool connected in the chat), for the pages you changed and a few you did not as a control group. Compares the change per page and per engine (ChatGPT, Perplexity, Google AI Overviews and AI Mode, Gemini, Copilot), against the control group, so a general rise in AI traffic is not counted as your result. The numbers are used for this answer only.
Added "check_ga4_tracking", "check_local_seo", "get_fix_log" and 2 more; changed the definition of "get_fix_pack", "measure_impact" and "watch_page" (50 tools before, 55 now)
⟨51 unchanged words⟩ code and the steps to open a pullrequest.request, or cloudflare for a Cloudflare Worker that applies the fixes as the page is served, on any CMS, when the domain runs through the user's own Cloudflare.","enum":["html","wordpress","git","cloudflare"],"type":"string"},"url": ⟨23 unchanged words⟩
⟨23 unchanged words⟩ live, YYYY-MM-DD.","type":"string"},"fix_log_id":{"description":"Optional fix log from log_fix: takes the fix date from it and saves the result per fix, with a rollback plan for fixes that did worse.","type":"string"},"
Certificate recorded, valid to 2026-12-30
Authorization not required
Added "check_accessibility", "check_answer_format", "check_consent" and 5 more (42 tools before, 50 now)
Accessibility report (WCAG 2.1 AA) — Check a page against WCAG 2.1 level AA, the standard behind the European Accessibility Act (EN 301 549): page language, text alternatives, form labels, link and button names, headings, page title, zoom, landmarks and frames, each mapped to its WCAG success criterion. Contrast, reflow and the screen reader view are added when a real-browser check of the page ran in the last 15 minutes (render_page or screen_reader_view). Lists the criteria that need a manual check, such as keyboard use and focus.
Answer format that wins — For a question people search (a featured snippet or a People Also Ask question), find the section that answers it on the pages that rank and on your page, and compare the format: a paragraph (and its length), a list (and its items) or a table (and its rows). Returns the format that wins and how to rewrite your section to match. Fetch the top results for the query with the user's Ahrefs, Semrush or search tool and pass up to 3 as competitors. Scans one page per call: call again with the same arguments until complete.
Cookie banner and Consent Mode — Check a page's cookie consent setup from its HTML: which consent platform runs (Cookiebot, OneTrust, Usercentrics, CookieYes, Complianz, Didomi and more), whether Google Analytics or Tag Manager loads, whether Google Consent Mode sets a default before those tags, and whether the Consent Mode v2 signals ad_user_data and ad_personalization are there. When a real-browser check ran in the last 15 minutes, it also reports a cookie wall that covers the page.
Added "analyze_logs", "check_web_vitals" and "submit_indexnow"; changed the definition of "check_ai_visibility", "check_readability", "get_fix_pack" and 2 more (39 tools before, 42 now)
⟨23 unchanged words⟩ citable the content is for AI answers (1415 checks, including fact density, cited outside sourcesand, whether question headings get a direct answer and whether every section opens with its point), and how an AI model sees the ⟨16 unchanged words⟩
⟨73 unchanged words⟩ ease with the pages that rank. Returns the
Added "check_og_tags" (38 tools before, 39 now)
Check Open Graph and social tags — Check how a page looks when it is shared on Facebook, LinkedIn, X, WhatsApp, Slack or iMessage: every Open Graph and Twitter Card tag, and the share image itself (does it load, its real size in pixels, file type and weight) against what these platforms need. Returns a score, the issues to fix and the tags to add. The same check is free as a public REST API: GET https://onpage.dev/api/v1/og?url=…
Added "check_readability", "export_findings", "match_intent" and 1 more; changed the definition of "analyze_layout", "get_fix_pack" and "render_page" (34 tools before, 38 now)
⟨7 unchanged words⟩ measured in your own browser: the samefirst-screenchecks as render_page (H1 and call to action position, pop-ups, tap targets, small text, sideways scrolling and its cause, low-contrast text, inconsistent buttons, uneven spacing, layout shift, largest element), plus a ⟨27 unchanged words⟩
Generate ready-to-pasteHTMLfixes for the issues on a page, built ⟨21 unchanged words⟩
Unknown → Live
First tool surface recorded: 34 tools (server version 1.4.0)
https://onpage.dev/mcp (mcp_streamable_http) — from mcp_registry, with the record
Showing the latest 11 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
after
{"description":"The same result as the text, as structured data.","type":"object"}{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":truefalse,"title":"Measure impact"}
⟨86 unchanged words⟩ Watches end after 90 days without a check. To watch a competitor, pass their page as url and yours as competitor_of: every change they make comes with the counter-move for your page.
{"additionalProperties":false,"properties":{"competitor_of":{"description":"Optional: your own page. Then url is a competitor: OnPage.dev also tracks their new sections, structured data, length and description, and with each change writes the counter-move for your page.","type":"string"},"url":{"description":"Full address, for ⟨37 unchanged words⟩
GA4 tracking debugger — Debug Google Analytics 4 on a live page in a real browser, the way Tag Assistant would: which GA4 measurement IDs (G-), Google Tag Manager containers (GTM-) and old Universal Analytics tags are installed, then the hits the page really sends to Google, in three steps: a first visit before any cookie choice, after clicking accept in the cookie banner, and a return visit. Finds page_view not firing or firing twice (double counting), hits sent before consent, Consent Mode states (gcs) that do not change after accept, debug mode left on, Universal Analytics leftovers and IDs that differ from what …
Local SEO: business markup, NAP and locations — Check a local business site for Google Maps and local search: LocalBusiness markup (most specific type, address, phone, opening hours, geo coordinates), whether name, address and phone (NAP) in the markup match what the pages show, a link to the Google Business Profile, a map, the city in the title, and a page with its own markup for every location. Reads the home page, the Contact page and up to 4 location pages linked from the given page (run it on the locations overview to check those), 2 pages per call: call again with the same arguments until complete. Writes a corrected LocalBusiness JS…
Fix log: still live, impact and client report — Show a fix log: per fix whether it is still live, undone or changed since it shipped, with the restore code for every undone fix, the measured impact when measure_impact ran with this fix_log_id, and a rollback plan (the old value back) for fixes that made a page do worse. format 'report' writes a client-ready monthly report without OnPage.dev branding; format 'annotations' gives GA4 annotations that mark every fix in the user's GA4 charts. verify true re-checks up to 4 pages now; otherwise the last automatic check is shown.
Log shipped fixes — Record SEO fixes after they ship, so OnPage.dev keeps them honest: it checks about every 6 hours that each fix is still live (title, description, canonical, robots, H1, Open Graph, hreflang, JSON-LD type, redirect target), sends the restore code to a webhook when a deploy undoes one, gives measure_impact the dates and pages, and turns it all into a client report. Call it right after a pull request merges, a WordPress change is applied or an edge fix deploys, with the old and new value of each change. Without fix_log_id it starts a new private log and returns its id: keep it, it is the only ke…
Internal link equity and click depth — Map how link authority flows through a site from a finished site audit: internal PageRank per page, click depth from the home page, links in and out. Finds pages the home page cannot reach, pages too many clicks deep, dead ends that pass nothing on, strong pages that link to few others, links that run through redirects or to broken or noindex pages, and important pages with too few links. Give important_urls (for example your top pages from Search Console or GA4, or the pages that make money) to check those first; then use suggest_internal_links to pick where the new links go.
Hreflang check for multilingual sites — Check the hreflang setup of a multilingual page: valid language and region codes, x-default, the self-reference and duplicates, then each language version: does it return 200, is it indexable, does its canonical point to itself, does it link back (return tags) and does its html lang match. Returns the problems with fixes and the corrected tag set, ready to paste. Checks up to 4 language versions per call: call again with the same arguments until complete.
Ecommerce product page check — Check an ecommerce product page for Google: Product structured data with name, image, price, currency and availability, identifiers (SKU, GTIN, MPN, brand), shipping and return policy for merchant listings, ratings, variants (ProductGroup), out-of-stock handling, breadcrumbs, and filter or variant URLs with their canonical. Each failed check comes with the fix; use generate_schema with type Product for the code.
Question coverage for AI Mode and AI Overviews — Check how well a page covers a topic the way AI search reads it. AI Mode and AI Overviews split a search into many sub-questions (a query fan-out) and pick a source for each. Before calling, write the sub-questions an AI search engine would ask for the topic yourself: 8 to 20 short questions covering what it is, how it works, cost, time, steps, comparisons, risks, alternatives and who it is for. The tool finds the passage that answers each question on the page, rates it answered, partly answered or missing, and returns a coverage score, the gaps and the sections to add. Pass up to 2 competito…
Trust signals (E-E-A-T) across the site — Check the trust signals Google and AI models look for across a site, not only on one page: an About page with real content, contact details (email, phone, address), privacy and terms pages, company identifiers (Chamber of Commerce, VAT), Organization markup with logo and profile links, links to social profiles, and on articles a named author and dates. Finds the About, Contact, Privacy and Terms pages from the page's own links (English, Dutch, German, French, Spanish) and checks 2 of them per call: call again with the same arguments until complete.
Topic clusters from Search Console — Group a site's search queries into topic clusters and map them to pages: which page owns each topic, where several pages compete for the same topic, which topics have no page that targets them, and which internal links would strengthen the owner page. Fetch Search Console rows by query and page (clicks, impressions, position; up to 1000, last 3 months) with the user's Search Console tool and pass them as rows. Pass the audit_id of a finished site audit to also find pages without search demand and to check titles and H1s.
⟨81 unchanged words⟩ MCP server) after the user approves each change. With platform git it returns the fixes as code for the site's framework (Next.js, Nuxt, SvelteKit, Astro, Angular, React, Vue or plain HTML, detected from the page) and the steps to ship them as a pull request on a new branch, checked with scan_html before the user merges.
{"additionalProperties":false,"properties":{"framework":{"description":"With platform git: the site's framework. auto (default) detects it from the page.","enum":["auto","nextjs-app","nextjs-pages","nuxt","sveltekit","astro","angular","react","vue","html"],"type":"string"},"platform":{"description":"html (default) for code to paste, wordpress for a plan your WordPress connection canapply.apply, git for framework code and the steps to open a pull request.","enum":["html","wordpress","git"],"type":"string"},"url": ⟨23 unchanged words⟩
⟨10 unchanged words⟩ using data from the user's other connected tools. With GA4, also pass each page's organic conversions (key events) or revenue, and fixes are ranked by the money they can bring instead of clicks. Pass clicks_previous (an earlier period of the same length) to catch pages that are losing clicks and need a content refresh. Before calling, look at your available tools: ⟨115 unchanged words⟩
⟨16 unchanged words⟩ scanned again.","type":"string"},"currency":{"description":"Currency of revenue, for example EUR or USD.","maxLength":3,"type":"string"},"pages":{"items":{"properties":{"backlinks ⟨5 unchanged words⟩ "minimum":0,"type":"number"},"clicks_previous":{"description":"Clicks in an earlier period of the same length, for example the same 3 months a year or 6 months ago. Pages that lost clicks get a refresh fix.","minimum":0,"type":"number"},"conversions":{"description":"Conversions (GA4 key events, sales, leads) from this page's organic visits in the same period.","minimum":0,"type":"number"},"ctr":{"description":"Click-through rate, 0-1 ⟨52 unchanged words⟩ 20,"type":"array"},"referring_domains":{"minimum":0,"type":"number"},"revenue":{"description":"Revenue from this page's organic visits in the same period.","minimum":0,"type":"number"}," ⟨47 unchanged words⟩
⟨6 unchanged words⟩ "array"},"mode":{"enum":["revenue","conversions","traffic","severity"],"type":"string"} ⟨10 unchanged words⟩
⟨31 unchanged words⟩ headings, words, speed, structured data). Client-side apps (React, Angular, Vue) are loaded in a real browser and the rendered page is scanned. Use this first for any question about how ⟨8 unchanged words⟩
What search and AI bots really crawl — Analyse server access log lines to see what Googlebot, Bingbot and AI crawlers (GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, Applebot, Meta, Amazon, ByteDance, CCBot) actually request: hits per bot, the pages they crawl most, errors and redirects they get, crawl budget spent on parameters and assets, and, with the site's sitemap URLs, which pages Googlebot never visits. Pass raw lines in the common or combined log format (Apache, Nginx, Cloudflare, most hosts), up to 5000 lines. Logs can hold visitor IP addresses: only send them when the user agrees.
Core Web Vitals from real users — Get Core Web Vitals from real Chrome users (the Chrome UX Report, the field data Google uses for ranking): LCP, INP, CLS, FCP and TTFB at the 75th percentile, on phones and desktops, each rated good, needs improvement or poor. Falls back to the whole site when the page has too little traffic. Use render_page for lab checks of the first screen.
Tell search engines a page changed — Submit changed URLs to IndexNow, so Bing, Yandex, Naver, Seznam and Yep recrawl them within minutes instead of days. Call it after a fix is live. The first time, call it without key: it returns a key and the file to put on the site (ship it with the user's Git or WordPress tools). Then call it again with the key. All URLs must be on the same host. Google does not use IndexNow: for Google, use URL Inspection in the user's Search Console tool.
{"additionalProperties":false,"properties":{"platform":{"description":"html (default) for code to paste, wordpress for a plan your WordPress connection can apply.","enum":["html","wordpress"],"type":"string"},"url":{"description":"Full address of the ⟨18 unchanged words⟩
⟨40 unchanged words⟩ is the text readable, does it scroll sideways (and which element causes it), how much does the layout shift, and which element is the largest. Also checks design and readability: text with too little contrast (WCAG AA), inconsistent button styles and uneven spacing between sections. Also loads it with JavaScript off and shows ⟨47 unchanged words⟩
Readability for the page type and the pages that rank — Check how easy a page is to read, against the right target. A product page should read differently from documentation, so the target depends on the page type (guide, listicle, product, category, service, docs, news, recipe and more). For the best benchmark, also pass the keyword and the top results from the user's Ahrefs or Semrush as competitors: OnPage.dev scans them (one per call, call again until done) and compares your reading ease with the pages that rank. Returns the Flesch reading ease (Flesch-Douma for Dutch), average sentence length, the share of long sentences, and the hardest sent…
Send findings to Sheets, Slack, Notion or a task board — Turn a page scan or a finished site audit into an action plan the team can work from. Returns: rows for a spreadsheet plus a private CSV link that loads straight into Google Sheets with =IMPORTDATA (no connector needed), a ready Slack message, one task per issue for Linear, Jira, Asana, Trello or GitHub Issues, and a Markdown checklist for Notion or Confluence. If the user has a Google Sheets, Slack, Notion or task board tool connected, use it to send the output there. Optionally posts the Slack message to an https incoming webhook. Pass url for one page or audit_id for a whole site.
Match a page to search intent — Check whether a page matches what searchers want for a keyword, based on what actually ranks. Fetch the top organic results for the keyword with the user's connected Ahrefs, Semrush or other SERP tool (5 to 8 URLs), and pass them as competitors with your page as url. OnPage.dev scans every page, one per call (call again with the same arguments until done), works out the page type Google rewards (guide, product page, category page, comparison or list, tool, local page, homepage) and the format (length, headings, FAQ, year in the title), and tells you whether your page fits and what to change. …
Measure what the fixes did — Show whether SEO fixes paid off, using numbers from the user's connected tools. Fetch two periods of equal length from Google Search Console, GA4, Ahrefs or Semrush, one before and one after the fix date (28 days each works well), for the pages you changed and, ideally, a few pages you did not change as a control group. Pass them here with changed true or false. OnPage.dev compares clicks, impressions, CTR and position, subtracts the trend of the unchanged pages so seasonality and Google updates are not counted as your result, and lists what changed on each page from the watch history when yo…