90 checks. Every one explained.
Our whole method, in the open. Agencies call this their secret framework.
Work that runs itself.
Missing a connection? The step says what it needs and the rest carries on.
Onboard a site
Full crawl, the whole catalogue, the topic model, the gap analysis and the first set of briefs. This is the run that replaces the audit an agency charges for.
Weekly growth cycle
Re-crawl what changed, close the findings that were fixed, catch new ones, refresh the content queue and report the difference against last week.
Fix and publish
Take approved changes and apply them: through the CMS where one is connected, as a webhook payload, a pull request or plain text where one is not.
Content production
Brief, draft, run the quality gates, route to review. A draft that fails a gate never reaches the queue.
AI answer tracking
Crawler access, extractability, citable passages and entity strength. Flags factual assertions engines make about you for checking against your own facts.
Local cycle
Profile completeness, this week's post, replies to every new review, citation consistency and geo grid position.
Link building
Prospect, qualify, draft something that references what the recipient actually published, send from your domain under a cap, and stop the moment somebody replies.
Monthly report
What was done, what it cost, what moved and what is next. Written as a narrative, with the trace behind every claim.
Every check, by category.
“Fix generated” means the finished change comes attached. The rest come with clear guidance.
Technical and crawl 17 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Page is blocked from indexing page_noindex | A noindex directive removes the page from search results entirely. | critical | 1.00 | 0.20 | guidance |
| Server error page_5xx | A 5xx page cannot be indexed and burns crawl budget on every visit. | critical | 1.00 | 0.60 | guidance |
| Redirect loop redirect_loop | The URL never resolves, so neither users nor crawlers reach content. | critical | 1.00 | 0.40 | guidance |
| robots.txt blocks a page that should rank robots_blocks_important | Disallowed URLs cannot be crawled, so their content never enters the index. | critical | 1.00 | 0.20 | guidance |
| Page is not served over HTTPS no_https | HTTPS is a ranking signal and browsers warn users on insecure pages. | critical | 0.90 | 0.50 | guidance |
| Broken internal link page_404_linked | Internal links to 404s waste crawl budget and strand users mid-journey. | high | 0.60 | 0.20 | fix generated |
| No XML sitemap found no_sitemap | A sitemap is how a search engine learns about pages your internal links miss. | high | 0.60 | 0.30 | fix generated |
| HTTPS page loads insecure resources mixed_content | Browsers block or warn on mixed content, breaking the page for some users. | high | 0.50 | 0.30 | guidance |
| Canonical points to a different page canonical_mismatch | The page is telling search engines to index something else, so it will not rank. | high | 0.70 | 0.20 | guidance |
| Redirect chain redirect_chain | Each extra hop loses a little authority and adds latency. | medium | 0.40 | 0.30 | fix generated |
| Orphan page orphan_page | No internal link points here, so it gets little crawl attention and no internal authority. | medium | 0.50 | 0.30 | fix generated |
| Sitemap lists pages that cannot be indexed sitemap_contains_non_indexable | Submitting noindex or redirected URLs sends a contradictory signal. | medium | 0.40 | 0.20 | fix generated |
| Sitemap omits pages that are live and indexable sitemap_missing_pages | Pages missing from the sitemap rely entirely on internal links to be found. | medium | 0.35 | 0.20 | fix generated |
| No canonical tag canonical_missing | Without a canonical, parameter and variant URLs compete with each other. | medium | 0.40 | 0.20 | fix generated |
| No robots.txt robots_missing | Without one, every crawler guesses, and you lose the place to declare your sitemap. | low | 0.25 | 0.10 | fix generated |
| Page is more than four clicks from the homepage deep_page | Depth correlates with crawl frequency and with how much internal authority a page receives. | low | 0.30 | 0.30 | fix generated |
| No lang attribute on the html element no_lang_attribute | Screen readers and translation systems need to know the document language. | low | 0.20 | 0.10 | fix generated |
Content and on-page 17 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Duplicate page content duplicate_content | Identical content splits signals between URLs and can suppress all of them. | high | 0.60 | 0.50 | guidance |
| Missing title tag title_missing | The title is the strongest on-page relevance signal and the search result headline. | high | 0.80 | 0.10 | fix generated |
| Thin content thin_content | Too little substance to satisfy the query or to be worth citing. | high | 0.60 | 0.70 | guidance |
| Duplicate title tag duplicate_title | Identical titles make pages compete and give searchers no reason to pick one. | medium | 0.40 | 0.20 | fix generated |
| Missing meta description meta_description_missing | Search engines will assemble a snippet themselves, usually less persuasively. | medium | 0.35 | 0.10 | fix generated |
| No H1 heading h1_missing | The H1 confirms the page topic to readers, assistive technology and crawlers. | medium | 0.40 | 0.10 | fix generated |
| Page links to nothing internally no_internal_links_out | A page that links nowhere is a dead end for both users and authority flow. | medium | 0.35 | 0.20 | fix generated |
| Content has not been updated in over 18 months content_stale | Freshness matters for queries where the answer changes, and stale pages decay. | medium | 0.45 | 0.50 | guidance |
| Several pages target the same query keyword_cannibalisation | Pages competing for one query split their signals and neither wins. | medium | 0.50 | 0.40 | guidance |
| Image without alt text image_alt_missing | Alt text is an accessibility requirement and the only way image search understands the file. | medium | 0.30 | 0.10 | fix generated |
| Duplicate meta description duplicate_meta_description | Repeated descriptions lower click-through because the snippet is not about this page. | low | 0.25 | 0.20 | fix generated |
| Title is longer than the search snippet title_too_long | Truncated titles hide the part that would have earned the click. | low | 0.25 | 0.10 | fix generated |
| Title is very short title_too_short | A short title leaves relevance and click-through on the table. | low | 0.25 | 0.10 | fix generated |
| Meta description is outside the snippet length meta_description_length | Too short wastes the space; too long gets cut mid-sentence. | low | 0.20 | 0.10 | fix generated |
| More than one H1 h1_multiple | Multiple H1s blur which topic the page is actually about. | low | 0.20 | 0.20 | fix generated |
| Heading levels skip heading_hierarchy_broken | Jumping from H2 to H4 breaks the document outline for screen readers and parsers. | low | 0.20 | 0.20 | fix generated |
| Headings carry no topical information no_meaningful_headings | Generic headings tell neither a reader nor a parser what the section covers. | low | 0.25 | 0.20 | fix generated |
AI answers (AEO and GEO) 11 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| The page's content only exists after JavaScript runs content_needs_javascript | AI crawlers do not execute JavaScript. GPTBot, ClaudeBot and PerplexityBot read the raw HTML and nothing else, so a page whose copy is assembled in the browser is a blank page to every answer engine except Google's. | critical | 0.90 | 0.70 | guidance |
| AI crawlers are blocked ai_crawler_blocked | Blocking GPTBot, ClaudeBot, PerplexityBot and friends removes the site from AI answers. | high | 0.70 | 0.20 | fix generated |
| Title or description is injected by script rather than served meta_needs_javascript | A title set by JavaScript is a title half the machines reading the page never see. Google usually renders and catches it. The answer engines do not. | high | 0.70 | 0.40 | guidance |
| An SEO tool is injecting fixes client side seo_injection_script | Scripts that apply SEO changes in the browser produce fixes no AI crawler can see, and the changes disappear the day the subscription stops because they were never written into the site. | high | 0.60 | 0.50 | guidance |
| Body content is not present in the served HTML content_not_extractable | If the HTML arrives empty, an answer engine that does not execute JavaScript sees nothing. | high | 0.80 | 0.70 | guidance |
| Page does not answer its question directly no_direct_answer | Answer engines quote the passage that states the answer plainly near the top. | medium | 0.50 | 0.40 | fix generated |
| No citable facts or data no_citable_facts | Models cite pages that contain specific numbers, dates and named sources. | medium | 0.45 | 0.60 | guidance |
| No identifiable author no_author_attribution | Experience and expertise cannot be assessed without a real, credentialed author. | medium | 0.45 | 0.40 | guidance |
| The brand entity is not defined entity_unclear | Answer engines resolve brands through consistent entity signals, not prose. | medium | 0.40 | 0.30 | fix generated |
| No llms.txt missing_llms_txt | An llms.txt gives answer engines a curated map of what matters on the site. | low | 0.20 | 0.20 | fix generated |
| Questions are answered without FAQ structure no_faq_structure | A question heading followed by a short answer is the shape an engine lifts. | low | 0.30 | 0.20 | fix generated |
Local and maps 8 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Business name, address or phone is inconsistent nap_inconsistent | Conflicting NAP data undermines the confidence that drives map pack ranking. | high | 0.60 | 0.40 | guidance |
| Address and phone are not on the site nap_missing | A local business without visible contact details cannot be verified by anyone. | high | 0.60 | 0.20 | fix generated |
| Google Business Profile is incomplete gbp_incomplete | Profile completeness correlates directly with map pack visibility. | high | 0.60 | 0.30 | fix generated |
| No recent Google Business Profile posts gbp_no_recent_posts | An inactive profile signals an inactive business to both users and the ranking system. | medium | 0.35 | 0.20 | fix generated |
| Reviews have no response reviews_unanswered | Responding is a documented local ranking factor and changes how prospects read the profile. | medium | 0.40 | 0.20 | fix generated |
| No landing page for this location missing_location_page | Each location needs a page to rank for its own city and to link the profile to. | medium | 0.50 | 0.60 | fix generated |
| No LocalBusiness markup no_local_schema | LocalBusiness schema carries the hours, address and geo that map surfaces read. | medium | 0.45 | 0.20 | fix generated |
| Missing directory citation citation_missing | Citations on authoritative directories reinforce the entity and its NAP. | low | 0.25 | 0.30 | guidance |
Speed and Core Web Vitals 7 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Server response is slow slow_response | Time to first byte sits in front of every other performance metric. | high | 0.55 | 0.50 | guidance |
| Page weight is large heavy_page | Weight is the part of Core Web Vitals you control without touching the framework. | medium | 0.40 | 0.50 | guidance |
| Very large JavaScript payload excessive_javascript | Parse and execution time on mid-range phones is where most performance is lost. | medium | 0.40 | 0.70 | guidance |
| Render-blocking stylesheets and scripts render_blocking_resources | Anything parsed before first paint delays first paint. | medium | 0.40 | 0.50 | guidance |
| Image uses a legacy format image_legacy_format | WebP and AVIF are typically 25 to 50 percent smaller at the same quality. | low | 0.25 | 0.30 | fix generated |
| Image has no width and height image_no_dimensions | Missing dimensions cause layout shift as the image loads. | low | 0.25 | 0.10 | fix generated |
| Below-the-fold images load eagerly image_no_lazy_loading | Every eager image competes with the hero for bandwidth on first paint. | low | 0.20 | 0.10 | fix generated |
Structured data 6 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Structured data is invalid schema_invalid | Invalid JSON-LD is ignored entirely, so the effort already spent earns nothing. | high | 0.50 | 0.30 | fix generated |
| Structured data does not match the visible page schema_contradicts_page | Markup that describes content a user cannot see is a manual action risk. | high | 0.70 | 0.30 | guidance |
| No structured data schema_missing | Without schema the page cannot earn rich results and is harder for answer engines to parse. | medium | 0.45 | 0.30 | fix generated |
| Structured data is missing required properties schema_missing_required | Rich results need the required fields; without them the markup is decorative. | medium | 0.40 | 0.20 | fix generated |
| No Organization or LocalBusiness markup on the homepage no_organization_schema | This is the markup that tells every engine who the brand is. | medium | 0.50 | 0.20 | fix generated |
| No breadcrumb markup no_breadcrumb_schema | Breadcrumbs replace the URL in the result and show where the page sits. | low | 0.25 | 0.20 | fix generated |
Authority and links 6 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Toxic backlinks detected toxic_backlinks | Links from spam networks can drag a site down and occasionally trigger a manual action. | high | 0.50 | 0.40 | guidance |
| No backlink data source connected backlinks_not_connected | Link work is guesswork until the referring domain set is known. | high | 0.60 | 0.10 | guidance |
| Backlinks lost lost_backlinks | Losing earned links reverses the authority that earned the rankings. | medium | 0.40 | 0.40 | guidance |
| Brand mentioned without a link unlinked_mention | The hardest part, the coverage, already happened. The link is one email away. | medium | 0.40 | 0.20 | guidance |
| Competitors have substantially more referring domains authority_gap | For competitive queries, link authority is often the binding constraint. | medium | 0.55 | 0.80 | guidance |
| Nothing on the site is worth linking to no_linkable_asset | Outreach fails without an asset: original data, a tool, or a genuine reference. | medium | 0.50 | 0.80 | guidance |
Experience and conversion 4 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Page format does not match search intent intent_mismatch | A product page cannot win an informational query however well it is optimised. | high | 0.70 | 0.60 | guidance |
| Page is not mobile friendly mobile_unfriendly | Indexing is mobile-first, and most traffic is mobile. | high | 0.70 | 0.50 | fix generated |
| No clear call to action no_clear_cta | Traffic that cannot convert is a cost, not a result. | medium | 0.50 | 0.30 | guidance |
| No Open Graph or Twitter card no_social_preview | Shared links render as a bare URL, which nobody clicks. | low | 0.25 | 0.10 | fix generated |
Compliance and risk 4 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Health, legal or financial content with no stated credentials ymyl_no_credentials | For topics that affect health or money, unqualified advice is both a ranking and a liability problem. | high | 0.70 | 0.40 | guidance |
| Claim published without substantiation unsubstantiated_claim | Unsupported superlatives and performance claims carry regulatory risk in most markets. | high | 0.50 | 0.20 | guidance |
| Affiliate or sponsored content without disclosure missing_disclosure | Undisclosed commercial relationships breach platform policy and advertising law. | medium | 0.50 | 0.10 | fix generated |
| No privacy policy found no_privacy_policy | It is a legal requirement in most markets and a trust signal everywhere. | medium | 0.35 | 0.20 | guidance |
Measurement 4 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| No analytics tag detected analytics_missing | Without measurement, nothing that follows can be attributed or defended. | high | 0.60 | 0.20 | guidance |
| Search Console is not connected gsc_not_connected | Search Console is the only first-party source of query and indexing truth. | high | 0.80 | 0.10 | guidance |
| Analytics is not connected to the platform ga4_not_connected | Without session and conversion data, the reporting cannot show what the work earned. | medium | 0.50 | 0.10 | guidance |
| No conversion tracking conversion_tracking_missing | Ranking without conversion data optimises for the wrong thing. | medium | 0.50 | 0.40 | guidance |
International targeting 3 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Hreflang has no return tag hreflang_missing_return | Hreflang is only honoured when every version points back at the others. | high | 0.50 | 0.30 | fix generated |
| Invalid hreflang language or region code hreflang_invalid_code | An invalid code is ignored, so the targeting silently does nothing. | medium | 0.35 | 0.20 | fix generated |
| No x-default hreflang no_x_default | Users outside your targeted regions get an arbitrary version. | low | 0.20 | 0.20 | fix generated |
Ecommerce 3 checks
| Check | Why it matters | Severity | Impact | Effort | Fix |
|---|---|---|---|---|---|
| Product markup is missing merchant listing fields product_schema_incomplete | Without price, availability and identifiers the product cannot appear in shopping surfaces. | high | 0.60 | 0.30 | fix generated |
| Faceted navigation is generating crawlable duplicate URLs faceted_nav_crawl_waste | Filter combinations can multiply into millions of near-identical pages. | high | 0.60 | 0.50 | guidance |
| Product pages carry no review markup no_product_reviews | Ratings in the result are the single largest click-through lever in shopping. | medium | 0.40 | 0.40 | guidance |
Five levels of hands-off.
Pick how much ships without you. The risky stuff always waits, whatever you pick.
What each level ships on its own
| Level | Ships on its own | Always waits for you |
|---|---|---|
| Observe | Nothing. Audit and report only | Everything |
| Propose | Nothing, but everything is queued and ready | Everything |
| Assist | Low-risk reversible fixes, after a delay you set | Content, outreach, anything site-wide |
| Operate | Technical fixes and schema | Content, outreach, anything site-wide |
| Autopilot | Everything reversible | Content, outreach, anything irreversible or site-wide |
Works with nothing connected.
No twelve login screens before you see anything. Each connection adds a bit more, and the dashboard says exactly what.
Tell us about your business.
Thirty minutes with a specialist. You leave with a plan, whether or not you hire us.