Every SEO check findable runs, and how to fix each one

Contents
  1. What does the SEO family cover in findable?
  2. How do I fix the title and description checks?
  3. How do I fix the page setup checks?
  4. How do I fix the heading and content checks?
  5. How do I fix the link checks?
  6. How do I fix the image checks?
  7. How do I fix the canonical and social tag checks?
  8. How do I fix the security header checks?
  9. How do I fix the structured data and markup checks?
  10. Key takeaways

You ran an audit and got a list of ids like title_length and img_dimensions. This guide explains every one of them. Each check is a simple test on your HTML or response headers. Fix the failing ones and your score goes up.

What does the SEO family cover in findable?

SEO is 50% of your findable score, the biggest share. It has 98 checks covering metadata, structured data, performance and accessibility - the basics: metadata, page setup, headings, content size, links, images, social tags, security headers and markup. Each check has a fixed id, so you can search for it in any report.

Check idWhat it checksFix in one line
title_existsA title tag is presentAdd <title> in the head
title_lengthTitle is 30 to 60 charactersRewrite the title to fit
desc_existsA meta description is presentAdd <meta name="description">
desc_lengthDescription is 120 to 160 charactersTrim or expand it
viewportA viewport meta tag is presentAdd the viewport tag
charsetUTF-8 is declaredAdd <meta charset="utf-8">
lang_attr<html> has a lang attributeSet lang="en" or your language
html_doctype<!DOCTYPE html> is presentPut it on line one
meta_refreshNo meta refresh tagUse a server redirect instead
robots_metaNo noindex in the robots metaRemove noindex
h1_existsExactly one h1Keep one h1 per page
h2_existsAt least one h2Split content into sections
heading_hierarchyNo skipped heading levelsGo h1, h2, h3 in order
word_count300 or more wordsAdd useful body text
text_html_ratioText is at least 15% of the HTMLCut markup bloat
dom_sizeFewer than 1500 elementsSimplify the markup
internal_links2 or more internal linksLink to related pages
external_links1 or more external linkCite a source
empty_hrefsNo empty href valuesFix or remove the link
link_noopenertarget="_blank" links have rel="noopener"Add the rel attribute
img_altEvery image has alt textAdd alt to each img
img_dimensionsEvery image has width and heightAdd both attributes
canonicalA canonical link is presentAdd <link rel="canonical">
og_titleOpen Graph title is presentAdd og:title
og_descOpen Graph description is presentAdd og:description
og_imageOpen Graph image is presentAdd og:image
og_urlOpen Graph URL is presentAdd og:url
twitter_cardA twitter:card meta is presentAdd the card tag
httpsPage is served over HTTPSInstall a certificate
hstsStrict-Transport-Security header is setSend the header
x_content_typeX-Content-Type-Options: nosniff is setSend the header
x_frame_optionsX-Frame-Options header is setSend the header
cspContent-Security-Policy header is setSend a policy
jsonldAt least one JSON-LD blockAdd structured data
aria_landmarks<main> and <nav> are presentUse landmark elements
duplicate_idsNo duplicate id attributesMake each id unique
canonical_selfCanonical points to this pagePoint canonical at the page itself
canonical_absoluteCanonical is an absolute URLUse a full https URL
meta_robots_conflictRobots meta has no contradictory directivesDrop the conflicting index or follow token
robots_nofollowRobots meta does not nofollow every linkRemove nofollow or none
title_singleAt most one title tag in headKeep a single title
desc_singleAt most one meta descriptionKeep a single description
url_lengthPath and query of 100 characters or fewerShorten the URL
url_query_params2 or fewer query parametersUse clean paths over parameters
url_depth5 or fewer path levelsFlatten the URL structure
faviconA favicon linkAdd a rel=icon link
viewport_device_widthViewport uses width=device-width (N/A without a viewport)Set width=device-width
viewport_scalableViewport allows pinch zoom (N/A without a viewport)Remove user-scalable=no and low maximum-scale
lang_validThe html lang value is a valid tag (N/A without lang)Use a code like en or pt-BR
hreflang_validHreflang codes are valid (N/A without hreflang)Use language-region codes or x-default
hreflang_absoluteHreflang URLs are absolute (N/A without hreflang)Use full URLs
charset_earlyCharset declared in the first 1024 bytes (N/A without charset)Put the charset meta first in head
img_alt_qualityAlt text is not a filename or placeholder (N/A without images)Describe the image
img_alt_lengthAlt text of 125 characters or fewer (N/A without images)Shorten long alt text
img_lazy_loadingAt most 5 images load eagerly; lazy-load the rest (N/A without images)Add loading=lazy
img_modern_formatHalf or more images are WebP, AVIF or SVG (N/A without images)Convert to WebP or AVIF
nofollow_internalNo internal link marked nofollowRemove nofollow from your own links
generic_anchor_textNo "click here" style anchorsWrite descriptive link text
empty_anchor_textNo links without text, label or imageAdd text or an aria-label
javascript_hrefsNo javascript: hrefsUse real URLs
links_count200 or fewer linksTrim link-heavy navigation
mixed_contentNo http resources on an https page (N/A on http)Load everything over https
render_blocking_scriptsNo blocking scripts in headAdd defer or async
script_count20 or fewer external scriptsRemove or bundle scripts
stylesheet_count6 or fewer stylesheetsCombine stylesheets
inline_css_size20000 bytes or less of inline CSSMove large CSS to a file
resource_hintsThird-party resources have preconnect or preloadAdd rel=preconnect
html_weightHTML of 500000 bytes or lessCut inline data and markup
skip_linkA skip-to-content linkAdd a "Skip to content" link
button_namesEvery button has an accessible nameAdd button text or aria-label
table_headersAt least one th per tableUse th header cells
iframe_titleEvery iframe has a titleAdd a title attribute
color_contrastInline text and background colors reach WCAG AA contrast, 4.5:1 or 3:1 for h1-h3 (N/A without inline color pairs)Darken the text or lighten the background
jsonld_validAll JSON-LD blocks parse (N/A without JSON-LD)Fix the JSON syntax
jsonld_contextEvery JSON-LD root has a schema.org @contextAdd @context
schema_empty_valuesNo empty strings in structured dataFill or remove empty fields
schema_urls_absoluteurl, logo and image values are absoluteUse full http(s) URLs
org_nameOrganization has a name (N/A without Organization)Add name
org_logoOrganization has a logo (N/A without Organization)Add logo
org_urlOrganization has a url (N/A without Organization)Add url
website_name_urlWebSite has name and url (N/A without WebSite)Add both fields
searchaction_validSearchAction has a target template (N/A without it)Add a target with {search_term_string}
breadcrumb_validBreadcrumbList items are complete (N/A without it)Give each item a position and name
faq_validFAQPage questions have a name and answer textFill every question and answer
article_headlineArticle headline of 110 characters or fewerAdd a short headline
article_authorArticle names an authorAdd author with a name
article_datesArticle dates are valid ISO datesUse 2025-01-31 style dates
article_imageArticle has an imageAdd image
product_offersProduct has offers (N/A without Product)Add offers
product_priceProduct offer has a price and currency (N/A without Product)Add price and priceCurrency
product_ratingaggregateRating is complete (N/A without it)Add ratingValue and a count
localbusiness_addressLocalBusiness has an address (N/A without it)Add address
localbusiness_phoneLocalBusiness has a telephone (N/A without it)Add telephone
video_fieldsVideoObject has name, thumbnail and date (N/A without it)Fill the required fields
og_typeog:type is setAdd og:type
og_site_nameog:site_name is setAdd og:site_name
og_image_absoluteog:image is an absolute URLUse a full URL
og_url_matches_canonicalog:url matches canonicalMake both URLs the same

How do I fix the title and description checks?

Four checks cover this: title_exists, title_length, desc_exists and desc_length. The title must exist and be 30 to 60 characters. The description must exist and be 120 to 160 characters. Search engines use both to build your result snippet, so write them for people.

<title>Every SEO Check ID and How to Fix It</title>
<meta name="description" content="A plain guide to the SEO checks, with the fix for each one.">

The length ranges are common guidance, not a hard rule from Google. Google may rewrite your snippet anyway. See the SEO starter guide for what it says about titles and snippets.

How do I fix the page setup checks?

Six checks cover basic page setup: viewport, charset, lang_attr, html_doctype, meta_refresh and robots_meta. Most are one-line additions to the head. The last two are about things you must not have: a meta refresh and a noindex directive. html_doctype ignores leading whitespace but fails if a byte order mark comes before the doctype.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

If robots_meta fails, look for noindex in <meta name="robots">. It tells crawlers to skip the page. If meta_refresh fails, replace the tag with a 301 redirect on the server.

How do I fix the heading and content checks?

Six checks look at structure and size: h1_exists, h2_exists, heading_hierarchy, word_count, text_html_ratio and dom_size. Use one h1, then h2 sections, then h3 inside them. Never jump from h2 to h4. Write at least 300 words of real text. A page with two h1 tags fails h1_exists just like a page with none.

Be honest about three of these. word_count, text_html_ratio (15%) and dom_size (1500 elements) are heuristics. Google does not publish these cutoffs. A short page can still be great. Use them as a smell test for thin or bloated pages.

Four checks cover links: internal_links, external_links, empty_hrefs and link_noopener. You need at least 2 internal links and 1 external link. No link may have an empty href. Every target="_blank" link needs rel="noopener". A link to another host counts as external, so a link to your own subdomain is external too.

<a href="https://example.org/source" target="_blank" rel="noopener">Source</a>

The noopener value stops the new page from reaching your page through window.opener. rel="noreferrer" also passes the check, since it implies noopener. Read the MDN page on rel=noopener for details.

How do I fix the image checks?

Two checks cover images: img_alt and img_dimensions. Every image needs an alt attribute and explicit width and height. The alt check passes when the page has no images. The size attributes let the browser reserve space, so the layout does not jump.

<img src="/chart.png" alt="Bar chart of audit scores by family" width="800" height="450">

One catch: findable treats alt="" as missing, because the check trims whitespace and tests for empty. Decorative images with an empty alt are correct HTML, but they will still fail img_alt. Decide which matters more to you. Do not stuff keywords into alt text. Describe the image.

How do I fix the canonical and social tag checks?

Six checks cover sharing and duplicates: canonical, og_title, og_desc, og_image, og_url and twitter_card. The canonical link names the preferred URL. The Open Graph and Twitter tags control how your link looks when shared. See the Open Graph protocol. Each check only tests that the tag has a non-empty value, so a broken og:image URL still passes.

<link rel="canonical" href="https://example.com/page">
<meta property="og:title" content="Page title">
<meta property="og:description" content="Short summary.">
<meta property="og:image" content="https://example.com/card.png">
<meta property="og:url" content="https://example.com/page">
<meta name="twitter:card" content="summary_large_image">

How do I fix the security header checks?

Five checks look at transport and headers: https, hsts, x_content_type, x_frame_options and csp. They test your server response, not your HTML. A check passes when the header is present. It does not judge how strong the value is. If you audit a local file with findable ./page.html, there are no response headers, so expect these five to fail.

Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: default-src 'self'

Set these in your web server or CDN. Start the CSP in report-only mode so you do not break scripts. The MDN CSP guide explains the options.

How do I fix the structured data and markup checks?

Three checks cover markup: jsonld, aria_landmarks and duplicate_ids. Add at least one JSON-LD block, use both <main> and <nav>, and keep every id unique. Duplicate ids break anchors and scripts, and they confuse screen readers. The jsonld check drops any block that is not valid JSON, so one stray trailing comma makes it fail.

<script type="application/ld+json">
{"@context":"https://schema.org","@type":"Article","headline":"Every SEO check"}
</script>

Read Google's structured data intro to pick a type that fits your page.

Key takeaways

FAQ

How much of the findable score is SEO?
SEO is 50% of the score. AEO and GEO are 25% each. The SEO family has the most checks and covers metadata, headings, links, images, social tags, security headers and markup.
Do I need to pass every SEO check?
No. Some checks are rules of thumb, like word_count and dom_size. Treat them as prompts to look at the page, not as laws. Fix the failing basics first, then decide on the rest.
How do I see only SEO failures for my page?
Run findable on the URL and read the SEO family card. The issue list puts failing checks first, and each row shows the check id from this guide.
Can I run these checks in CI?
Yes. Use the -fail-under flag, for example findable -fail-under 80 https://example.com. The command exits with code 1 when the score is below your number.

How does findable score a page?

FamilyWeightQuestion it asks
SEO50%Can crawlers read and index this page?
AEO25%Is it easy to lift an answer from this page?
GEO25%Does the page give a generative model a reason to cite it?

The hosted audit waits up to 10 s for a page and fetches at most 5 MB. It reads robots.txt and llms.txt up to 512 KB each.

More guides

Every findable AEO Check ID and How to Fix It
All 35 AEO checks in findable explained, from aeo_faq to aeo_summary. See what each id tests, how loose the test is and how to fix it. AEO is 25% of the score.
Canonical Tags and Duplicate Content: How to Get Them Right
Use one canonical link per page that points to its own absolute URL. Learn the checks canonical, canonical_self and canonical_absolute and fix them.
FAQ Schema for Answer Engines: Markup and Checks
How to add FAQPage JSON-LD that answer engines can lift, and how findable tests aeo_faq, aeo_faq_count and faq_valid. Includes a working example.
Get Findable in 15 Minutes: A Step by Step Checklist
Install findable, audit a page and your site, fix the top failures, then add MCP, the web UI, the API and a CI gate. Every step has a copy-paste command.
Every findable GEO Check ID, Plus AI Crawler Checks
All 27 GEO checks in findable explained, plus the unscored Site checks for GPTBot, ClaudeBot and llms.txt. GEO is 25% of the score. Fixes included.
Image Alt Text, Dimensions and Lazy Loading Explained
Fix img_alt, img_dimensions, img_alt_quality, img_lazy_loading and img_modern_format. See what each image check in findable tests and how to pass.
JSON-LD Schema Basics: What findable Checks and Why
Learn what JSON-LD is, which schema.org types findable validates, and how to fix jsonld_valid, jsonld_context and empty or relative values.
llms.txt: What It Is and How findable Checks It
llms.txt is a plain Markdown file at your site root that points AI tools to your key pages. See the llms-txt check and how to write the file.
How to Write a Meta Description That Passes findable
Write a meta description of 120 to 160 characters, one per page, that matches the page. See the checks desc_exists, desc_length and desc_single.
Open Graph and Twitter Cards: Fix Your Share Previews
Add og:title, og:description, og:image, og:url and twitter:card so links unfurl well. See every social check findable runs and how to pass it.
robots.txt and AI Crawlers: GPTBot, ClaudeBot, PerplexityBot
How robots.txt rules decide whether GPTBot, ClaudeBot, PerplexityBot and Google-Extended can fetch your page, and how findable tests each one.
SEO vs AEO vs GEO: The Difference in Plain Words
SEO, AEO and GEO each target a different reader: a search crawler, an answer box, or a generative AI model. See what wins in each and how to check them.
Why AI Answer Engines Skip Your Site and How to Fix It
ChatGPT, Perplexity and Claude may ignore your pages for five fixable reasons, from robots.txt blocks to missing answers. Learn each cause and its check id.