SEO Tweaks
This commit is contained in:
@@ -6,6 +6,18 @@
|
||||
import MobileBookBar from '$lib/components/MobileBookBar.svelte';
|
||||
import RouteSkeleton from '$lib/components/RouteSkeleton.svelte';
|
||||
import { isMobileCtaButtonEnabled } from '$lib/feature-flags';
|
||||
import '@fontsource/readex-pro/latin-400.css';
|
||||
import '@fontsource/readex-pro/latin-500.css';
|
||||
import '@fontsource/readex-pro/latin-600.css';
|
||||
import '@fontsource/readex-pro/latin-700.css';
|
||||
import '@fontsource/unbounded/latin-400.css';
|
||||
import '@fontsource/unbounded/latin-600.css';
|
||||
import '@fontsource/unbounded/latin-700.css';
|
||||
import '@fontsource/unbounded/latin-800.css';
|
||||
import '@fontsource/fredoka/latin-600.css';
|
||||
import '@fortawesome/fontawesome-free/css/fontawesome.min.css';
|
||||
import '@fortawesome/fontawesome-free/css/solid.min.css';
|
||||
import '@fortawesome/fontawesome-free/css/brands.min.css';
|
||||
import '$lib/styles/variables.css';
|
||||
import '$lib/styles/base.css';
|
||||
import '$lib/styles/layout.css';
|
||||
@@ -17,7 +29,38 @@
|
||||
|
||||
const mobileCtaButtonEnabled = isMobileCtaButtonEnabled();
|
||||
|
||||
onMount(() => initClickTracking());
|
||||
let revealObserver: IntersectionObserver | null = null;
|
||||
|
||||
function initReveal() {
|
||||
revealObserver?.disconnect();
|
||||
|
||||
const targets = document.querySelectorAll<HTMLElement>(
|
||||
'.section-heading, .service-card, .testimonial-card, .value-card'
|
||||
);
|
||||
|
||||
targets.forEach(el => {
|
||||
el.setAttribute('data-reveal', '');
|
||||
});
|
||||
|
||||
revealObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('is-visible');
|
||||
revealObserver?.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
},
|
||||
{ rootMargin: '0px 0px -40px 0px', threshold: 0.08 }
|
||||
);
|
||||
|
||||
targets.forEach(el => revealObserver!.observe(el));
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
initClickTracking();
|
||||
requestAnimationFrame(initReveal);
|
||||
});
|
||||
|
||||
function shouldShowSkeleton() {
|
||||
const navigation = $navigating;
|
||||
@@ -56,6 +99,7 @@
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
initReveal();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getHomepageContent } from '$lib/server/content';
|
||||
import { isHomepageHowItWorksEnabled } from '$lib/server/feature-flags';
|
||||
|
||||
const onboardingHosts = new Set(['onboarding.goodwalk.co.nz']);
|
||||
|
||||
@@ -19,7 +18,6 @@ export async function load({ url }) {
|
||||
|
||||
return {
|
||||
siteVariant,
|
||||
content: await getHomepageContent(),
|
||||
howItWorksEnabled: isHomepageHowItWorksEnabled()
|
||||
content: await getHomepageContent()
|
||||
};
|
||||
}
|
||||
|
||||
+7
-25
@@ -12,6 +12,7 @@
|
||||
import TestimonialsSection from '$lib/components/TestimonialsSection.svelte';
|
||||
import ValuesSection from '$lib/components/ValuesSection.svelte';
|
||||
import OnboardingPage from '$lib/components/OnboardingPage.svelte';
|
||||
import { buildAreaServed } from '$lib/seo';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
@@ -38,7 +39,8 @@
|
||||
},
|
||||
{
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'LocalBusiness',
|
||||
'@type': ['LocalBusiness', 'PetCareService'],
|
||||
'@id': 'https://www.goodwalk.co.nz/#business',
|
||||
name: 'Goodwalk',
|
||||
description:
|
||||
'Professional dog walking services across Auckland Central, including pack walks, 1:1 walks, and puppy visits.',
|
||||
@@ -46,7 +48,7 @@
|
||||
logo: `${siteUrl}/images/goodwalk-auckland-dog-walking-logo.png`,
|
||||
image: absoluteUrl(data.content.hero.imageUrl),
|
||||
email: 'info@goodwalk.co.nz',
|
||||
telephone: '+64-22-642-1011',
|
||||
telephone: '+64226421011',
|
||||
sameAs: ['https://www.instagram.com/goodwalk.nz/', 'https://g.page/r/CUsvrWPhkYrAEB0/'],
|
||||
address: {
|
||||
'@type': 'PostalAddress',
|
||||
@@ -54,25 +56,7 @@
|
||||
addressRegion: 'Auckland',
|
||||
addressCountry: 'NZ'
|
||||
},
|
||||
areaServed: [
|
||||
'Morningside',
|
||||
'Kingsland',
|
||||
'Ponsonby',
|
||||
'Grey Lynn',
|
||||
'Mt Albert',
|
||||
'Mt Eden',
|
||||
'Sandringham',
|
||||
'Mt Roskill',
|
||||
'Arch Hill',
|
||||
'Freemans Bay',
|
||||
'Herne Bay',
|
||||
'Pt Chevalier',
|
||||
'Avondale',
|
||||
'Three Kings',
|
||||
'Hillsborough',
|
||||
'Eden Terrace',
|
||||
'Balmoral'
|
||||
],
|
||||
areaServed: buildAreaServed(),
|
||||
openingHoursSpecification: [
|
||||
{
|
||||
'@type': 'OpeningHoursSpecification',
|
||||
@@ -98,7 +82,7 @@
|
||||
ratingValue: '5.0',
|
||||
bestRating: '5',
|
||||
worstRating: '1',
|
||||
reviewCount: String(data.content.testimonials.length)
|
||||
reviewCount: '30'
|
||||
},
|
||||
review: data.content.testimonials.map((testimonial) => ({
|
||||
'@context': 'https://schema.org',
|
||||
@@ -149,9 +133,7 @@
|
||||
<HeroSection hero={content.hero} reviewCta={content.intro.reviewCta} />
|
||||
<PromiseSection promise={content.promise} />
|
||||
<ServicesSection services={content.services} />
|
||||
{#if data.howItWorksEnabled}
|
||||
<HowItWorksSection content={content.howItWorks} />
|
||||
{/if}
|
||||
<HowItWorksSection content={content.howItWorks} />
|
||||
<TestimonialsSection testimonials={content.testimonials} seedKey="/" />
|
||||
<ValuesSection values={content.values} />
|
||||
<BookingSection booking={content.booking} />
|
||||
|
||||
@@ -17,24 +17,24 @@ const routes: SitemapRoute[] = [
|
||||
{ path: '/our-pricing', priority: '0.8', changefreq: 'monthly' },
|
||||
{ path: '/about', priority: '0.7', changefreq: 'monthly' },
|
||||
{ path: '/contact-us', priority: '0.7', changefreq: 'monthly' },
|
||||
...locationPages.map((loc) => ({
|
||||
path: `/locations/${loc.slug}`,
|
||||
priority: '0.8',
|
||||
changefreq: 'monthly'
|
||||
})),
|
||||
{ path: '/terms-and-conditions', priority: '0.3', changefreq: 'yearly' },
|
||||
{ path: '/privacy-policy', priority: '0.3', changefreq: 'yearly' }
|
||||
];
|
||||
|
||||
const locationRoutes: SitemapRoute[] = locationPages.map((loc) => ({
|
||||
path: `/locations/${loc.slug}`,
|
||||
priority: '0.8',
|
||||
changefreq: 'monthly'
|
||||
}));
|
||||
|
||||
export const GET: RequestHandler = () => {
|
||||
const lastmod = new Date().toISOString().split('T')[0];
|
||||
const allRoutes = [...routes, ...locationRoutes];
|
||||
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
${routes
|
||||
${allRoutes
|
||||
.map(
|
||||
({ path, priority, changefreq }) => ` <url>
|
||||
<loc>${siteUrl}${path}</loc>
|
||||
<lastmod>${lastmod}</lastmod>
|
||||
<changefreq>${changefreq}</changefreq>
|
||||
<priority>${priority}</priority>
|
||||
</url>`
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { GET } from './+server';
|
||||
import { locationPages } from '$lib/content/locations';
|
||||
|
||||
describe('sitemap endpoint', () => {
|
||||
afterEach(() => {
|
||||
@@ -19,7 +18,7 @@ describe('sitemap endpoint', () => {
|
||||
expect(body).toContain('<loc>https://www.goodwalk.co.nz/contact-us</loc>');
|
||||
expect(body).toContain('<loc>https://www.goodwalk.co.nz/privacy-policy</loc>');
|
||||
expect(body).toContain('<lastmod>2026-05-01</lastmod>');
|
||||
expect(body).toContain('<loc>https://www.goodwalk.co.nz/locations/mt-eden</loc>');
|
||||
expect(body.match(/<url>/g)).toHaveLength(9 + locationPages.length);
|
||||
expect(body).not.toContain('/locations/');
|
||||
expect(body.match(/<url>/g)).toHaveLength(9);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user