Merge branch 'seo-fixes'

SEO improvements: AggregateOffer on Service schema, AggregateRating
+ Review on home, tighter Puppy Visits meta, removed dead /about-us
duplicate.
This commit is contained in:
2026-05-05 14:10:43 +12:00
4 changed files with 54 additions and 15 deletions
+1 -1
View File
@@ -13,7 +13,7 @@
function getVariant(path: string) { function getVariant(path: string) {
if (path === '/') return 'home'; if (path === '/') return 'home';
if (serviceRoutes.has(path)) return 'service'; if (serviceRoutes.has(path)) return 'service';
if (path === '/about' || path === '/about-us') return 'about'; if (path === '/about') return 'about';
if (path === '/our-pricing') return 'pricing'; if (path === '/our-pricing') return 'pricing';
if (path === '/contact-us') return 'contact'; if (path === '/contact-us') return 'contact';
if (legalRoutes.has(path)) return 'legal'; if (legalRoutes.has(path)) return 'legal';
+2 -8
View File
@@ -12,9 +12,9 @@ export const staticPages = {
canonicalPath: '/dog-walking' canonicalPath: '/dog-walking'
}, },
'puppy-visits': { 'puppy-visits': {
title: 'Puppy Visits | Puppy Training', title: 'Puppy Visits | Auckland In-Home Puppy Care | Goodwalk',
description: description:
'Puppy Visits Introducing Puppy Visits: Building strong foundations for our pack walks! We love puppies! Our puppy home visits are perfect for young pups not quite ready to join the pack and busy owners with hectic schedules. We lay the groundwork for future pack walks, including fun games, potty breaks, and even feeding if required. Let us help your furry friend thrive while you are away!', 'In-home puppy visits across Auckland Central — toilet breaks, feeding, play and gentle early training for pups not yet ready for pack walks.',
canonicalPath: '/puppy-visits' canonicalPath: '/puppy-visits'
}, },
'our-pricing': { 'our-pricing': {
@@ -29,12 +29,6 @@ export const staticPages = {
'Learn more about Kingsland based dog walking company Goodwalk. We offer our Tiny Gang pack walks throughout the Auckland region. Solo (1:1 walks), homestays and more.', 'Learn more about Kingsland based dog walking company Goodwalk. We offer our Tiny Gang pack walks throughout the Auckland region. Solo (1:1 walks), homestays and more.',
canonicalPath: '/about' canonicalPath: '/about'
}, },
'about-us': {
title: 'About Us | Dog Walkers',
description:
'Learn more about Kingsland based dog walking company Goodwalk. We offer our Tiny Gang pack walks throughout the Auckland region. Solo (1:1 walks), homestays and more.',
canonicalPath: '/about'
},
'contact-us': { 'contact-us': {
title: 'Contact Us', title: 'Contact Us',
description: 'Book a Meet & Greet or send a general enquiry to Goodwalk Auckland dog walking services.', description: 'Book a Meet & Greet or send a general enquiry to Goodwalk Auckland dog walking services.',
+21 -1
View File
@@ -89,7 +89,27 @@
url: `${siteUrl}${service.href}` url: `${siteUrl}${service.href}`
} }
})) }))
} },
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: '5.0',
bestRating: '5',
worstRating: '1',
reviewCount: String(data.content.testimonials.length)
},
review: data.content.testimonials.map((testimonial) => ({
'@type': 'Review',
reviewRating: {
'@type': 'Rating',
ratingValue: '5',
bestRating: '5'
},
author: {
'@type': 'Person',
name: testimonial.reviewer
},
reviewBody: testimonial.quote
}))
}, },
{ {
'@context': 'https://schema.org', '@context': 'https://schema.org',
+30 -5
View File
@@ -30,6 +30,28 @@
return `${siteUrl}${value.startsWith('/') ? value : `/${value}`}`; return `${siteUrl}${value.startsWith('/') ? value : `/${value}`}`;
} }
function aggregateOfferSchema(plans: { price: string }[]) {
const numericPrices = plans
.map((plan) => Number(plan.price.replace(/[^0-9.]/g, '')))
.filter((value) => Number.isFinite(value) && value > 0);
if (numericPrices.length === 0) {
return null;
}
const lowPrice = Math.min(...numericPrices);
const highPrice = Math.max(...numericPrices);
return {
'@type': 'AggregateOffer',
priceCurrency: 'NZD',
lowPrice: lowPrice.toFixed(2),
highPrice: highPrice.toFixed(2),
offerCount: numericPrices.length,
availability: 'https://schema.org/InStock'
};
}
function breadcrumbSchema(name: string, path: string) { function breadcrumbSchema(name: string, path: string) {
return { return {
'@context': 'https://schema.org', '@context': 'https://schema.org',
@@ -89,7 +111,8 @@
}, },
areaServed: 'Auckland Central, New Zealand', areaServed: 'Auckland Central, New Zealand',
image: absoluteUrl(seoImage), image: absoluteUrl(seoImage),
url: `${siteUrl}${data.page.canonicalPath}` url: `${siteUrl}${data.page.canonicalPath}`,
offers: aggregateOfferSchema(packWalksContent.pricing.plans)
}, },
breadcrumbSchema('Pack Walks', data.page.canonicalPath) breadcrumbSchema('Pack Walks', data.page.canonicalPath)
]; ];
@@ -111,7 +134,8 @@
}, },
areaServed: 'Auckland Central, New Zealand', areaServed: 'Auckland Central, New Zealand',
image: absoluteUrl(seoImage), image: absoluteUrl(seoImage),
url: `${siteUrl}${data.page.canonicalPath}` url: `${siteUrl}${data.page.canonicalPath}`,
offers: aggregateOfferSchema(dogWalkingContent.pricing.plans)
}, },
breadcrumbSchema('1:1 Walks', data.page.canonicalPath) breadcrumbSchema('1:1 Walks', data.page.canonicalPath)
]; ];
@@ -133,7 +157,8 @@
}, },
areaServed: 'Auckland Central, New Zealand', areaServed: 'Auckland Central, New Zealand',
image: absoluteUrl(seoImage), image: absoluteUrl(seoImage),
url: `${siteUrl}${data.page.canonicalPath}` url: `${siteUrl}${data.page.canonicalPath}`,
offers: aggregateOfferSchema(puppyVisitsContent.pricing.plans)
}, },
breadcrumbSchema('Puppy Visits', data.page.canonicalPath) breadcrumbSchema('Puppy Visits', data.page.canonicalPath)
]; ];
@@ -148,7 +173,7 @@
}, },
breadcrumbSchema('Our Pricing', data.page.canonicalPath) breadcrumbSchema('Our Pricing', data.page.canonicalPath)
]; ];
} else if (data.slug === 'about' || data.slug === 'about-us') { } else if (data.slug === 'about') {
seoImage = aboutPageContent.sections[0].imageUrl; seoImage = aboutPageContent.sections[0].imageUrl;
seoImageAlt = aboutPageContent.sections[0].imageAlt; seoImageAlt = aboutPageContent.sections[0].imageAlt;
pageStructuredData = [ pageStructuredData = [
@@ -186,7 +211,7 @@
<ServiceLandingPage content={data.content} pageContent={puppyVisitsContent} currentPath={data.page.canonicalPath} /> <ServiceLandingPage content={data.content} pageContent={puppyVisitsContent} currentPath={data.page.canonicalPath} />
{:else if data.slug === 'our-pricing'} {:else if data.slug === 'our-pricing'}
<PricingPage content={data.content} pageContent={ourPricingContent} /> <PricingPage content={data.content} pageContent={ourPricingContent} />
{:else if data.slug === 'about' || data.slug === 'about-us'} {:else if data.slug === 'about'}
<AboutPage content={data.content} pageContent={aboutPageContent} /> <AboutPage content={data.content} pageContent={aboutPageContent} />
{:else if data.slug === 'terms-and-conditions'} {:else if data.slug === 'terms-and-conditions'}
<LegalPage pageContent={termsAndConditionsContent} /> <LegalPage pageContent={termsAndConditionsContent} />