Files
gw-svelte/SEO-AUDIT.MD
T
2026-05-12 00:45:02 +12:00

38 KiB
Raw Blame History

goodwalk.co.nz — Full SEO Audit Report

Date: 12 May 2026 | Site: Auckland dog walking service (SvelteKit + NGINX) | Auditor: 9 specialist subagents run in parallel


SEO Health Score: 60 / 100

┌──────────────────────────┬────────┬───────┬───────────┐ │ Category │ Weight │ Score │ Weighted │ ├──────────────────────────┼────────┼───────┼───────────┤ │ Content Quality │ 23% │ 68 │ 15.6 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ Technical SEO │ 22% │ 52 │ 11.4 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ On-Page SEO │ 20% │ 62 │ 12.4 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ Schema / Structured Data │ 10% │ 58 │ 5.8 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ Performance (CWV) │ 10% │ 62 │ 6.2 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ AI Search Readiness │ 10% │ 51 │ 5.1 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ Images │ 5% │ 65 │ 3.3 │ ├──────────────────────────┼────────┼───────┼───────────┤ │ TOTAL │ │ │ 59.8 → 60 │ └──────────────────────────┴────────┴───────┴───────────┘

▎ The score is dragged down by one dominant structural issue: all 17 location pages are noindex. Remove that single directive and the score jumps ~8 points immediately.


CRITICAL Issues (Fix Immediately)

C-1 — All 17 location pages are noindex

File: src/routes/locations/[suburb]/+page.svelte line ~23

Every suburb page (/locations/mt-eden, /locations/kingsland, etc.) has noindex set. These are Goodwalk's primary local SEO assets — suburb-specific content, Service schema, BreadcrumbList, targeted H1s — and none of it is visible to Google. This is the largest single SEO issue on the site.

Fix: Remove noindex from the call. One line change, high impact.

C-2 — Location pages missing from sitemap

File: src/routes/sitemap.xml/+server.ts

The sitemap deliberately excludes /locations/*. After unblocking indexation (C-1), Google discovery will be slow without sitemap inclusion.

Fix: Import locationPages from $lib/content/locations and generate dynamic sitemap entries for all 17 suburb URLs.

C-3 — reviewCount in schema is 4 when business has 30+ Google reviews

File: src/routes/+page.svelte ~line 101

reviewCount is hardcoded to String(data.content.testimonials.length) which resolves to "4". The site claims "30+ five-star Google reviews" in visible copy. Emitting reviewCount: "4" suppresses rich result eligibility and creates a factual schema/content discrepancy.

Fix: Change to a static "30" floor value or a content-managed field.


HIGH Priority (Fix Within 1 Week)

H-1 — Homepage suburb list not linked to location pages

File: src/lib/content/homepage.ts, InfoSection component

The info.suburbs string is plain text — not hyperlinks. Even after fixing C-1, Google won't easily discover or distribute PageRank to location pages without internal links from the homepage. This is the fastest way to give location pages authority.

Fix: Render each suburb as in the InfoSection.

H-2 — Font Awesome npm import is killing performance

File: src/routes/+layout.svelte

Three FontAwesome CSS files (fontawesome.min.css, solid.min.css, brands.min.css) are imported globally for ~8 icons. Combined with 9 @fontsource weight files (Readex Pro × 4, Unbounded × 4, Fredoka × 1), this is estimated at 600900 KB uncompressed CSS + WOFF2 on every page. This is the single largest performance bottleneck and the highest-ROI fix.

Fix: Replace Font Awesome with inline SVG components for the specific icons used. Drop unused font weights.

H-3 — Hero image preload is broken

File: src/lib/components/SeoHead.svelte

points to the raw .png file, but @sveltejs/enhanced-img generates AVIF/WebP variants that the browser actually uses. The preload wastes bandwidth fetching the PNG while the actual LCP element loads later. The fetchpriority="high" on the already handles this correctly.

Fix: Remove the from SeoHead when preloadImage=true — rely solely on fetchpriority="high" on the image element.

H-4 — Schema missing @id node stitching

File: src/routes/+page.svelte, src/routes/[slug]/+page.svelte, src/lib/seo.ts

No schema block uses @id URIs, so Google cannot link the LocalBusiness entity to the Service blocks across pages — they're treated as unrelated graphs. This weakens Knowledge Graph entity consolidation significantly.

Fix:

  • Add "@id": "https://www.goodwalk.co.nz/#business" to the LocalBusiness block
  • Reference it as "provider": {"@id": "https://www.goodwalk.co.nz/#business"} in every Service block

H-5 — @type: LocalBusiness too generic — missing PetCareService

File: src/routes/+page.svelte ~line 41

Using ["LocalBusiness", "PetCareService"] as the @type improves entity disambiguation for pet-service queries. No breaking change.

H-6 — No NZ directory citations

No codebase evidence of listings on:

  • Yellow Pages NZ (yellow.co.nz) — highest DA, commonly cited by Google NZ
  • Finda NZ (finda.co.nz) — pet services category exists
  • NoCowboys (nocowboys.co.nz) — NZ-specific service directory
  • Localist (localist.co.nz) — Auckland local business focus
  • Neighbourly (neighbourly.co.nz) — suburb-level community platform

Per Whitespark 2026, 3 of the top 5 AI visibility factors are citation signals. For a local NZ service business this gap is material.

H-7 — Service pages missing from desktop navigation

The desktop nav only has #services (anchor), /our-pricing, and /about. Direct /pack-walks, /dog-walking, /puppy-visits URLs are not in the desktop nav — only the mobile nav and footer.


MEDIUM Priority (Fix Within 1 Month)

M-1 — All three service pages below 800-word threshold

Pack Walks (~580 words), 1:1 Walks (~530 words), Puppy Visits (~510 words) all fall below the service page minimum. Missing from each: FAQ section, process explanation unique to that service, breed/situation examples.

M-2 — H1 lacks "dog walking Auckland" keyword

The hero H1 is "Come home to a calm, happy dog" — emotionally led but not keyword-anchored. "Auckland Central" appears in the subtitle but the primary query phrase "dog walking Auckland" is absent from any rendered H1 on the site. Google's local ranking algorithm still weights explicit keyword presence in H1.

M-3 — FAQ answers not self-contained for AI citation

All FAQ answers require context to make sense. For AI Overviews, each answer needs the entity name and full context embedded in the answer itself. Example: "All walks are paid for a week in advance, via invoice" → should read "Goodwalk charges for walks one week in advance via invoice."

M-4 — www vs non-www in sitemap vs canonical domain

The sitemap uses https://www.goodwalk.co.nz as the base. Confirm this is the canonical domain (it should be — NGINX enforces the www redirect). The audit was requested for https://goodwalk.co.nz (no www). If both are correct and consistent, no action needed.

M-5 — lastmod always set to today's date

File: src/routes/sitemap.xml/+server.ts line ~24

new Date().toISOString() at request time means every URL always shows today as last-modified. Google treats this as an unreliable freshness signal (may look manipulative). Replace with static per-route dates reflecting actual content changes.

M-6 — No Content Security Policy header

File: nginx/goodwalk.co.nz.svelte.conf.example

No Content-Security-Policy header is set. GA4 is loaded from www.googletagmanager.com without a CSP allowlist. Also missing Permissions-Policy. No immediate SEO impact but a security posture gap.

M-7 — Phone format inconsistent across schema

Homepage schema: +64-22-642-1011 (dashes). seo.ts provider: +64226421011 (no dashes). Standardise all schema telephone to E.164 without hyphens: +64226421011.

M-8 — No CDN / Brotli compression

All traffic routes to an Auckland VPS with no edge caching. PageSpeed mobile lab scores will be penalised by ~150300ms TTFB from geography. NGINX has Gzip at level 6 but no Brotli (1525% better compression). Short-term: enable Brotli or raise Gzip to level 9. Medium-term: add Cloudflare free tier.

M-9 — Add AI crawler permissions to robots.txt

File: src/routes/robots.txt/+server.ts

The robots.txt exists but has no AI crawler-specific directives (GPTBot, ClaudeBot, PerplexityBot, OAI-SearchBot). Explicitly allowing these signals GEO awareness and removes ambiguity.

M-10 — No llms.txt

A minimal static/llms.txt declaring key pages and a business summary would improve citability on Perplexity and emerging LLM crawlers. Low effort, growing importance.

M-11 — No business summary in AI citation window (140160 words)

No single paragraph on the site answers who/what/where/when/how-much in one citable block. GEO agent provided a ready-to-use 148-word draft in its findings.

M-12 — areaServed on homepage uses strings, not Place objects

File: src/routes/+page.svelte lines 5775

Homepage hardcodes suburb strings directly. The buildAreaServed() utility in seo.ts already returns correctly typed Place objects — it just needs to be called on the homepage too.

M-13 — FAQPage schema on commercial site (Google rich results — limited value)

Files: src/routes/+page.svelte, src/routes/[slug]/+page.svelte

Google restricted FAQPage rich results to government/healthcare sites (Aug 2023). The FAQPage blocks produce no Google rich results for Goodwalk. However, the schema does provide AI/LLM citation benefit — it's the structured content that Perplexity and Google AI Overviews prefer to extract. Recommendation: Keep FAQPage schema but note it won't produce visual rich results in standard SERPs.


LOW Priority (Backlog)

┌────────────────────────────────────────────────┬───────────────────────┬──────────────────────────────────────────────────────────┐ │ Issue │ File │ Notes │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Add priceRange: "$$" to LocalBusiness schema │ +page.svelte │ Appears in knowledge panels │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Add Person schema for Alessandra (founder) │ +page.svelte │ E-E-A-T signal for founder-led business │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Add SearchAction to WebSite schema │ +page.svelte │ Sitelinks Searchbox potential │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Add ContactPage schema to /contact-us │ [slug]/+page.svelte │ Missing structured data on key conversion page │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Add seller to AggregateOffer on service pages │ [slug]/+page.svelte │ Link back to LocalBusiness entity │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Remove @context from nested Review objects │ +page.svelte │ Redundant, technically incorrect placement │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Mobile testimonial carousel CLS │ responsive.css │ Set min-height on mobile stage for longest quote │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ disallow: /api/ in robots.txt │ robots.txt/+server.ts │ Keeps crawl budget on content pages │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ disallow: /contract in robots.txt │ Same │ Zero indexing value, wastes crawl budget │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ HSTS preload directive │ NGINX config │ Required for HSTS preload list submission │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Move large images to src/lib/images/ │ /static/images/ │ Puppy visits image is 3,327×2,217px, served uncompressed │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ terms-and-conditions, privacy-policy → noindex │ static-pages.ts │ Currently indexed; minor │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ IndexNow protocol │ New route │ Bing/Yandex faster indexation │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Founding year in content │ Content files │ "Serving Auckland since [year]" adds trust signal │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Second review platform (NoCowboys NZ) │ GBP/footer │ Review diversity reduces single-platform risk │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ YouTube presence │ External │ Highest-correlation AI citation signal — entirely absent │ ├────────────────────────────────────────────────┼───────────────────────┼──────────────────────────────────────────────────────────┤ │ Question-format H2/H3 headings │ Content files │ Current headings are descriptive, not interrogative │ └────────────────────────────────────────────────┴───────────────────────┴──────────────────────────────────────────────────────────┘


Backlink Profile

The backlinks agent was unable to run Python API scripts (Bash access not available in this session). However it identified the following key link building opportunities:

Unconfirmed NZ directory gaps (verify manually):

  • Yellow Pages NZ, Finda NZ, NoCowboys, Localist, Neighbourly, Dogz Online NZ, PetPages NZ

Known competitor backlink sources to audit: Search site:yellow.co.nz "dog walking auckland" and site:nocowboys.co.nz "dog walking" to find listings Goodwalk is missing.

To get a full scored backlink report, run python scripts/commoncrawl_graph.py goodwalk.co.nz --json via the terminal.


What's Working Well

┌───────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Strength │ Detail │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Full SSR │ SvelteKit SSR with adapter-node — all content in initial HTML, crawlers receive complete pages │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Security headers │ HTTPS, HSTS, X-Frame-Options, X-Content-Type-Options, HSTS all present │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Mobile implementation │ overflow-x: clip, iOS zoom prevention, safe-area-inset-bottom, aria-expanded — thorough │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ LocalBusiness schema │ Comprehensive: opening hours, offer catalog, reviews, sameAs, area served — strong foundation │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ max-snippet:-1 │ Correctly set — allows Google to use any text length for AI Overviews │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ LCP optimisation signals │ fetchpriority="high", loading="eager", decoding="async" on hero image │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ SSR structured data │ JSON-LD is server-rendered in initial HTML, not injected by JS │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Legacy redirects │ /about-us, /booking, /home-stays all 301 correctly via SvelteKit │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Canonical consistency │ siteUrl and NGINX redirect align on https://www.goodwalk.co.nz │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ geo.region / hreflang │ NZ-AUK geo meta and en-NZ hreflang correctly implemented │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Location page content quality │ 17 pages with genuinely unique suburb intros, named parks, leash notes — passes doorway test │ ├───────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤ │ Brand differentiation │ "Tiny Gang," small dog specialist, solo operator with named walker — strong and citable │ └───────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘


Prioritised Action Plan

WEEK 1 — Critical + quick wins [C-1] Remove noindex from /locations/[suburb]/+page.svelte → 5 min [C-2] Add location pages to sitemap.xml/+server.ts → 30 min [C-3] Fix reviewCount: 4 → 30 in AggregateRating → 5 min [H-1] Link suburb names on homepage InfoSection to location pages → 1 hr [H-3] Remove broken from SeoHead → 15 min [H-4] Add @id anchors to LocalBusiness and Service schemas → 30 min [H-5] Change @type to ["LocalBusiness", "PetCareService"] → 5 min [M-7] Standardise telephone to +64226421011 in all schema → 10 min

WEEK 2 — Performance + citations [H-2] Replace Font Awesome with inline SVG icons → 3 hrs [H-6] Create NZ directory listings (Yellow Pages, Finda, NoCowboys, Localist, Neighbourly) [M-9] Add AI crawler directives to robots.txt → 15 min [M-12] Fix areaServed → call buildAreaServed() on homepage → 15 min [M-5] Replace dynamic lastmod with static per-route dates → 30 min

MONTH 1 — Content + AI readiness [M-1] Expand service pages to 800+ words each (add FAQ, process, examples) [M-2] Update H1 or subtitle to include "dog walking Auckland" [M-3] Rewrite FAQ answers to be self-contained, entity-named [M-10] Create static/llms.txt → 30 min [M-11] Add 148-word business summary paragraph to About page [M-6] Add Content-Security-Policy and Permissions-Policy headers

BACKLOG — Nice to have Add Person schema for Alessandra Add priceRange, SearchAction, ContactPage schema Move large images to src/lib/images/ for AVIF/WebP pipeline Enable Brotli on NGINX Add Cloudflare CDN Build YouTube presence Second review platform (NoCowboys NZ)


▎ SXO agent is still running — I'll append its search experience / intent-match findings when it completes.


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Built by agricidaniel — Join the AI Marketing Hub community 🆓 Free → https://www.skool.com/ai-marketing-hub Pro → https://www.skool.com/ai-marketing-hub-pro ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✻ Cogitated for 4m 23s

● Agent "SXO search experience optimization for goodwalk.co.nz" completed

● The SXO agent is in — here are the additional findings it surfaced:


SXO Findings — Search Experience Optimization

SXO Gap Score: 68 / 100

Page-Type Analysis

The site's structure is largely correct — single-provider service pages are the right type for branded and long-tail queries. The dominant structural problem is the same one found in Technical SEO: the 17 location pages are noindexed, which means Goodwalk cannot compete for the high-value suburb-specific queries ("dog walker Mt Eden", "dog walking Ponsonby") where a dedicated location page would beat both a homepage and a directory listing.

For the head terms "dog walker Auckland" / "dog walking Auckland", the SERP is dominated by Local Pack results (~4055% of clicks) and aggregator directories (Bark.com, NoCowboys). A single-provider homepage cannot displace aggregators on these terms — the real wins are in the Local Pack (GBP) and in long-tail suburb + service queries where location pages and specific service pages can rank.

Additional Issues Surfaced by SXO

HIGH — Homepage