38 KiB
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 600–900 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 ~150–300ms TTFB from geography. NGINX has Gzip at level 6 but no Brotli (15–25% 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 (140–160 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 57–75
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 (~40–55% 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