Landing Page Audit Tool: 14-Point Technical Checklist (2026)
Use a landing page audit tool to catch the speed, SEO, form and tracking bugs that kill conversions. 14-point checklist, real data from 6 pages, free script.
A landing page audit tool checks whether a page can be found, loads fast enough to keep the visitor, works on a phone, and records the conversion correctly. In practice that means testing indexability, title and meta tags, Core Web Vitals, render-blocking scripts, image dimensions, form labels, structured data and tracking consent, then ranking the fixes by impact.
Most landing page "analyzers" focus on persuasion: headline clarity, social proof, CTA wording. Those matter. But a brilliant headline on a page that takes 5 seconds to paint on mobile, or a form whose fields a screen reader cannot announce, still loses the conversion.
This guide focuses on the technical half that copy tools skip. It includes a 14-point checklist, results from running it on six real SaaS homepages, a free Python script to run it yourself, and a framework for picking the best landing page audit tool for your team.
What a Landing Page Audit Should Cover
A complete landing page audit covers four layers: discoverability (can search engines and AI crawlers index it), speed (does it pass Core Web Vitals on mobile), usability (do forms and controls work for everyone), and measurement (do your tags fire correctly, and only after consent).
Copy and design review sits on top of these four layers. Fix the foundations first, because no headline test produces valid results on a page that is half-broken for part of your traffic.
| Layer | What breaks | Measurable symptom |
|---|---|---|
| Discoverability | noindex left over from staging, missing canonical, duplicate H1 | Page never ranks or ranks for the wrong query |
| Speed | Hero image too large, render-blocking scripts, heavy HTML | LCP above 2.5 s, INP above 200 ms |
| Stability | Images and embeds without reserved space | CLS above 0.1, mis-clicked CTAs |
| Usability | Unlabeled form fields, tiny tap targets | Form abandonment, accessibility complaints |
| Measurement | Tags firing before consent, duplicate conversion events | Inflated or legally risky conversion data |
The 14-Point Technical Landing Page Checklist
The checks below are ordered by tier. P0 items block ranking or conversion outright. P1 items cost you a measurable share of visitors. P2 items are polish that compounds over time.
| # | Check | Tier | Pass condition |
|---|---|---|---|
| 1 | HTTP status | P0 | Final URL returns 200 |
| 2 | Indexable | P0 | No noindex in meta robots or X-Robots-Tag |
| 3 | Canonical tag | P0 | Present and pointing at itself |
| 4 | Mobile viewport | P0 | <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 5 | Title length | P1 | Roughly 30โ60 characters, primary keyword near the start |
| 6 | Meta description | P1 | Roughly 70โ160 characters, states the offer |
| 7 | Exactly one H1 | P1 | One H1 that matches the ad or search intent |
| 8 | No render-blocking head scripts | P1 | Every <head> script uses async, defer or type="module" |
| 9 | Images have dimensions | P1 | width and height set, so CLS stays โค 0.1 |
| 10 | Form fields labeled | P1 | Each field has a <label>, aria-label or aria-labelledby |
| 11 | HTML weight | P1 | Initial HTML under ~500 KB |
| 12 | Third-party script hosts | P2 | Five or fewer, each one justified |
| 13 | Social preview image | P2 | og:image set, so shared links render a card |
| 14 | Structured data | P2 | Valid JSON-LD (Organization, Product, SoftwareApplication or FAQPage) |
Points 5 and 6 are guidelines rather than hard limits. Google truncates title links and snippets by pixel width and sometimes rewrites them. Our guides to writing title tags and meta descriptions cover the details.
Real Data: 6 SaaS Landing Pages Audited
We ran the script from the next section against six public SaaS homepages on 1 October 2026: our own (bugviso.com) and five well-known SaaS brands, anonymised as Sites A to E. All are professionally built pages from well-funded teams.
| Page | Score | Failed checks |
|---|---|---|
| bugviso.com | 13/14 | Two H1 tags (second one inside a <noscript> fallback) |
| Site A | 13/14 | No JSON-LD structured data |
| Site B | 11/14 | Two H1 tags; 1 of 35 images missing dimensions; 642 KB HTML |
| Site C | 11/14 | 66-character title; 27 of 56 images missing dimensions; 869 KB HTML |
| Site D | 10/14 | 74-character title; 1 render-blocking head script; 1 of 91 images missing dimensions; 628 KB HTML |
| Site E | 9/14 | 64-character meta description; no JSON-LD; 3 of 38 images missing dimensions; 1 of 2 form fields unlabeled; 1,256 KB HTML |
Three patterns stand out:
- Heavy HTML is the most common failure. Four of six pages shipped more than 500 KB of HTML, usually from inlined framework data or SVG. Every byte delays the first paint on a slow mobile connection.
- Missing image dimensions are everywhere. Four of six pages had at least one image without
widthandheight. Site C was missing them on nearly half its images. - Nobody is perfect, including us. Our own homepage failed on a duplicate H1. A generic
<h1>inside the<noscript>fallback appeared on every prerendered page of the site. Non-JavaScript crawlers, which include most AI crawlers, saw two competing headings. We changed it to a paragraph the same day.
๐ก Method note: This is a raw-HTML check, so it sees exactly what a non-JavaScript crawler sees. Elements injected later by JavaScript are not counted. Scores reflect the pages on the test date and will drift as those sites ship changes.
We found two false positives while building the script, and both are fixed in the version below. Site D's form fields were first reported as unlabeled because the inputs sat inside <label> elements, which is a valid implicit label. If a tool cannot tell the difference, its accessibility findings are not trustworthy.
Run a Landing Page Audit in Python (Free Script)
This script needs only httpx and the Python standard library. It fetches the page once and evaluates all 14 checks against the raw HTML, the way a non-JavaScript crawler sees it.
"""
lp_audit.py โ technical landing page audit from raw HTML (no browser needed).
Checks the on-page signals that decide whether a landing page can rank,
render fast and convert: title/meta length, canonical, indexability,
H1, viewport, social preview tags, JSON-LD, render-blocking scripts,
third-party script hosts, image dimensions, and unlabeled form fields.
Usage:
pip install httpx
python3 lp_audit.py https://example.com/landing-page
"""
import sys
import time
from html.parser import HTMLParser
from urllib.parse import urlparse
import httpx
class LandingPageParser(HTMLParser):
def __init__(self):
super().__init__()
self.in_head, self.in_title = True, False
self.title, self.meta, self.links = "", {}, {}
self.h1 = 0
self.blocking_scripts, self.script_hosts = 0, set()
self.imgs, self.imgs_no_size = 0, 0
self.inputs, self.labels_for, self.input_ids = 0, set(), []
self.labeled, self.jsonld, self.label_depth = 0, 0, 0
def handle_starttag(self, tag, attrs):
a = {k: (v or "") for k, v in attrs}
if tag == "body":
self.in_head = False
elif tag == "title":
self.in_title = True
elif tag == "meta":
key = a.get("name") or a.get("property")
if key:
self.meta[key.lower()] = a.get("content", "")
elif tag == "link" and a.get("rel"):
self.links[a["rel"].lower()] = a.get("href", "")
elif tag == "h1":
self.h1 += 1
elif tag == "script":
if a.get("type") == "application/ld+json":
self.jsonld += 1
elif a.get("src"):
self.script_hosts.add(urlparse(a["src"]).netloc)
if self.in_head and "async" not in a and "defer" not in a \
and a.get("type") != "module":
self.blocking_scripts += 1
elif tag == "img":
self.imgs += 1
if not (a.get("width") and a.get("height")):
self.imgs_no_size += 1
elif tag == "label":
self.label_depth += 1 # <label><input></label> is labeled implicitly
if a.get("for"):
self.labels_for.add(a["for"])
elif tag in ("input", "select", "textarea") and \
a.get("type") not in ("hidden", "submit", "button"):
self.inputs += 1
if a.get("aria-label") or a.get("aria-labelledby") or self.label_depth:
self.labeled += 1
else:
self.input_ids.append(a.get("id", ""))
def handle_endtag(self, tag):
if tag == "title":
self.in_title = False
elif tag == "label" and self.label_depth:
self.label_depth -= 1
def handle_data(self, data):
if self.in_title:
self.title += data
def audit(url: str) -> None:
headers = {"User-Agent": "Mozilla/5.0 (landing-page-audit script)"}
start = time.perf_counter()
r = httpx.get(url, headers=headers, follow_redirects=True, timeout=20)
elapsed_ms = (time.perf_counter() - start) * 1000
p = LandingPageParser()
p.feed(r.text)
own_host = urlparse(str(r.url)).netloc
third_party = {h for h in p.script_hosts if h and not h.endswith(own_host.removeprefix("www."))}
unlabeled = sum(1 for i in p.input_ids if not i or i not in p.labels_for)
robots = p.meta.get("robots", "") + " " + r.headers.get("x-robots-tag", "")
title, desc = p.title.strip(), p.meta.get("description", "")
checks = [
("HTTP status 200", r.status_code == 200, r.status_code),
("Indexable (no noindex)", "noindex" not in robots.lower(), robots.strip() or "none"),
("Title 30-60 chars", 30 <= len(title) <= 60, len(title)),
("Meta description 70-160 chars", 70 <= len(desc) <= 160, len(desc)),
("Canonical tag present", bool(p.links.get("canonical")), p.links.get("canonical", "missing")),
("Exactly one H1", p.h1 == 1, p.h1),
("Mobile viewport meta", "viewport" in p.meta, p.meta.get("viewport", "missing")),
("og:image for link previews", "og:image" in p.meta, "set" if "og:image" in p.meta else "missing"),
("JSON-LD structured data", p.jsonld > 0, p.jsonld),
("No render-blocking head scripts", p.blocking_scripts == 0, p.blocking_scripts),
("Third-party script hosts <= 5", len(third_party) <= 5, len(third_party)),
("Images have width+height", p.imgs_no_size == 0, f"{p.imgs_no_size}/{p.imgs} missing"),
("Form fields labeled", unlabeled == 0, f"{unlabeled}/{p.inputs} unlabeled"),
("HTML size < 500 KB", len(r.content) < 500_000, f"{len(r.content) // 1024} KB"),
]
passed = sum(ok for _, ok, _ in checks)
print(f"Landing page audit: {r.url} ({elapsed_ms:.0f} ms)\n")
for name, ok, detail in checks:
print(f" {'PASS' if ok else 'FAIL'} {name:34} {detail}")
print(f"\n Score: {passed}/{len(checks)}")
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.exit("Usage: python3 lp_audit.py <URL>")
audit(sys.argv[1])Here is the real output for our own homepage on the test date, including the duplicate H1 it caught:
Landing page audit: https://bugviso.com (220 ms)
PASS HTTP status 200 200
PASS Indexable (no noindex) index, follow, max-image-preview:large, max-snippet:-1
PASS Title 30-60 chars 51
PASS Meta description 70-160 chars 142
PASS Canonical tag present https://bugviso.com/
FAIL Exactly one H1 2
PASS Mobile viewport meta width=device-width, initial-scale=1.0
PASS og:image for link previews set
PASS JSON-LD structured data 1
PASS No render-blocking head scripts 0
PASS Third-party script hosts <= 5 0
PASS Images have width+height 0/1 missing
PASS Form fields labeled 0/1 unlabeled
PASS HTML size < 500 KB 127 KB
Score: 13/14The script is deliberately limited. It cannot measure real LCP, INP or CLS, because those need a browser. It also cannot see tags that fire before consent. The next section covers those checks.
The Checks That Need a Real Browser
Raw HTML tells you what a crawler sees. It cannot tell you what a visitor on a mid-range phone experiences. Four landing page checks need a real browser engine.
Core Web Vitals Under Mobile Conditions
Google's Core Web Vitals thresholds are LCP โค 2.5 s, INP โค 200 ms and CLS โค 0.1, measured at the 75th percentile of real visits. Paid traffic skews mobile, so test under throttled network and CPU conditions, not on office Wi-Fi. Paste this into the DevTools console to see the LCP element and its timing:
// Logs each LCP candidate; the last one logged is the final LCP element
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('LCP', Math.round(entry.startTime), 'ms', entry.element)
}
}).observe({ type: 'largest-contentful-paint', buffered: true })If the LCP element is the hero image, see how to identify the LCP element in Chrome DevTools. If the cause is a blocking script, the fix is usually in finding and fixing render-blocking resources.
Render-Blocking Scripts: Before and After
<!-- โ Broken: parser stops until the chat widget downloads and executes -->
<head>
<script src="https://widget.example-chat.com/loader.js"></script>
</head><!-- โ
Fixed: downloads in parallel, runs after the document is parsed -->
<head>
<script src="https://widget.example-chat.com/loader.js" defer></script>
</head>Accessible Form Fields
A landing page's form is its conversion point. Placeholder text is not a label: it disappears on input and many screen readers do not announce it reliably. Follow the W3C's form labels tutorial.
<!-- โ Broken: no programmatic label -->
<input type="email" placeholder="Work email">
<!-- โ
Fixed: explicit label (can be visually styled or hidden) -->
<label for="email">Work email</label>
<input id="email" type="email" autocomplete="email">Tracking Before Consent
Ad landing pages carry the heaviest tag load on most sites. If a marketing pixel sets cookies before the visitor accepts, you have a compliance problem in the EU and parts of the US, and conversion data you may not be allowed to use. The GDPR website compliance checklist covers what to verify.
What Is the Best Landing Page Audit Tool?
The best landing page audit tool depends on which layer you need to test. No single tool judges technical health, persuasion and real-user behaviour equally well, so most teams combine two or three.
| Tool category | Best at | Blind spot | Example |
|---|---|---|---|
| Full technical audit | Speed, SEO, accessibility, security, tracking consent, ranked fixes | Cannot judge copy persuasiveness | BugViso |
| Speed lab + field data | Core Web Vitals from real Chrome users (CrUX) | No SEO, forms or consent checks | Google PageSpeed Insights |
| Accessibility extension | Deep WCAG inspection of one page in DevTools | Manual, one page at a time | axe DevTools |
| AI copy / CRO analyzer | Headline clarity, CTA wording, trust signals | Often no measured performance or accessibility data | Various |
| Behaviour analytics | Heatmaps and session recordings of real visitors | Needs traffic; shows symptoms, not causes | Microsoft Clarity |
Decision framework:
- Launching a new page: run a full technical audit first, then a copy review. Fix P0 and P1 items before you spend on traffic.
- Paid traffic converting poorly: check mobile Core Web Vitals and form usability before rewriting copy.
- Agency client handoff: use a tool that produces a branded, prioritised report the client can read.
- Page already fast and accessible: this is where copy analyzers and A/B tests earn their keep.
For a broader comparison beyond landing pages, see our best website audit tools in 2026 roundup.
How BugViso Audits a Landing Page Automatically
BugViso runs every check in this guide in one scan, in a real headless Chromium browser, so JavaScript-rendered content is tested the way visitors and Googlebot see it.
For a landing page, the relevant engines are:
- Performance & Core Web Vitals: LCP, CLS, INP, FCP and TTFB via the
web-vitalslibrary, a mobile device-emulation pass, and re-loads under Slow 3G and Fast 3G throttling to show how much LCP regresses on a weak connection. - Code coverage and long tasks: the percentage of unused JavaScript and CSS shipped, and the script responsible for the worst main-thread blocking.
- On-Page Keyword Intelligence: derives the page's apparent primary keyword and scores its alignment across title, H1, meta description, URL slug and first paragraph. This is how you catch an ad landing page whose H1 does not match the ad.
- Advanced SEO Intelligence: JSON-LD validation, including pricing sections that lack matching commerce schema, plus canonical checks and image
alt/dimension audits. - Accessibility: a WCAG 2.1 A/AA axe-core audit with violations grouped by impact.
- Privacy & Compliance: every cookie and third-party host seen on the un-consented page load, flagging trackers that fire before consent.
Findings are ranked in a prioritised playbook. The branded PDF includes AI-written rewrites of your title, meta description and H1, plus code fixes for your exact markup. See the Core Web Vitals and speed feature page for the full list of performance checks.
High-Risk Landing Page Oversights
A staging noindex that ships to production. It is the single most expensive one-line bug in SEO. Check the X-Robots-Tag header too, not just the meta tag.
A duplicate canonical from a page builder. Some builders inject their own canonical tag. Two canonicals pointing at different URLs means Google may ignore both.
A/B testing scripts that cause flicker. Client-side testing tools often hide the page until the variant loads, which delays LCP and can cause layout shift. Measure performance with the test running, not just the control page.
A thank-you page that is indexable. If your conversion confirmation page can be found in search, your conversion counts are polluted. Mark it noindex.
UTM parameters creating duplicate URLs. Make sure the canonical tag strips campaign parameters, or every ad variant becomes its own indexable URL.
Frequently Asked Questions
What does a landing page audit tool check?
A landing page audit tool checks indexability, title and meta tags, Core Web Vitals, render-blocking resources, image dimensions, mobile usability, form accessibility, structured data and tracking consent. Copy-focused tools add headline and CTA analysis. A complete audit ranks every finding by its likely impact on traffic and conversions.
What is the best free landing page audit tool?
For a free technical check, combine Google PageSpeed Insights (Core Web Vitals field data) with the Python script in this guide (on-page SEO and HTML checks). For one report covering speed, SEO, accessibility and tracking consent, a free BugViso scan includes one full PDF report.
How is a landing page audit different from a full website audit?
A landing page audit goes deep on one page and its conversion path: speed, form usability, message match and tracking. A full website audit adds site-wide checks such as crawl depth, internal linking, duplicate content and broken links across hundreds of pages.
How often should I audit my landing pages?
Audit every landing page before launch, after any template or tag manager change, and monthly while it receives paid traffic. Third-party scripts change without warning, and a single new tag can push mobile LCP past 2.5 seconds.
Can a landing page audit tool improve conversion rates?
Indirectly, yes. Technical audits remove friction such as slow loads, layout shifts that cause mis-taps, and unusable form fields. These lift conversion for the share of visitors who were hitting them. Persuasion improvements still need copy testing.
Conclusion
Most landing pages that underperform are not short of clever copy: they are slow on mobile, heavy in HTML, missing image dimensions, or firing tags before consent. Fix the technical layer first. A free BugViso scan checks all 14 points, plus the browser-level ones, on your landing page in about two minutes.
See where your site stands
Run a free BugViso audit for SEO, speed, accessibility and AI search readiness โ with fixes you can ship today.