Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/oekazuma/svelte-meta-tags

Svelte Meta Tags provides components designed to help you manage SEO for Svelte projects.
https://github.com/oekazuma/svelte-meta-tags

metadata metatags seo svelte sveltekit

Last synced: 7 days ago
JSON representation

Svelte Meta Tags provides components designed to help you manage SEO for Svelte projects.

Awesome Lists containing this project

README

        

svelte-meta-tags

[![CI](https://github.com/oekazuma/svelte-meta-tags/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/oekazuma/svelte-meta-tags/actions/workflows/ci.yml)
[![download](https://img.shields.io/npm/dt/svelte-meta-tags.svg)](https://www.npmjs.com/package/svelte-meta-tags)
[![npm](https://img.shields.io/npm/v/svelte-meta-tags)](https://www.npmjs.com/package/svelte-meta-tags)
[![MIT](https://img.shields.io/npm/l/svelte-meta-tags)](https://opensource.org/licenses/MIT)

Svelte Meta Tags provides components designed to help you manage SEO for Svelte projects.

[Demo](https://svelte.dev/repl/ffd783c9b8e54d97b6b7cac6eadace42)

**Note: If you are migrating from v3 to v4, [Please Read Migration Guide](https://github.com/oekazuma/svelte-meta-tags/issues/1015)**

**Table of Contents**

- [Installing](#-installing)
- [Usage](#-usage)
- [MetaTags Properties](#metatags-properties)
- [Title Template](#title-template)
- [Twitter](#twitter)
- [Facebook](#facebook)
- [additionalRobotsProps](#additionalRobotsProps)
- [Alternate](#alternate)
- [Additional Meta Tags](#additional-meta-tags)
- [Additional Link Tags](#additional-link-tags)
- [Open Graph](#open-graph)
- [Open Graph Examples](#open-graph-examples)
- [Basic](#basic)
- [Video](#video)
- [Article](#article)
- [Book](#book)
- [Profile](#profile)
- [JSON-LD](#json-ld)
- [Using schema-dts](#using-schema-dts)
- [JSON-LD Properties](#json-ld-properties)
- [JSON-LD Examples](#json-ld-examples)
- [Article](#article)
- [Breadcrumb](#breadcrumb)
- [Product](#product)
- [Course](#course)
- [DataSet](#dataset)
- [FAQ](#faq)
- [JSON-LD Multiple Examples](#json-ld-multiple-examples)
- [Types](#types)
- [Additional types](#additional-types)

### πŸ“¦ Installing

```shell
npm install -D svelte-meta-tags
```

or

```shell
yarn add -D svelte-meta-tags
```

or

```shell
pnpm add -D svelte-meta-tags
```

### πŸš€ Usage

**Example with just title and description:**

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

**Typical page example:**

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

**Overwriting default values with a child page:**

[Example](https://github.com/oekazuma/svelte-meta-tags/tree/main/example)

`+layout.svelte`

```svelte

import { page } from '$app/stores';
import { MetaTags, deepMerge } from 'svelte-meta-tags';

let { data, children } = $props();

let metaTags = $derived(deepMerge(data.baseMetaTags, $page.data.pageMetaTags));

{@render children()}
```

`+layout.ts`

```ts
import type { MetaTagsProps } from 'svelte-meta-tags';

export const load = ({ url }) => {
const baseMetaTags = Object.freeze({
title: 'Default',
titleTemplate: '%s | Svelte Meta Tags',
description: 'Svelte Meta Tags is a Svelte component for managing meta tags and SEO in your Svelte applications.',
canonical: new URL(url.pathname, url.origin).href,
openGraph: {
type: 'website',
url: new URL(url.pathname, url.origin).href,
locale: 'en_IE',
title: 'Open Graph Title',
description: 'Open Graph Description',
siteName: 'SiteName',
images: [
{
url: 'https://www.example.ie/og-image.jpg',
alt: 'Og Image Alt',
width: 800,
height: 600,
secureUrl: 'https://www.example.ie/og-image.jpg',
type: 'image/jpeg'
}
]
}
}) satisfies MetaTagsProps;

return {
baseMetaTags
};
};
```

`+page.ts`

```ts
import type { MetaTagsProps } from 'svelte-meta-tags';

export const load = () => {
const pageMetaTags = Object.freeze({
title: 'TOP',
description: 'Description TOP',
openGraph: {
title: 'Open Graph Title TOP',
description: 'Open Graph Description TOP'
}
}) satisfies MetaTagsProps;

return {
pageMetaTags
};
};
```

### MetaTags Properties

| Property | Type | Description |
| ---------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title` | string | Sets the meta title of the page |
| `titleTemplate` | string | Allows you to set the default title template that will be added to your title [More Info](#title-template) |
| `robots` | string or boolean (default `index,follow`) | Sets the meta robots of the page ⚠ You can disable it completely by setting it to false, but use it with caution as there is a risk that the page will not be indexed⚠ |
| `additionRobotsProps` | Object | Set the additional meta information for the `X-Robots-Tag` [More Info](#additionalRobotsProps) |
| `description` | string | Sets the meta description of the page |
| `canonical` | string | Make the page canonical URL |
| `keywords` | array | Sets the meta keywords of the page |
| `mobileAlternate.media` | string | Set the screen size from which the mobile site will be served |
| `mobileAlternate.href` | string | Set the alternate URL for the mobile page |
| `languageAlternates` | array | Set the language of the alternate urls. Expects array of objects with the shape: `{ hrefLang: string, href: string }` |
| `additionalMetaTags` | array | Allows you to add a meta tag that is not documented here [More Info](#additional-meta-tags) |
| `additionalLinkTags` | array | Allows you to add a link tag that is not documented here [More Info](#additional-link-tags) |
| `twitter.cardType` | string | The card type, which will be one of `summary`, `summary_large_image`, `app`, or `player` |
| `twitter.site` | string | @username for the website used in the card footer |
| `twitter.creator` | string | @username for the creator of the content (output as `twitter:creator`) |
| `twitter.title` | string | The concise title for the related content |
| `twitter.description` | string | The description that concisely summarizes the content in a manner suitable for presentation within a Tweet. You should not reuse the title as the description or use this field to describe the general services provided by the website |
| `twitter.image` | string | The URL to a unique image that represents the content of the page. You should not use a generic image such as your site logo, author photo, or other image that spans multiple pages. Images for this card support a 1:1 aspect ratio with a minimum size of 144x144 pixels or a maximum size of 4096x4096 pixels. Images must be less than 5MB in size. The image will be cropped to a square on all platforms. JPG, PNG, WEBP, and GIF formats are supported. Only the first frame of an animated GIF is used. SVG is not supported |
| `twitter.imageAlt` | string | The textual description of the image that conveys the essence of the image to visually impaired users. Maximum 420 characters |
| `twitter.player` | string | HTTPS URL of a video player for this content |
| `twitter.playerWidth` | number | Width of the player in pixels |
| `twitter.playerHeight` | number | Height of the player in pixels |
| `twitter.playerStream` | string | URL to raw video or audio stream |
| `twitter.appNameIPhone` | string | Name of your iPhone app |
| `twitter.appIdIPhone` | string | Your iPhone app ID |
| `twitter.appUrlIPhone` | string | Your iPhone app URL |
| `twitter.appNameIPad` | string | Name of your iPad app |
| `twitter.appIdIPad` | string | Your iPad app ID |
| `twitter.appUrlIPad` | string | Your iPad app URL |
| `twitter.appNameGooglePlay` | string | Name of your Android app |
| `twitter.appIdGooglePlay` | string | Your Android app ID |
| `twitter.appUrlGooglePlay` | string | Your Android app URL |
| `facebook.appId` | string | For Facebook Insights, you will need to add a Facebook app ID to your page in order to use it |
| `openGraph.url` | string | The canonical URL of your object, which will be used as its permanent ID in the graph |
| `openGraph.type` | string | The type of your object. Depending on the type you specify, other properties may also be required [More Info](#open-graph) |
| `openGraph.title` | string | The open graph title, this can be different from your meta title |
| `openGraph.description` | string | The open graph description, which may be different from your meta description |
| `openGraph.images` | array | An array of images to use as previews. If multiple are provided, you can choose one when sharing [See Examples](#open-graph-examples) |
| `openGraph.videos` | array | An array of videos (object) |
| `openGraph.audio` | array | An array of audio(object) |
| `openGraph.locale` | string | The locale in which the open graph tags are highlighted |
| `openGraph.siteName` | string | If your item is part of a larger website, the name that should be displayed for the entire site |
| `openGraph.profile.firstName` | string | Person's first name |
| `openGraph.profile.lastName` | string | Person's last name |
| `openGraph.profile.username` | string | Person's username |
| `openGraph.profile.gender` | string | Person's gender |
| `openGraph.book.authors` | string[] | Author of the article [See Examples](#open-graph-examples) |
| `openGraph.book.isbn` | string | The [ISBN](https://en.wikipedia.org/wiki/International_Standard_Book_Number) |
| `openGraph.book.releaseDate` | datetime | The date the book was released |
| `openGraph.book.tags` | string[] | Tag words related to this book |
| `openGraph.article.publishedTime` | datetime | When the article was first published [See Examples](#open-graph-examples) |
| `openGraph.article.modifiedTime` | datetime | When the item was last modified |
| `openGraph.article.expirationTime` | datetime | When the article is out of date after |
| `openGraph.article.authors` | string[] | Author of the article |
| `openGraph.article.section` | string | A high-level section name. E.g. Technology |
| `openGraph.article.tags` | string[] | Tag words associated with this article |

#### Title Template

Replace `%s` with your title string.

```
title = 'This is my title'
titleTemplate = 'Svelte Meta Tags | %s'
// outputs: Svelte Meta Tags | This is my title
```

```
title = 'This is my title'
titleTemplate = '%s | Svelte Meta Tags'
// outputs: This is my title | Svelte Meta Tags
```

#### Twitter

```js
twitter={{
creator: '@handle',
site: '@site',
cardType: 'summary_large_image',
title: 'Twitter',
description: 'Twitter',
image: 'https://www.example.ie/twitter-image.jpg',
imageAlt: 'Twitter image alt'
}}
```

See out the Twitter [documentation](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary) for more information.

#### Facebook

```js
facebook={{
appId: '1234567890',
}}
```

Add this to your SEO config to include the fb:app_id meta if you need to enable Facebook Insights for your site. Information on this can be found in Facebook's [documentation](https://developers.facebook.com/docs/sharing/webmasters/).

#### additionalRobotsProps

In addition to `index, follow` the `robots` meta tag accepts more properties to archive a more accurate crawling and serve better snippets for SEO bots that crawl your page.

Example:

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

**Available properties**

| Property | Type | Description |
| ------------------ | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `noarchive` | boolean | Do not display a [cached link](https://support.google.com/websearch/answer/1687222) in search results |
| `nosnippet` | boolean | Do not show a text snippet or video preview in the search results for this page |
| `maxSnippet` | number | Use a maximum of [number] characters as the text snippet for this search result [Read more](https://developers.google.com/search/reference/robots_meta_tag?hl=en-GB#directives) |
| `maxImagePreview` | 'none','standard','large' | Set the maximum size of an image preview for this page in a search result |
| `maxVideoPreview` | number | Use a maximum of [number] seconds as a video snippet for videos on this page in search results [Read more](https://developers.google.com/search/reference/robots_meta_tag?hl=en-GB#directives) |
| `notranslate` | boolean | Do not offer translation of this page in search results |
| `noimageindex` | boolean | Do not index images on this page |
| `unavailableAfter` | string | Do not show this page in search results after the specified date/time. The date/time must be in a widely accepted format, including but not limited to RFC 822, RFC 850, and ISO 8601 |

For more information on the `X-Robots-Tag` visit [Google Search Central - Control Crawling and Indexing](https://developers.google.com/search/reference/robots_meta_tag?hl=en-GB#directives)

#### Alternate

This link relationship is used to indicate a relationship between a desktop and mobile website to search engines.

Example:

```js
mobileAlternate={{
media: 'only screen and (max-width: 640px)',
href: 'https://m.canonical.ie'
}}
```

```js
languageAlternates={[
{
hrefLang: 'de-AT',
href: 'https://www.canonical.ie/de'
}
]}
```

#### Additional Meta Tags

This allows you to add any other meta tags that are not required by the `config`.

`content` is required. Then either `name`, `property` or `httpEquiv`. (only one of each)

Example:

```js
additionalMetaTags={[
{
property: 'dc:creator',
content: 'Jane Doe'
},
{
name: 'application-name',
content: 'Svelte-Meta-Tags'
},
{
httpEquiv: 'x-ua-compatible',
content: 'IE=edge; chrome=1'
}
]}
```

Invalid Examples:

These are invalid because they contain more than one of `name`, `property`, and `httpEquiv` in the same entry.

```js
additionalMetaTags={[
{
property: 'dc:creator',
name: 'dc:creator',
content: 'Jane Doe'
},
{
property: 'application-name',
httpEquiv: 'application-name',
content: 'Svelte-Meta-Tags'
}
]}
```

One thing to note on this is that it currently only supports unique tags.
This means it will only render one tag per unique `name` / `property` / `httpEquiv`. The last one defined will be rendered.

Example:

If you pass:

```js
additionalMetaTags={[
{
property: 'dc:creator',
content: 'John Doe'
},
{
property: 'dc:creator',
content: 'Jane Doe'
}
]}
```

it will result in this being rendered:

```html
,
```

#### Additional Link Tags

This allows you to add any other link tags that are not covered in the `config`.

`rel` and `href` is required.

Example:

```js
additionalLinkTags={[
{
rel: 'icon',
href: 'https://www.test.ie/favicon.ico'
},
{
rel: 'apple-touch-icon',
href: 'https://www.test.ie/touch-icon-ipad.jpg',
sizes: '76x76'
},
{
rel: 'manifest',
href: 'https://www.test.ie/manifest.json'
}
]}
```

it will result in this being rendered:

```html

```

## Open Graph

The full specification can be found at .

Svelte Meta Tags currently supports:

- [Basic](#basic)
- [Video](#video)
- [Article](#article)
- [Book](#book)
- [Profile](#profile)

### Open Graph Examples

#### Basic

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

#### Video

Full info on [http://ogp.me/](http://ogp.me/#type_video)

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

#### Article

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

#### Book

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

#### Profile

```svelte

import { MetaTags } from 'svelte-meta-tags';

```

## JSON-LD

JSON-LD allows for more customized and richer display, such as in search results.

To discover all the different content types that JSON-LD offers, go to: https://developers.google.com/search/docs/guides/search-gallery

Tips: If you want to handle multiple JSON-LDs on one page, pass an array to the `schema`.

### Using `schema-dts`

This plugin uses [schema-dts](https://github.com/google/schema-dts), so it provides other types than the examples below.

### JSON-LD Properties

| Property | Type | Description |
| -------- | --------------------- | -------------------------------------------------------------------------------------------------------- |
| `output` | string (default head) | Specifies whether to output json-ld in `` or ``. Possible values are either `head` or `body` |
| `schema` | Object | Data in `ld+json` format [See Examples](#json-ld-examples) |

### JSON-LD Examples

#### Article

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

#### Breadcrumb

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

#### Product

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

#### Course

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

#### DataSet

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

#### FAQ

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

### JSON-LD Multiple Examples

```svelte

import { JsonLd } from 'svelte-meta-tags';

```

## Deep Merge function

Provides a function to deeply merge the enumerable properties of two or more objects.

Use this when you want to override the default values on child pages, as in the following example.

`+layout.svelte`

```svelte

import { page } from '$app/stores';
import { MetaTags, deepMerge } from 'svelte-meta-tags';

let { data, children } = $props();

let metaTags = $derived(deepMerge(data.baseMetaTags, $page.data.pageMetaTags));

{@render children()}
```

`+layout.ts`

```ts
import type { MetaTagsProps } from 'svelte-meta-tags';

export const load = ({ url }) => {
const baseMetaTags = Object.freeze({
title: 'Default',
titleTemplate: '%s | Svelte Meta Tags',
description: 'Svelte Meta Tags is a Svelte component for managing meta tags and SEO in your Svelte applications.',
canonical: new URL(url.pathname, url.origin).href,
openGraph: {
type: 'website',
url: new URL(url.pathname, url.origin).href,
locale: 'en_IE',
title: 'Open Graph Title',
description: 'Open Graph Description',
siteName: 'SiteName',
images: [
{
url: 'https://www.example.ie/og-image.jpg',
alt: 'Og Image Alt',
width: 800,
height: 600,
secureUrl: 'https://www.example.ie/og-image.jpg',
type: 'image/jpeg'
}
]
}
}) satisfies MetaTagsProps;

return {
baseMetaTags
};
};
```

`+page.ts`

```ts
import type { MetaTagsProps } from 'svelte-meta-tags';

export const load = () => {
const pageMetaTags = Object.freeze({
title: 'TOP',
description: 'Description TOP',
openGraph: {
title: 'Open Graph Title TOP',
description: 'Open Graph Description TOP'
}
}) satisfies MetaTagsProps;

return {
pageMetaTags
};
};
```

## Types

The following types can be imported from `svelte-meta-tags`

### MetaTagsProps

```ts
interface MetaTagsProps {
title?: string;
titleTemplate?: string;
robots?: string | boolean;
additionalRobotsProps?: AdditionalRobotsProps;
description?: string;
canonical?: string;
mobileAlternate?: MobileAlternate;
languageAlternates?: ReadonlyArray;
twitter?: Twitter;
facebook?: Facebook;
openGraph?: OpenGraph;
additionalMetaTags?: ReadonlyArray;
additionalLinkTags?: ReadonlyArray;
}
```

### JsonLdProps

```ts
interface JsonLdProps {
output?: 'head' | 'body';
schema?: Thing | WithContext | Thing[] | WithContext[];
}
```

### AdditionalRobotsProps

```ts
interface AdditionalRobotsProps {
nosnippet?: boolean;
maxSnippet?: number;
maxImagePreview?: 'none' | 'standard' | 'large';
maxVideoPreview?: number;
noarchive?: boolean;
unavailableAfter?: string;
noimageindex?: boolean;
notranslate?: boolean;
}
```

### MobileAlternate

```ts
interface MobileAlternate {
media: string;
href: string;
}
```

### LanguageAlternate

```ts
interface LanguageAlternate {
hrefLang: string;
href: string;
}
```

### Twitter

```ts
interface Twitter {
cardType?: 'summary' | 'summary_large_image' | 'app' | 'player';
site?: string;
creator?: string;
title?: string;
description?: string;
image?: string;
imageAlt?: string;
}
```

### Facebook

```ts
interface Facebook {
appId?: string;
}
```

### OpenGraph

```ts
interface OpenGraph {
url?: string;
type?: string;
title?: string;
description?: string;
images?: ReadonlyArray;
videos?: ReadonlyArray;
audio?: ReadonlyArray;
locale?: string;
siteName?: string;
profile?: OpenGraphProfile;
book?: OpenGraphBook;
article?: OpenGraphArticle;
video?: OpenGraphVideo;
}
```

### MetaTag

```ts
type MetaTag = HTML5MetaTag | RDFaMetaTag | HTTPEquivMetaTag;
```

### LinkTag

```ts
interface LinkTag {
rel: string;
href: string;
hrefLang?: string;
media?: string;
sizes?: string;
type?: string;
color?: string;
as?:
| 'fetch'
| 'audio'
| 'audioworklet'
| 'document'
| 'embed'
| 'font'
| 'frame'
| 'iframe'
| 'image'
| 'json'
| 'manifest'
| 'object'
| 'paintworklet'
| 'report'
| 'script'
| 'serviceworker'
| 'sharedworker'
| 'style'
| 'track'
| 'video'
| 'webidentity'
| 'worker'
| 'xslt'
| '';
crossOrigin?: string;
referrerPolicy?: string;
}
```

## Additional types

The following are referenced by the public types documented above, but cannot be imported directly

### OpenGraphImage

```ts
interface OpenGraphImage {
url: string;
secureUrl?: string;
type?: string;
width?: number;
height?: number;
alt?: string;
}
```

### OpenGraphVideos

```ts
interface OpenGraphVideos {
url: string;
secureUrl?: string;
type?: string;
width?: number;
height?: number;
}
```

### OpenGraphAudio

```ts
interface OpenGraphAudio {
url: string;
secureUrl?: string;
type?: string;
}
```

### OpenGraphProfile

```ts
interface OpenGraphProfile {
firstName?: string;
lastName?: string;
username?: string;
gender?: string;
}
```

### OpenGraphBook

```ts
interface OpenGraphBook {
authors?: ReadonlyArray;
isbn?: string;
releaseDate?: string;
tags?: ReadonlyArray;
}
```

### OpenGraphArticle

```ts
interface OpenGraphArticle {
publishedTime?: string;
modifiedTime?: string;
expirationTime?: string;
authors?: ReadonlyArray;
section?: string;
tags?: ReadonlyArray;
}
```

### OpenGraphVideo

```ts
interface OpenGraphVideo {
actors?: ReadonlyArray;
directors?: ReadonlyArray;
writers?: ReadonlyArray;
duration?: number;
releaseDate?: string;
tags?: ReadonlyArray;
series?: string;
}
```

### OpenGraphVideoActors

```ts
interface OpenGraphVideoActors {
profile: string;
role?: string;
}
```

### BaseMetaTag

```ts
interface BaseMetaTag {
content: string;
}
```

### HTML5MetaTag

```ts
interface HTML5MetaTag extends BaseMetaTag {
name: string;
property?: undefined;
httpEquiv?: undefined;
}
```

### RDFaMetaTag

```ts
interface RDFaMetaTag extends BaseMetaTag {
property: string;
name?: undefined;
httpEquiv?: undefined;
}
```

### HTTPEquivMetaTag

```ts
interface HTTPEquivMetaTag extends BaseMetaTag {
httpEquiv: 'content-security-policy' | 'content-type' | 'default-style' | 'x-ua-compatible' | 'refresh';
name?: undefined;
property?: undefined;
}
```

## License

MIT