Skip to main content
Engineering/technical-seo-audit

Technical SEO Audit

You need to evaluate site crawlability, speed, and indexation health.

You need to assess a website's technical SEO health. Produces a comprehensive checklist covering crawlability, site speed (Core Web Vitals), schema markup, mobile-friendliness, indexation, redirect chains, and security. Works for initial audits, pre-launch reviews, or diagnosing organic traffic drops.


How it works

  1. You provide the site URL and any known issues or symptoms (e.g., traffic drop, pages not indexing)
  2. The skill walks through each technical SEO category with specific checks, flags issues, and prioritizes fixes by impact
  3. Use the output as a remediation roadmap for developers or hand it to a technical SEO specialist for validation

Related skills: Feeds keyword context from /seo-keyword-discovery. Informs content optimization via /content-seo-brief.


Prompt

You are conducting a technical SEO audit. Your job is to produce a structured, prioritized checklist that a developer or site owner can act on. Be specific about what to check, what "good" looks like, and what the fix is when something is wrong.

Inputs I will provide:

  • Site URL: {{SITE_URL}} (e.g., "https://example.com")
  • Known issues (optional): {{KNOWN_ISSUES}} (e.g., "Pages dropped from index last month" or "Core Web Vitals failing on mobile")
  • CMS/platform (optional): {{PLATFORM}} (e.g., "WordPress with Yoast" or "Next.js on Vercel." Helps tailor recommendations.)
  • Priority pages (optional): {{PRIORITY_PAGES}} (e.g., "Homepage, /pricing, /blog/* -- these drive 80% of traffic")

Step 1: Crawlability and indexation

Check whether search engines can discover, crawl, and index the site's important pages.

### Crawlability and Indexation

**robots.txt**
- [ ] robots.txt exists and is accessible at {{SITE_URL}}/robots.txt
- [ ] No critical pages or directories are accidentally blocked
- [ ] Sitemap URL is declared in robots.txt
- [ ] Crawl-delay directive reviewed (if present)
- Finding: {{what was found}}
- Issue: {{specific problem, or "No issues"}}
- Fix: {{specific remediation}}

**XML Sitemap**
- [ ] Sitemap exists and is accessible (typically /sitemap.xml or /sitemap_index.xml)
- [ ] Sitemap is submitted to Google Search Console
- [ ] All important pages are included
- [ ] No 404, 301, or noindex pages in the sitemap
- [ ] Sitemap is under 50MB / 50,000 URLs per file
- [ ] Last modified dates are accurate (not all the same date)
- Finding: {{what was found}}
- Issue: {{specific problem, or "No issues"}}
- Fix: {{specific remediation}}

**Indexation Status**
- [ ] site: search shows expected number of indexed pages
- [ ] No unexpected pages indexed (staging, test, duplicate)
- [ ] No important pages missing from index
- [ ] Canonical tags are present and self-referencing (or pointing correctly)
- [ ] No conflicting noindex directives (meta tag vs. header vs. robots.txt)
- [ ] Pagination handled correctly (rel=next/prev or load-more patterns)
- Indexed pages: {{count or "check via Search Console"}}
- Issue: {{specific problem, or "No issues"}}
- Fix: {{specific remediation}}

**Crawl Budget (for larger sites, 10,000+ pages)**
- [ ] Faceted navigation not generating infinite crawl paths
- [ ] URL parameters handled (Search Console parameter tool or canonical tags)
- [ ] Internal search result pages blocked from crawling
- [ ] Thin or duplicate content not consuming crawl budget
- Issue: {{specific problem, or "Not applicable for site size"}}

Step 2: Site speed and Core Web Vitals

Assess loading performance using the three Core Web Vitals metrics plus supplementary speed indicators.

### Site Speed and Core Web Vitals

**Largest Contentful Paint (LCP) -- target: under 2.5 seconds**
- [ ] Measure LCP on mobile and desktop (PageSpeed Insights or CrUX data)
- [ ] Identify the LCP element (hero image, heading text, video)
- [ ] Check image optimization: format (WebP/AVIF), compression, sizing
- [ ] Check server response time (TTFB under 800ms)
- [ ] Check render-blocking resources (CSS, JS in critical path)
- Mobile LCP: {{value or "measure needed"}}
- Desktop LCP: {{value or "measure needed"}}
- Issue: {{specific bottleneck, or "Passing"}}
- Fix: {{specific remediation with expected impact}}

**First Input Delay (FID) / Interaction to Next Paint (INP) -- target: under 200ms**
- [ ] Measure INP (replaced FID as Core Web Vital in March 2024)
- [ ] Identify heavy JavaScript execution blocking main thread
- [ ] Check third-party script impact (analytics, chat widgets, ads)
- [ ] Review event handler responsiveness
- INP: {{value or "measure needed"}}
- Issue: {{specific bottleneck, or "Passing"}}
- Fix: {{specific remediation}}

**Cumulative Layout Shift (CLS) -- target: under 0.1**
- [ ] Measure CLS on key page templates
- [ ] Check for images/videos without explicit dimensions
- [ ] Check for dynamically injected content (ads, banners, cookie notices)
- [ ] Check for web fonts causing layout shift (font-display strategy)
- CLS: {{value or "measure needed"}}
- Issue: {{specific cause, or "Passing"}}
- Fix: {{specific remediation}}

**Supplementary Speed Checks**
- [ ] Total page weight: {{size}} (target: under 3MB for most pages)
- [ ] Number of HTTP requests: {{count}} (target: minimize)
- [ ] Browser caching headers configured (Cache-Control, ETag)
- [ ] Gzip/Brotli compression enabled
- [ ] CDN in use for static assets
- [ ] Critical CSS inlined, non-critical CSS deferred

Step 3: Schema markup review

Evaluate structured data implementation for search result enrichment.

### Schema Markup (JSON-LD)

**Implementation Check**
- [ ] Schema markup present on key page types
- [ ] Using JSON-LD format (preferred by Google)
- [ ] Validates without errors in Google Rich Results Test
- [ ] Validates without errors in Schema.org validator

**Page-Type Coverage**
| Page Type | Recommended Schema | Implemented? | Valid? | Notes |
|-----------|-------------------|-------------|--------|-------|
| Homepage | Organization, WebSite | {{yes/no}} | {{yes/no/errors}} | {{notes}} |
| Blog posts | Article, BlogPosting | {{yes/no}} | {{yes/no/errors}} | {{notes}} |
| Product pages | Product, Offer | {{yes/no}} | {{yes/no/errors}} | {{notes}} |
| Service pages | Service, LocalBusiness | {{yes/no}} | {{yes/no/errors}} | {{notes}} |
| FAQ pages | FAQPage | {{yes/no}} | {{yes/no/errors}} | {{notes}} |
| Contact page | LocalBusiness, ContactPoint | {{yes/no}} | {{yes/no/errors}} | {{notes}} |

**Missing Opportunities**
- {{schema type that could be added for SERP enrichment}}
- {{schema type that competitors use but this site does not}}

**Common Errors Found**
- {{error description, or "No errors"}}
- Fix: {{specific remediation}}

Step 4: Mobile-friendliness

### Mobile-Friendliness

- [ ] Site uses responsive design (not separate mobile URLs or dynamic serving)
- [ ] Viewport meta tag configured correctly
- [ ] Text readable without zooming (16px+ base font)
- [ ] Tap targets adequately sized and spaced (48px+ with 8px+ spacing)
- [ ] No horizontal scrolling on mobile viewports
- [ ] Mobile navigation is accessible and functional
- [ ] Forms are usable on mobile (input types, autocomplete attributes)
- [ ] Pop-ups and interstitials comply with Google's guidelines (no intrusive interstitials)
- [ ] Mobile page speed passes Core Web Vitals (see Step 2)
- Issue: {{specific problem, or "No issues"}}
- Fix: {{specific remediation}}

Step 5: Redirect chain audit

### Redirects

**Redirect Chains**
- [ ] No redirect chains longer than 2 hops (ideal: 1 hop)
- [ ] Redirect chains identified and shortened to direct 301s
- Chain count: {{number found or "audit needed with Screaming Frog / Ahrefs"}}
- Worst chain: {{example chain, or "None"}}

**Redirect Audit**
- [ ] All redirects use 301 (permanent) unless temporarily moved
- [ ] No redirect loops detected
- [ ] Old URLs from site migrations still redirect correctly
- [ ] HTTP to HTTPS redirect in place (single hop)
- [ ] www to non-www (or vice versa) redirect in place (single hop)
- [ ] Trailing slash behavior is consistent

**Orphan Pages**
- [ ] All important pages are reachable through internal links (not just sitemap)
- [ ] No important pages require 4+ clicks from homepage
- Orphan pages found: {{count or "audit needed"}}

Step 6: Security

### Security (HTTPS and Mixed Content)

- [ ] Site loads on HTTPS by default
- [ ] Valid SSL/TLS certificate (not expired, correct domain)
- [ ] HTTP requests redirect to HTTPS (301, single hop)
- [ ] No mixed content warnings (HTTP resources loaded on HTTPS pages)
- [ ] HSTS header configured (Strict-Transport-Security)
- [ ] Security headers present: X-Content-Type-Options, X-Frame-Options, Content-Security-Policy
- Mixed content issues: {{count and examples, or "None"}}
- Certificate expiry: {{date}}
- Fix: {{specific remediation, or "No issues"}}

Step 7: Priority remediation plan

Rank all issues found by impact and effort.

### Priority Remediation Plan

| Priority | Issue | Category | Impact | Effort | Recommended Fix |
|----------|-------|----------|--------|--------|----------------|
| P0 (critical) | {{issue}} | {{category}} | {{high/medium/low}} | {{hours/days estimate}} | {{specific fix}} |
| P1 (high) | {{issue}} | {{category}} | {{impact}} | {{effort}} | {{fix}} |
| P2 (medium) | {{issue}} | {{category}} | {{impact}} | {{effort}} | {{fix}} |
| P3 (low) | {{issue}} | {{category}} | {{impact}} | {{effort}} | {{fix}} |

**Quick wins (high impact, low effort):**
1. {{fix}}
2. {{fix}}

**Monitoring plan:**
- Re-audit Core Web Vitals: {{frequency, e.g., monthly}}
- Check indexation status: {{frequency}}
- Review Search Console for new crawl errors: {{frequency}}

Example Output

Input

  • Site URL: https://www.harborwellness.com
  • Known issues: "Organic traffic dropped ~35% over the past 6 weeks; several blog posts and service pages appear to have fallen out of the index"
  • CMS/platform: WordPress with Rank Math SEO plugin, hosted on WP Engine
  • Priority pages: Homepage, /services/iv-therapy, /services/weight-loss, /blog/*, /book-appointment

Output

Technical SEO Audit — harborwellness.com

Audit Date: June 2025 Platform: WordPress / Rank Math / WP Engine Trigger: ~35% organic traffic decline over 6 weeks; suspected deindexation of blog and service pages


Crawlability and Indexation

robots.txt

  • robots.txt exists at https://www.harborwellness.com/robots.txt
  • [✗] /wp-admin/ correctly blocked, but /services/ directory is disallowed — critical blocker
  • Sitemap declared: Sitemap: https://www.harborwellness.com/sitemap_index.xml
  • Crawl-delay directive not present (acceptable)
  • Finding: A Disallow: /services/ rule was added — likely during a staging migration 6 weeks ago. Matches the timing of the traffic drop exactly.
  • Issue: Googlebot cannot crawl any /services/* pages. All service pages have effectively been removed from crawlable scope.
  • Fix: Remove Disallow: /services/ from robots.txt immediately. Submit updated file to Google Search Console and request recrawl of /services/iv-therapy and /services/weight-loss via URL Inspection tool.

XML Sitemap

  • Sitemap index accessible at /sitemap_index.xml with three child sitemaps (pages, posts, services)
  • [✗] 14 blog posts in post-sitemap.xml return 301 redirects (not their canonical final URLs)
  • [✗] 3 pages in sitemap carry a noindex meta tag — including /book-appointment
  • Sitemap submitted in Search Console
  • Under 50,000 URLs (site has ~380 indexed pages)
  • Issue: 301 URLs in sitemap dilute crawl efficiency; noindex on /book-appointment is a conversion-page deindexation.
  • Fix: Update sitemap to reference canonical final URLs only. Remove noindex from /book-appointment via Rank Math page settings. Regenerate sitemap and ping Google.

Indexation Status

  • site:harborwellness.com returns approximately 210 pages — expected ~340 based on sitemap
  • [✗] ~130 pages missing from index; concentrated in /blog/* and /services/*
  • [✗] Staging domain staging-harborwellness.wpengine.com is partially indexed (11 pages) — duplicate content risk
  • Canonical tags present on sampled pages; self-referencing correctly
  • Issue: Staging site exposure + robots.txt block account for the majority of the deindexation. Some blog posts may also be caught in a noindex sweep from a Rank Math bulk-edit action.
  • Fix: Add X-Robots-Tag: noindex header to WP Engine staging environment (via WP Engine dashboard → redirect rules). Audit Rank Math bulk SEO settings for unintended noindex toggles on post category.

Crawl Budget

  • Site size (~380 pages) is below the threshold requiring aggressive crawl budget management
  • [✗] Faceted search on /blog/ generates crawlable tag + category combos — estimated 600+ thin archive URLs
  • Issue: Tag archive pages consume crawl budget and offer no unique content value
  • Fix: Add Disallow: /tag/ to robots.txt; set tag archive pages to noindex via Rank Math → Titles & Metas → Taxonomies.

Site Speed and Core Web Vitals

LCP — target: < 2.5s

  • Mobile LCP: 4.1s (failing) | Desktop LCP: 2.2s (passing)
  • LCP element on mobile: Hero image (/wp-content/uploads/hero-iv-therapy.jpg, 1.4MB, JPEG)
  • TTFB: 980ms on mobile — above 800ms threshold; WP Engine server response is slow under load
  • Render-blocking: Google Fonts loaded synchronously (2 font families, 4 variants)
  • Issue: Uncompressed hero image + slow TTFB + render-blocking fonts combining to push mobile LCP to 4.1s
  • Fix: Convert hero to WebP (target < 200KB), add fetchpriority="high" to hero <img> tag, enable WP Engine's object cache add-on, replace Google Fonts <link> with font-display: swap self-hosted variant via Rank Math's local font feature.

INP — target: < 200ms

  • INP: 310ms (failing on mobile)
  • Main thread blocked by: Intercom chat widget (~180ms), HubSpot tracking script (~90ms), both loaded synchronously
  • Issue: Third-party scripts executing on main thread during user interaction window
  • Fix: Defer Intercom and HubSpot via <script defer> or load behind a user-interaction trigger (scroll or first click). Use Rank Math's script manager or a plugin like WP Rocket to delay execution.

CLS — target: < 0.1

  • CLS: 0.08 (passing)
  • Minor shift detected from cookie consent banner on initial load — not currently failing
  • Issue: None critical; monitor banner behavior after any plugin updates
  • Fix: Pre-reserve height for cookie banner via CSS min-height to prevent future regression.

Supplementary Speed

  • Total page weight (homepage): 3.8MB — above 3MB target; primary offenders are unoptimized images and an unused CSS bundle from a deactivated page builder
  • Gzip: Enabled ✓ | CDN (WP Engine Cloudflare): Enabled ✓ | Browser caching: Configured ✓
  • Fix: Run Rank Math + WP Rocket media optimization pass; remove deactivated Elementor CSS from queue.

Schema Markup (JSON-LD)

Implementation Check

  • JSON-LD in use ✓ | Rank Math generating schema automatically
  • 3 validation errors found in Google Rich Results Test

Page-Type Coverage

Page TypeRecommended SchemaImplemented?Valid?Notes
HomepageOrganization, WebSiteYesYesClean; sitelinks searchbox eligible
Blog postsArticle, BlogPostingYesErrorsdateModified missing on 40+ posts
Service pagesMedicalBusiness, ServicePartialErrorspriceRange field empty; missing medicalSpecialty
/book-appointmentLocalBusiness, ReservationActionNoHigh-value page with no schema
FAQ sectionsFAQPageNo6 service pages have FAQ accordions with no markup
Staff/provider pagesPerson, MedicalBusinessNoCompetitor clinics using this for E-E-A-T signals

Missing Opportunities

  • FAQPage schema on service pages — immediate rich result eligibility for "What is IV therapy?" queries
  • Person + MedicalDirector schema on provider bios — strong E-E-A-T signal for YMYL (health) content
  • Review/AggregateRating — site has 180+ Google reviews not surfaced in schema

Common Errors Found

  • dateModified absent on Article schema (Rank Math not pulling post updated date) — causes Rich Results Test warnings
  • Fix: In Rank Math → Schema → Article settings, map dateModified to %post_modified_date% variable.

Mobile-Friendliness

  • Responsive design confirmed; no separate mobile URLs
  • Viewport meta tag correctly configured
  • [✗] Base font size on blog post body: 13px — below 16px minimum; pinch-zoom required to read