Files
gw-svelte/src/lib/components/SeoHead.svelte
T
admin 65bdc8dc20 - Add "Explore our other services" block to service landing pages
with colour-tinted cards + Our Pricing entry (grey "All services" pill)
- Wrap homepage Instagram CTA in <aside aria-label="...">
- Always emit og:image:width/height with 1200x630 fallback when
  image metadata is unknown
- Add aria-current="page" to active desktop, mega-menu, and mobile
  nav links (exact-path match only — not "Services" parent)
- Richer testimonial alt text derived from dog name in the detail
  field (e.g. "Archie, a happy Goodwalk dog walking client...")
- Tier sitemap.xml priorities: home 1.0, services 0.9, pricing 0.8,
  about/contact 0.7, legal 0.3 (yearly changefreq)
- Bump to 4.1.0
2026-05-05 08:12:36 +12:00

82 lines
2.9 KiB
Svelte

<script lang="ts">
import { getImageMetadata } from '$lib/image-metadata';
export let title: string;
export let description: string;
export let canonicalPath: string;
export let image = '/images/auckland-dog-walking-happy-dog-hero.png';
export let imageAlt = 'Goodwalk Auckland dog walking services';
export let type = 'website';
export let structuredData: Record<string, unknown>[] = [];
export let noindex = false;
export let preloadImage = false;
const siteName = 'Goodwalk';
const siteUrl = 'https://www.goodwalk.co.nz';
function absoluteUrl(value: string) {
if (!value) {
return siteUrl;
}
if (value.startsWith('http://') || value.startsWith('https://')) {
return value;
}
return `${siteUrl}${value.startsWith('/') ? value : `/${value}`}`;
}
function fullTitle(value: string) {
return value.includes(siteName) ? value : `${value} | ${siteName}`;
}
$: pageTitle = fullTitle(title);
$: canonicalUrl = absoluteUrl(canonicalPath);
$: imageUrl = absoluteUrl(image);
$: imageMeta = getImageMetadata(image);
</script>
<svelte:head>
<title>{pageTitle}</title>
<meta name="description" content={description} />
<meta
name="robots"
content={noindex
? 'noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1'
: 'index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1'}
/>
<meta name="author" content="Goodwalk" />
<meta name="publisher" content="Goodwalk" />
<meta name="geo.region" content="NZ-AUK" />
<meta name="geo.placename" content="Auckland Central" />
<link rel="canonical" href={canonicalUrl} />
{#if preloadImage}
<link rel="preload" as="image" href={imageUrl} />
{/if}
<link rel="alternate" hreflang="en-NZ" href={canonicalUrl} />
<link rel="alternate" hreflang="x-default" href={canonicalUrl} />
<meta property="og:type" content={type} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:site_name" content={siteName} />
<meta property="og:locale" content="en_NZ" />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={description} />
<meta property="og:image" content={imageUrl} />
<meta property="og:image:secure_url" content={imageUrl} />
<meta property="og:image:alt" content={imageAlt} />
<meta property="og:image:width" content={String(imageMeta?.width ?? 1200)} />
<meta property="og:image:height" content={String(imageMeta?.height ?? 630)} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@goodwalk.nz" />
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={imageUrl} />
<meta name="twitter:image:alt" content={imageAlt} />
{#each structuredData as schema}
{@html `<script type="application/ld+json">${JSON.stringify(schema)}</script>`}
{/each}
</svelte:head>