Explore the audit evidence

Six local HTTP fixtures, not a scan of your website. Before and after responses are tested locally; Google indexing, traffic and ranking outcomes remain unknown.

The priority reflects the stated example intent, not a universal SEO score. A working response alone does not prove indexing.

A01 · Public launch page carries noindex

Priority: High

Observation
GET /launch returns 200 and a robots meta noindex. The stated intent is a public page eligible for search.
Why it matters
The directive contradicts that intent. Its presence is confirmed; Google having seen it is not.
Proposed action
Remove the unintended directive from the public template. Check response headers and rendered HTML as well as source HTML.
Owner
Web developer
Acceptance check
The replacement /fixed/launch returns 200 without noindex. Recheck the real deployment and use authorized URL Inspection separately.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /launch
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><meta name="robots" content="noindex"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

After

GET /fixed/launch
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/fixed/launch"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

A02 · Robots prevents reading the exclusion directive

Priority: High

Observation
robots.txt disallows /blocked/, while /blocked/page contains noindex. The stated intent is exclusion from search, not access restriction.
Why it matters
A compliant crawler cannot read the page directive at that path. Robots rules are not authentication.
Proposed action
Allow crawling of the intended excluded page while retaining noindex. Use authentication for genuinely private content.
Owner
Platform owner
Acceptance check
/fixed/blocked/page is outside the blocked prefix and still returns noindex. Validate the actual host rules and later indexing observations independently.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /robots.txt
HTTP 200
Content-Type: text/plain; charset=utf-8

User-agent: *
Disallow: /blocked/


────────

GET /blocked/page
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><meta name="robots" content="noindex"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

After

GET /robots.txt
HTTP 200
Content-Type: text/plain; charset=utf-8

User-agent: *
Disallow: /blocked/


────────

GET /fixed/blocked/page
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><meta name="robots" content="noindex"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

A03 · Permanent redirect ends in an error

Priority: High

Observation
/old-guide returns 301 to /missing-guide, which returns 404. The example assumes /guide is a relevant replacement.
Why it matters
The path fails to deliver the intended content. A redirect status does not prove a successful destination.
Proposed action
Point the moved URL directly to the relevant working replacement and update internal links. Do not redirect every removed page to the homepage.
Owner
Routing developer
Acceptance check
/fixed/old-guide returns one 301 followed by /guide with 200 and the expected content. Inspect the entire chain after deployment.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /old-guide
HTTP 301
Location: /missing-guide



────────

GET /missing-guide
HTTP 404
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title></head><body><h1>Not found</h1></body></html>

After

GET /fixed/old-guide
HTTP 301
Location: /guide



────────

GET /guide
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/guide"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

A04 · Canonical points at unrelated content

Priority: Medium

Observation
/variant declares /other-topic as canonical, although its content duplicates /guide.
Why it matters
The declared preference conflicts with the example content relationship. This does not reveal Google’s selected canonical.
Proposed action
Confirm equivalence, then align the canonical, internal links and sitemap with /guide. Retain distinct pages when their content serves different needs.
Owner
SEO lead and developer
Acceptance check
/fixed/variant declares /guide and that destination responds successfully. Check the Google-selected canonical separately when access is available.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /variant
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/other-topic"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

After

GET /fixed/variant
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/guide"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

A05 · Missing page uses a success response

Priority: Medium

Observation
/gone returns 200 with a Not found heading. There is no suitable replacement in this example.
Why it matters
This is an error-content/success-status mismatch and a soft-404 candidate, not an observed Google classification.
Proposed action
Return the appropriate missing-resource status and remove stale internal links. Keep a useful error page for visitors.
Owner
Web developer
Acceptance check
/fixed/gone returns 404 with the error content. A later Search Console observation is separate evidence, not part of this local test.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /gone
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title></head><body><h1>Not found</h1></body></html>

After

GET /fixed/gone
HTTP 404
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title></head><body><h1>Not found</h1></body></html>

A06 · Working control needs no speculative fix

Priority: No change

Observation
/guide returns 200, declares itself canonical and is not blocked by these robots rules. No noindex is present in this response.
Why it matters
These checks pass for this fixture. They do not prove content quality, rendered behavior, discovery, indexing or rankings.
Proposed action
Record a passing control. Investigate other signals only when the question and evidence justify it.
Owner
Audit reviewer
Acceptance check
The before and after responses remain identical. Preserve the passing evidence instead of manufacturing an issue to increase the issue count.

Confirmed in this local fixture; production scope and search outcomes are unverified.

Before

GET /guide
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/guide"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

After

GET /guide
HTTP 200
Content-Type: text/html; charset=utf-8

<!doctype html><html lang="en"><head><title>Local audit fixture</title><link rel="canonical" href="/guide"></head><body><h1>Guide</h1><p>Local practice content.</p></body></html>

Run the fixtures

Run the fixtures

Six local HTTP fixtures, not a scan of your website. Before and after responses are tested locally; Google indexing, traffic and ranking outcomes remain unknown.

Python 3.10 or newer. Extract the ZIP to a local folder. The verification command starts a temporary loopback server, tests every case, prints JSON and stops. It does not contact external websites.

python3 audit_lab.py --verify

For manual inspection, start the server with the command below, open the local URLs, then stop it with Ctrl+C. Use another local port if 8765 is occupied.

python3 audit_lab.py --port 8765

http://127.0.0.1:8765/robots.txt

http://127.0.0.1:8765/launch

http://127.0.0.1:8765/fixed/launch

http://127.0.0.1:8765/blocked/page

http://127.0.0.1:8765/fixed/blocked/page

http://127.0.0.1:8765/old-guide

http://127.0.0.1:8765/missing-guide

http://127.0.0.1:8765/fixed/old-guide

http://127.0.0.1:8765/guide

http://127.0.0.1:8765/variant

http://127.0.0.1:8765/fixed/variant

http://127.0.0.1:8765/gone

http://127.0.0.1:8765/fixed/gone

http://127.0.0.1:8765/guide

http://127.0.0.1:8765/guide

Commands and paths are technical identifiers; report text is translated.

Search indexing outcome: unknown

Search indexing outcome: unknown