Reactive SEO - Global default in root layout, reactive reusable component, data props
This commit is contained in:
parent
8291443c80
commit
0e30d0a539
|
@ -0,0 +1,150 @@
|
|||
<!-- <script lang="ts">
|
||||
import * as conf from '$lib/config'
|
||||
import { getImageLink } from '$lib/images';
|
||||
import type { ExtendedService, ExtendedCategory } from '$lib/types/service';
|
||||
export let data: ExtendedService | ExtendedCategory
|
||||
|
||||
let seoData: ExtendedService | ExtendedCategory
|
||||
|
||||
export let title: string;
|
||||
export let description: string;
|
||||
export let type: string;
|
||||
export let keywords: string;
|
||||
export let image: string;
|
||||
export let canonical: string;
|
||||
export let twitter: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
} = {};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
<meta name="robots" content="index, follow" />
|
||||
<meta name="googlebot" content="index,follow" />
|
||||
{#if data.description}
|
||||
<meta name="description" content={data.description} />
|
||||
{/if}
|
||||
<meta name="keywords" content={keywords} />
|
||||
{#if data.canonical}
|
||||
<link rel="canonical" href={data.canonical} />
|
||||
{/if}
|
||||
|
||||
<meta property="og:site_name" content="{conf.title}" />
|
||||
<meta property="og:title" content={data.title} />
|
||||
<meta property="og:type" content={data.type ? data.type : 'site'} />
|
||||
{#if data.description}
|
||||
<meta property="og:description" content={data.description} />
|
||||
{/if}
|
||||
{#if data.canonical}
|
||||
<meta property="og:url" content={data.canonical} />
|
||||
{/if}
|
||||
<meta property="og:image" content={getImageLink({id: data.id, h:, w:})} />
|
||||
|
||||
<meta property="fb:admins" content="${conf.FBNumID}" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={data.title} />
|
||||
{#if data.description}
|
||||
<meta name="twitter:description" content={data.description} />
|
||||
{/if}
|
||||
<meta name="twitter:image" content={twitter.image || image} />
|
||||
|
||||
<meta property="article:published_time" content={data.frontmatter?.date} />
|
||||
{#each data.frontmatter?.tags as tag (tag)}
|
||||
<meta property="article:tag" content={tag} />
|
||||
{/each}
|
||||
|
||||
</svelte:head> -->
|
||||
<!-- src/lib/components/SEO.svelte -->
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import * as conf from '$lib/config';
|
||||
|
||||
export let seoData: {
|
||||
title: string;
|
||||
description: string;
|
||||
type: string;
|
||||
keywords: string;
|
||||
image: string;
|
||||
canonical?: string;
|
||||
twitter?: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
};
|
||||
frontmatter?: {
|
||||
date: string;
|
||||
tags: string[];
|
||||
};
|
||||
};
|
||||
|
||||
$: title = seoData.title;
|
||||
$: description = seoData.description;
|
||||
$: type = seoData.type;
|
||||
$: keywords = seoData.keywords;
|
||||
$: image = seoData.image;
|
||||
$: canonical = seoData.canonical;
|
||||
$: twitter = seoData.twitter;
|
||||
$: frontmatter = seoData.frontmatter;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{title}</title>
|
||||
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
<meta name="googlebot" content="index,follow" />
|
||||
|
||||
{#if description}
|
||||
<meta name="description" content={description} />
|
||||
{/if}
|
||||
|
||||
<meta name="keywords" content={keywords} />
|
||||
|
||||
{#if canonical}
|
||||
<link rel="canonical" href={canonical} />
|
||||
{/if}
|
||||
|
||||
<meta property="og:site_name" content={conf.title} />
|
||||
|
||||
<meta property="og:title" content={title} />
|
||||
|
||||
{#if description}
|
||||
<meta property="og:description" content={description} />
|
||||
{/if}
|
||||
|
||||
{#if canonical}
|
||||
<meta property="og:url" content={canonical} />
|
||||
{/if}
|
||||
|
||||
<meta property="og:image" content={image} />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
|
||||
<meta name="twitter:title" content={twitter?.title || title} />
|
||||
|
||||
{#if twitter?.description || description}
|
||||
<meta name="twitter:description" content={twitter?.description || description} />
|
||||
{/if}
|
||||
|
||||
<meta name="twitter:image" content={twitter?.image || image} />
|
||||
|
||||
<!--If there is frontmatter, make it into an article-->
|
||||
{#if frontmatter?}
|
||||
<meta property="og:type" content="article" />
|
||||
{:else}
|
||||
<meta property="og:type" content={type || 'website'} />
|
||||
{/if}
|
||||
|
||||
{#if frontmatter?.date}
|
||||
<meta property="article:published_time" content={frontmatter.date} />
|
||||
{/if}
|
||||
|
||||
{#if frontmatter?.tags}
|
||||
{#each frontmatter.tags as tag}
|
||||
<meta property="article:tag" content={tag} />
|
||||
{/each}
|
||||
{/if}
|
||||
</svelte:head>
|
|
@ -1,20 +0,0 @@
|
|||
<script lang="ts">
|
||||
import * as conf from '$lib/config'
|
||||
import type { ExtendedServiceItem } from '$lib/types/service';
|
||||
|
||||
export let openGraphData: ExtendedServiceItem;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{openGraphData.title}</title>
|
||||
<meta name="description" content={openGraphData.description} />
|
||||
<meta property="og:title" content={openGraphData.title} />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:description" content={openGraphData.description} />
|
||||
<meta property="og:url" content="{conf.url}{openGraphData.id}" />
|
||||
<meta property="og:image" content={openGraphData.image} />
|
||||
<meta property="article:published_time" content={openGraphData.date} />
|
||||
{#each tags as tag (tag)} <!-- FIX THIS tags is not defined, but it needs to be "eached somehow"-->
|
||||
<meta property="article:tag" content={openGraphData.tag} />
|
||||
{/each}
|
||||
</svelte:head>
|
|
@ -1,56 +0,0 @@
|
|||
<script lang="ts">
|
||||
import * as conf from '$lib/config'
|
||||
import type { ExtendedService, ExtendedCategory } from '$lib/types/service';
|
||||
export let data: ExtendedService | ExtendedCategory
|
||||
|
||||
export let title: string;
|
||||
export let description: string;
|
||||
export let type: string;
|
||||
export let keywords: string;
|
||||
export let image: string;
|
||||
export let canonical: string = undefined;
|
||||
export let twitter: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
} = {};
|
||||
conf.</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{data.title}</title>
|
||||
<meta name="robots" content="index, follow" />
|
||||
<meta name="googlebot" content="index,follow" />
|
||||
{#if data.description}
|
||||
<meta name="description" content={data.description} />
|
||||
{/if}
|
||||
<meta name="keywords" content={keywords} />
|
||||
{#if data.canonical}
|
||||
<link rel="canonical" href={data.canonical} />
|
||||
{/if}
|
||||
|
||||
<meta property="og:site_name" content="{conf.title}" />
|
||||
<meta property="og:title" content={data.title} />
|
||||
<meta property="og:type" content={data.type ? data.type : 'site'} />
|
||||
{#if data.description}
|
||||
<meta property="og:description" content={data.description} />
|
||||
{/if}
|
||||
{#if data.canonical}
|
||||
<meta property="og:url" content={data.canonical} />
|
||||
{/if}
|
||||
<meta property="og:image" content={data.image} />
|
||||
|
||||
<meta property="fb:admins" content="{conf.FBNumID}" />
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content={data.title} />
|
||||
{#if data.description}
|
||||
<meta name="twitter:description" content={data.description} />
|
||||
{/if}
|
||||
<meta name="twitter:image" content={twitter.image || image} />
|
||||
|
||||
<meta property="article:published_time" content={data.frontmatter?.date} />
|
||||
{#each data.frontmatter?.tags as tag (tag)}
|
||||
<meta property="article:tag" content={tag} />
|
||||
{/each}
|
||||
|
||||
</svelte:head>
|
|
@ -27,25 +27,35 @@
|
|||
import MainFooter from '$lib/components/MainFooter.svelte';
|
||||
|
||||
// SEO Meta tags
|
||||
const metaDefaults = {
|
||||
title: 'BeautySalon',
|
||||
description: 'BeautySalon Popis.',
|
||||
image: 'https://user-images.githubusercontent.com/1509726/212382766-f29b9c9a-82e3-44c2-b911-b17a9197e5b9.jpg'
|
||||
};
|
||||
const meta = {
|
||||
title: metaDefaults.title,
|
||||
description: metaDefaults.description,
|
||||
image: metaDefaults.image,
|
||||
// Article
|
||||
article: { publishTime: '', modifiedTime: '', author: '' },
|
||||
// Twitter
|
||||
twitter: {
|
||||
title: metaDefaults.title,
|
||||
description: metaDefaults.description,
|
||||
image: metaDefaults.image
|
||||
}
|
||||
import SEO from '$lib/components/SEO.svelte'
|
||||
|
||||
$: seoData = $page.data.seoData || {
|
||||
title: 'KKosmetickySalon - Klára Morinová',
|
||||
description: 'Přijeďte si ke mně pro odbornou péči o Vaši pleť. Jsem certifikovaná kosmetička a makeup artistka, provádím Permanentní Make-up, vizážistiku, ošetřovací a zeštihlovací procedury, a mnoho dalšího... Vše s ohledem na vaše zdraví. Zarezervujte si péči o svůj vzhled přes moje stránky nyní!',
|
||||
keywords: 'kosmetika, vizáž, pleť, Písek, kosmetička, permanentní makeup, ',
|
||||
image: '/logo-text.png',
|
||||
type: 'website',
|
||||
};
|
||||
|
||||
// const metaDefaults = {
|
||||
// title: 'BeautySalon',
|
||||
// description: 'BeautySalon Popis.',
|
||||
// image: 'https://user-images.githubusercontent.com/1509726/212382766-f29b9c9a-82e3-44c2-b911-b17a9197e5b9.jpg'
|
||||
// };
|
||||
// const meta = {
|
||||
// title: metaDefaults.title,
|
||||
// description: metaDefaults.description,
|
||||
// image: metaDefaults.image,
|
||||
// // Article
|
||||
// article: { publishTime: '', modifiedTime: '', author: '' },
|
||||
// // Twitter
|
||||
// twitter: {
|
||||
// title: metaDefaults.title,
|
||||
// description: metaDefaults.description,
|
||||
// image: metaDefaults.image
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
// Scroll to anchor
|
||||
$: if ($page.url.pathname) {
|
||||
|
@ -63,15 +73,15 @@
|
|||
</script>
|
||||
|
||||
<!-- SEO -->
|
||||
<svelte:head>
|
||||
<!-- <svelte:head>
|
||||
<title>{meta.title}</title>
|
||||
<!-- Meta Tags -->
|
||||
Meta Tags
|
||||
<meta name="title" content={meta.title} />
|
||||
<meta name="description" content={meta.description} />
|
||||
<meta name="keywords" content="krása, kosmetika, permanentní makeup, revitalizace pleti, oprava pleti, salón, kosmetička, kosmetický salón, Písek, obočí, vytrhání, natočení řas, řasy" />
|
||||
<meta name="theme-color" content="#242c46" />
|
||||
<meta name="author" content="Klára Morinová" />
|
||||
<!-- Open Graph - https://ogp.me/ -->
|
||||
Open Graph - https://ogp.me/
|
||||
<meta property="og:site_name" content="BeautySalon" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://www.beautysalon.cz{$page.url.pathname}" />
|
||||
|
@ -84,12 +94,12 @@
|
|||
<meta property="og:image:width" content="1707" />
|
||||
<meta property="og:image:height" content="1233" />
|
||||
|
||||
<!-- Open Graph: Twitter -->
|
||||
Open Graph: Twitter
|
||||
<meta name="twitter:title" content={meta.twitter.title} />
|
||||
<meta name="twitter:description" content={meta.twitter.description} />
|
||||
<meta name="twitter:image" content={meta.twitter.image} />
|
||||
</svelte:head>
|
||||
|
||||
</svelte:head> -->
|
||||
<SEO {seoData}/>
|
||||
<!-- <Analytics /> -->
|
||||
<!-- App Shell -->
|
||||
<Drawer />
|
||||
|
|
Loading…
Reference in New Issue