Merge pull request #229 from reuters-graphics/mf-seo

Updates SEO
This commit is contained in:
MinamiFunakoshiTR 2025-03-12 11:25:49 -05:00 committed by GitHub
commit bf2bcaed1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 116 additions and 143 deletions

View file

@ -0,0 +1,80 @@
import { Meta, Canvas } from '@storybook/blocks';
import * as SEOStories from './SEO.stories.svelte';
<Meta of={SEOStories} />
# SEO
The `SEO` component adds essential metadata to pages.
```svelte
<script>
import { SEO } from '@reuters-graphics/graphics-components';
</script>
<SEO
baseUrl="https://www.reuters.com/graphics/world-coronavirus-tracker-and-maps"
pageUrl={new URL(
'https://www.reuters.com/graphics/world-coronavirus-tracker-and-maps/countries/united-kingdom/'
)}
seoTitle="A title for Google"
seoDescription="A description for Google"
shareTitle="A title for Twitter/Facebook"
shareDescription="A description for Twitter/Facebook"
shareImgPath="https://www.reuters.com/graphics/world-coronavirus-tracker-and-maps/assets/images/share.jpg"
shareImgAlt="An image showing global COVID infection rates"
publishTime="2020-09-15T00:00:00.000Z"
updateTime="2021-01-10T12:30:00.000Z"
authors={[
{ name: 'Jane Doe', link: 'https://www.reuters.com/authors/jane-doe/' },
{ name: 'John Doe', link: 'https://www.reuters.com/authors/john-doe/' },
]}
/>
```
## Using with ArchieML docs
With the Graphics Kit, you'll likely get many of your text values from an ArchieML doc...
```yaml
# ArchieML doc
slug: ROOT-SLUG/WILD
seoTitle: Page title for search
seoDescription: Page description for search
shareTitle: Page title for social media
shareDescription: Page description for social media
shareImgPath: images/reuters-graphics.jpg
shareImgAlt: Alt text for share image.
```
... which you'll pass to the `SEO` component.
```svelte
<script>
import { SEO } from '@reuters-graphics/graphics-components';
import pkg from '$pkg';
import content from '$locales/en/content.json';
import { assets } from '$app/paths';
import { page } from '$app/stores';
</script>
<SEO
baseUrl={VITE_BASE_URL}
pageUrl={$page.url}
seoTitle={content.seoTitle}
seoDescription={content.seoDescription}
shareTitle={content.shareTitle}
shareDescription={content.shareDescription}
shareImgPath={`${assets}/${content.shareImgPath}`}
shareImgAlt={content.shareImgAlt}
publishTime={pkg?.reuters?.graphic?.published}
updateTime={pkg?.reuters?.graphic?.updated}
authors={pkg?.reuters?.graphic?.authors}
/>
```
> **Note:** For _reasons_, we can't document the value of `VITE_BASE_URL` below. It's `import` + `.meta.env.BASE_URL` (concatenate all that) in the Graphics Kit and other Vite-based rigs.
<Canvas of={SEOStories.Demo} />
```

View file

@ -1,49 +1,23 @@
<script module lang="ts"> <script module lang="ts">
// @ts-ignore raw import { defineMeta } from '@storybook/addon-svelte-csf';
import componentDocs from './stories/docs/component.md?raw';
// @ts-ignore raw
import archieMLDocs from './stories/docs/archieML.md?raw';
import SEO from './SEO.svelte'; import SEO from './SEO.svelte';
import { const { Story } = defineMeta({
withComponentDocs,
withStoryDocs,
} from '$lib/docs/utils/withParams.js';
export const meta = {
title: 'Components/Ads & analytics/SEO', title: 'Components/Ads & analytics/SEO',
component: SEO, component: SEO,
...withComponentDocs(componentDocs), });
};
</script> </script>
<script> <div>View page source to see the SEO metadata.</div>
import { Template, Story } from '@storybook/addon-svelte-csf';
</script>
<Template >
{#snippet children({ args })}
<SEO {...args} />
<div>Nothing to see here. 😎</div>
{/snippet}
</Template>
<Story <Story
name="Default" name="Demo"
args="{{ args={{
baseUrl: 'https://graphics.reuters.com', baseUrl: 'https://www.reuters.com',
pageUrl: new URL('https://graphics.reuters.com/hello-world/'), seoTitle: 'A title for Google',
publishTime: new Date('2020-09-15').toISOString(), seoDescription: 'A description for Google',
}}" shareTitle: 'A title for Twitter/Facebook',
/> shareDescription: 'A description for Twitter/Facebook',
shareImgPath:
<Story 'https://www.reuters.com/graphics/world-coronavirus-tracker-and-maps/assets/images/share.jpg',
name="ArchieML" }}
args="{{
baseUrl: 'https://graphics.reuters.com',
pageUrl: new URL('https://graphics.reuters.com/hello-world/'),
publishTime: new Date('2020-09-15').toISOString(),
}}"
{...withStoryDocs(archieMLDocs)}
/> />

View file

@ -2,77 +2,59 @@
<script lang="ts"> <script lang="ts">
interface GraphicAuthor { interface GraphicAuthor {
name: string; name: string;
url: string; link: string;
} }
interface Props { interface Props {
/** /**
* Base url for the page, which in [Vite-based projects](https://vitejs.dev/guide/build.html#public-base-path) * Base url for the page, which in [Vite-based projects](https://vitejs.dev/guide/build.html#public-base-path) is globally available as `import.meta.env.BASE_URL`.
* is globally available as `import.meta.env.BASE_URL`.
* @requiredx
* @type {string}
*/ */
baseUrl?: string; baseUrl: string;
/** /**
* [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) object for the page. * [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) object for the page.
* @required
* @type {URL}
*/ */
pageUrl?: URL | null; pageUrl: URL;
/** /**
* SEO title * SEO title
* @required
* @type {string}
*/ */
seoTitle: string; seoTitle: string;
/** /**
* SEO description * SEO description
* @required
* @type {string}
*/ */
seoDescription: string; seoDescription: string;
/** /**
* Share title * Share title
* @required
* @type {string}
*/ */
shareTitle: string; shareTitle: string;
/** /**
* Share description * Share description
* @required
* @type {string}
*/ */
shareDescription: string; shareDescription: string;
/** /**
* Share image path. **Must be an absolute path.** * Share image path. **Must be an absolute path.**
* @required
* @type {string}
*/ */
shareImgPath: string; shareImgPath: string;
/** /**
* Share image alt text, up to 420 characters. * Share image alt text, up to 420 characters.
* @type {string}
*/ */
shareImgAlt?: string; shareImgAlt?: string;
/** /**
* Publish time as an [ISO string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) * Publish time as an [ISO string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
* @type {string}
*/ */
publishTime?: string; publishTime?: string;
/** /**
* Updated time as an [ISO string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) * Updated time as an [ISO string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
* @type {string}
*/ */
updateTime?: string; updateTime?: string;
/** /**
* Array of authors for the piece. Each author object must have `name` and `url` attributes. * Array of authors for the piece. Each author object must have `name` and `link` attributes.
*/ */
authors?: GraphicAuthor[]; authors?: GraphicAuthor[];
} }
let { let {
baseUrl = '', baseUrl,
pageUrl = null, pageUrl,
seoTitle, seoTitle,
seoDescription, seoDescription,
shareTitle, shareTitle,
@ -83,7 +65,6 @@
updateTime = '', updateTime = '',
authors = [], authors = [],
}: Props = $props(); }: Props = $props();
const getOrigin = (baseUrl: string) => { const getOrigin = (baseUrl: string) => {
try { try {
return new URL(baseUrl).origin; return new URL(baseUrl).origin;
@ -97,7 +78,7 @@
let origin = $derived(getOrigin(baseUrl)); let origin = $derived(getOrigin(baseUrl));
let canonicalUrl = $derived( let canonicalUrl = $derived(
(origin + pageUrl?.pathname).replace(/index\.html\/$/, '') (origin + (pageUrl?.pathname || '')).replace(/index\.html\/$/, '')
); );
const orgLdJson = { const orgLdJson = {
@ -138,10 +119,10 @@
dateCreated: publishTime, dateCreated: publishTime,
datePublished: publishTime, datePublished: publishTime,
dateModified: updateTime, dateModified: updateTime,
author: authors.map(({ name, url }) => ({ author: authors.map(({ name, link }) => ({
'@type': 'Person', '@type': 'Person',
name, name,
url, url: link,
})), })),
creator: authors.map(({ name }) => name), creator: authors.map(({ name }) => name),
articleSection: 'Graphics', articleSection: 'Graphics',
@ -153,8 +134,8 @@
<svelte:head> <svelte:head>
{#key canonicalUrl} {#key canonicalUrl}
<title>{seoTitle}</title> <title>{seoTitle}</title>
<meta name="description" content="{seoDescription}" /> <meta name="description" content={seoDescription} />
<link rel="canonical" href="{canonicalUrl}" /> <link rel="canonical" href={canonicalUrl} />
<link <link
rel="shortcut icon" rel="shortcut icon"
type="image/x-icon" type="image/x-icon"
@ -179,26 +160,26 @@
sizes="96x96" sizes="96x96"
/> />
<meta property="og:url" content="{canonicalUrl}" /> <meta property="og:url" content={canonicalUrl} />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:title" content="{shareTitle}" itemprop="name" /> <meta property="og:title" content={shareTitle} itemprop="name" />
<meta <meta
property="og:description" property="og:description"
content="{shareDescription}" content={shareDescription}
itemprop="description" itemprop="description"
/> />
<meta property="og:image" content="{shareImgPath}" itemprop="image" /> <meta property="og:image" content={shareImgPath} itemprop="image" />
<meta property="og:site_name" content="Reuters" /> <meta property="og:site_name" content="Reuters" />
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@ReutersGraphics" /> <meta name="twitter:site" content="@ReutersGraphics" />
<meta name="twitter:creator" content="@ReutersGraphics" /> <meta name="twitter:creator" content="@ReutersGraphics" />
<meta name="twitter:domain" content="{origin}" /> <meta name="twitter:domain" content={origin} />
<meta name="twitter:title" content="{shareTitle}" /> <meta name="twitter:title" content={shareTitle} />
<meta name="twitter:description" content="{shareDescription}" /> <meta name="twitter:description" content={shareDescription} />
<meta name="twitter:image" content="{shareImgPath}" /> <meta name="twitter:image" content={shareImgPath} />
{#if shareImgAlt} {#if shareImgAlt}
<meta name="twitter:image:alt" content="{shareImgAlt}" /> <meta name="twitter:image:alt" content={shareImgAlt} />
{/if} {/if}
<meta property="fb:app_id" content="319194411438328" /> <meta property="fb:app_id" content="319194411438328" />

View file

@ -1,36 +0,0 @@
```yaml
slug: ROOT-SLUG/WILD
seoTitle: Page title for search
seoDescription: Page description for search
shareTitle: Page title for social media
shareDescription: Page description for social media
shareImgPath: images/reuters-graphics.jpg
shareImgAlt: Alt text for share image.
```
```svelte
<script>
import { SEO } from '@reuters-graphics/graphics-components';
import pkg from '$pkg';
import content from '$locales/en/content.json';
import { assets } from '$app/paths';
import { page } from '$app/stores';
</script>
<SEO
baseUrl="{VITE_BASE_URL}"
pageUrl="{$page.url}"
seoTitle="{content.seoTitle}"
seoDescription="{content.seoDescription}"
shareTitle="{content.shareTitle}"
shareDescription="{content.shareDescription}"
shareImgPath="{`${assets}/${content.shareImgPath}`}"
shareImgAlt="{content.shareImgAlt}"
publishTime="{pkg?.reuters?.graphic?.published}"
updateTime="{pkg?.reuters?.graphic?.updated}"
authors="{pkg?.reuters?.graphic?.authors}"
/>
```
> **Note:** For _reasons_, we can't document the value of `VITE_BASE_URL` below. It's `import` + `.meta.env.BASE_URL` (concatenate all that) in the Graphics Kit and other Vite-based rigs.

View file

@ -1,26 +0,0 @@
The `SEO` component adds essential metadata to published pages.
```svelte
<script>
import { SEO } from '@reuters-graphics/graphics-components';
</script>
<SEO
baseUrl="https://graphics.reuters.com"
pageUrl="{new URL(
'https://graphics.reuters.com/world-coronavirus-tracker-and-maps/'
)}"
seoTitle="A title for Google"
seoDescription="A description for Google"
shareTitle="A title for Twitter/Facebook"
shareDecription="A description for Twitter/Facebook"
shareImgPath="https://graphics.reuters.com/world-coronavirus-tracker-and-maps/assets/images/share.jpg"
shareImgAlt="An image showing global COVID infection rates"
publishTime="2020-09-15T00:00:00.000Z"
updateTime="2021-01-10T12:30:00.000Z"
authors="{[
{ name: 'Jane Doe', url: 'https://twitter.com/JaneDoe' },
{ name: 'John Doe', url: 'https://twitter.com/JohnDoe' },
]}"
/>
```