Skip to content

Commit

Permalink
Change the API
Browse files Browse the repository at this point in the history
  • Loading branch information
blittle committed Apr 4, 2024
1 parent b7dde04 commit 954b520
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 211 deletions.
42 changes: 24 additions & 18 deletions .changeset/tiny-sheep-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,31 +70,37 @@ If your root route loader also returns an `seo` property, make sure to merge tha

```ts
export const meta = ({data, matches}) => {
return getSeoMeta({
...args.matches[0].data.seo,
return getSeoMeta(
args.matches[0].data.seo,
// the current route seo data overrides the root route data
...data.seo,
});
data.seo,
);
};
```

Or more simply:

```ts
export const meta = ({data, matches}) => {
return getSeoMeta(...matches.map((match) => match.data.seo));
};
```

**4. Override meta**

Sometimes `getSeoMeta` might produce a property in a way you'd like to change. Override any property by passing a second array:
Sometimes `getSeoMeta` might produce a property in a way you'd like to change. Map over the resulting array to change it. For example, Hydrogen removes query parameters from canonical URLs, add them back:

```ts
export const meta = ({data}) => {
return getSeoMeta(
data.seo,
// these override meta
() => {
return [{title: data.project.name}];
},

// these append meta
() => {
return [{name: 'author', content: 'Hydrogen'}];
},
);
export const meta = ({data, location}) => {
return getSeoMeta(data.seo).map((meta) => {
if (meta.rel === 'canonical') {
return {
...meta,
href: meta.href + location.search,
};
}

return meta;
});
};
```
98 changes: 63 additions & 35 deletions packages/hydrogen/docs/generated/generated_docs_data.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/hydrogen/src/seo/generate-seo-tags.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ describe('generateSeoTags', () => {
// Given
const input = {
jsonLd: {},
} as SeoConfig<Thing>;
} as SeoConfig;

// When
const output = generateSeoTags(input);
Expand All @@ -800,7 +800,7 @@ describe('generateSeoTags', () => {
],
url: 'http://localhost:3000/products/the-full-stack',
},
} satisfies SeoConfig<Organization>;
} satisfies SeoConfig;

// When
const output = generateSeoTags(input);
Expand Down Expand Up @@ -845,7 +845,7 @@ describe('generateSeoTags', () => {
],
},
},
} satisfies SeoConfig<Product>;
} satisfies SeoConfig;

// When
const output = generateSeoTags(input);
Expand Down Expand Up @@ -907,7 +907,7 @@ describe('generateSeoTags', () => {
},
},
],
} satisfies SeoConfig<Organization | Product>;
} satisfies SeoConfig;

// When
const output = generateSeoTags(input);
Expand Down
13 changes: 6 additions & 7 deletions packages/hydrogen/src/seo/generate-seo-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ export const schema = {
},
};

export interface SeoConfig<Schema extends Thing = Thing> {
export interface SeoConfig {
/**
* The <title> HTML element defines the document's title that is shown in a browser's title bar or a page's tab. It
* The `title` HTML element defines the document's title that is shown in a browser's title bar or a page's tab. It
* only contains text; tags within the element are ignored.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title
Expand Down Expand Up @@ -159,6 +159,8 @@ export interface SeoConfig<Schema extends Thing = Thing> {
* - `BlogPosting`
* - `Thing`
*
* The value is validated via [schema-dts](https://www.npmjs.com/package/schema-dts)
*
* @example
* ```js
* {
Expand Down Expand Up @@ -200,7 +202,7 @@ export interface SeoConfig<Schema extends Thing = Thing> {
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script
*
*/
jsonLd?: WithContext<Schema> | WithContext<Schema>[];
jsonLd?: WithContext<Thing> | WithContext<Thing>[];
/**
* The `alternates` property is used to specify the language and geographical targeting when you have multiple
* versions of the same page in different languages. The `url` property tells search engines about these variations
Expand Down Expand Up @@ -354,10 +356,7 @@ export interface CustomHeadTagObject {
* pairs well with the SEO component in `@shopify/hydrogen` when building a Hydrogen Remix app, but can be used on its
* own if you want to generate the tags yourself.
*/
export function generateSeoTags<
Schema extends Thing,
T extends SeoConfig<Schema> = SeoConfig<Schema>,
>(seoInput: T): CustomHeadTagObject[] {
export function generateSeoTags(seoInput: SeoConfig): CustomHeadTagObject[] {
const tagResults: CustomHeadTagObject[] = [];

for (const seoKey of Object.keys(seoInput)) {
Expand Down
2 changes: 1 addition & 1 deletion packages/hydrogen/src/seo/getSeoMeta.doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const data: ReferenceEntityTemplateSchema = {
category: 'utilities',
isVisualComponent: false,
related: [],
description: `Generate a Remix meta array based on the seo property used by the \`Seo\` component. Use it to help generate SEO return data from your meta funcitons. Learn more about [how SEO works in Hydrogen](https://shopify.dev/docs/custom-storefronts/hydrogen/seo).`,
description: `Generate a [Remix meta array](https://remix.run/docs/en/main/route/meta) from one or more SEO configuration objects. Pass SEO configuration for the parent route(s) and the current route to preserve meta data for all active routes. Similar to [\`Object.assign()\`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), each property is overwritten based on the object order. The exception is \`jsonLd\`, which is preserved so that each route has it's own independent jsonLd meta data. Learn more about [how SEO works in Hydrogen](https://shopify.dev/docs/custom-storefronts/hydrogen/seo).`,
type: 'utility',
defaultExample: {
description: 'I am the default example',
Expand Down
16 changes: 3 additions & 13 deletions packages/hydrogen/src/seo/getSeoMeta.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,7 @@ export async function loader({context}) {
};
}

export const meta = ({data}) => {
return getSeoMeta(
data.seo,
// these override meta
() => {
return [{title: 'Custom title'}];
},

// these append meta
() => {
return [{name: 'author', content: 'Hydrogen'}];
},
);
export const meta = ({data, matches}) => {
// Pass one or more arguments, preserving properties from parent routes
return getSeoMeta(matches[0].data.seo, data.seo);
};
19 changes: 3 additions & 16 deletions packages/hydrogen/src/seo/getSeoMeta.example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,7 @@ export async function loader({context}: LoaderFunctionArgs) {
};
}

// Instead of rendering the `<Seo />` component in root.tsx
// call `getSeoMeta` from within meta in each route that has
// an `seo` prop returned from the loader.
export const meta: MetaFunction<typeof loader> = ({data}) => {
return getSeoMeta(
data!.seo,
// these override meta
() => {
return [{title: 'Custom title'}];
},

// these append meta
() => {
return [{name: 'author', content: 'Hydrogen'}];
},
);
export const meta: MetaFunction<typeof loader> = ({data, matches}) => {
// Pass one or more arguments, preserving properties from parent routes
return getSeoMeta((matches as any).data.seo, data!.seo);
};
Loading

0 comments on commit 954b520

Please sign in to comment.