Link

Overriding Individual Meta Properties

This tutorial was contributed by Deo Kumar

Most common requirements for SEO optimization are handled by @quintype/seo. However, it is possible to override parts of the behavior.

Adding custom metadata

The custom metadata SEO logic can be added by passing the customSeo object in data of in _loadData() function in load-data.js file.

import { getCustomSeoMetadata } from "../../../../server/data-loaders/custom-seo";

return _loadData().then((data) => {
  return {
    httpStatusCode: data.httpStatusCode || 200,
    pageType: data.pageType || pageType,
    data: Object.assign({}, data, {
      navigationMenu: getNavigationMenuArray(config.layout.menu),
      customSeo: getCustomSeoMetadata(data, pageType),
    }),
    config: pick(config.asJson(), WHITELIST_CONFIG_KEYS),
  };
});

Where getCustomSeoMetadata(data, pageType) function which will take 2 args data and pageType and will return the list of all custom SEO related fields like title, description, page-title, keywords, canonicalUrl, ogUrl, ogTitle, ogDescription, twitterTitle, twitterDescription, keywords. Make sure that the keywords should be in form of string with comma separated. ex- ‘opinion, sports, videos, myjournal’.

ex - Let’s see the example of overriding section page SEO data.

function getCustomSeoMetadata(data, pageType) {
  switch (pageType) {
    case "section-page":
      return {
        title: data.collection.name + " || My Journal ",
        description: "Custom description",
        ogTitle: "og custom title",
        ogDescription: "og custom description",
        keywords: ['opinion', 'sports', 'videos', 'malibu']
      };
    default:
      break;
  }
}

The above function will override section page custom SEO data with title, description, ogTilte, ogDescription, and keywords. if you want to override the SEO for other pages then, you have to add a switch case in the above function return custom SEO data in form of object.

For an infinite story page, you need to add customSeo in storyPageLoadItems() function of <InfiniteStoryBase /> to update the custom SEO for all the stories appearing in the infinite scroll.

Before customSeo

function storyPageLoadItems(pageNumber) {
  return global
    .wretch("/api/v1/stories")
    .query({
      fields: FIELDS,
      limit: 5,
      offset: 5 * pageNumber,
    })
    .get()
    .json((response) =>
      response.stories.map((story) => ({ story, otherProp: "value" }))
    );
}

export function StoryPage(props) {
  return (
    <InfiniteStoryBase
      {...props}
      render={StoryPageBase}
      loadItems={storyPageLoadItems}
      onInitialItemFocus={(item) =>
        app.registerPageView(
          { pageType: "story-page", data: { story: item.story } },
          `/${item.story.slug}`
        )
      }
      onItemFocus={(item) =>
        console.log(`Story In View: ${item.story.headline}`)
      }
    />
  );
}

After adding customSeo

function storyPageLoadItems(pageNumber) {
  return global
    .wretch("/api/v1/stories")
    .query({
      fields: FIELDS,
      limit: 5,
      offset: 5 * pageNumber,
    })
    .get()
    .json((response) =>
      response.stories.map((story) => ({
        story,
        otherProp: "value",
        customSeo: getCustomSeoMetadata(story, "story-page"),
      }))
    );
}

export function StoryPage(props) {
  return (
    <InfiniteStoryBase
      {...props}
      render={StoryPageBase}
      loadItems={storyPageLoadItems}
      onInitialItemFocus={(item) =>
        app.registerPageView(
          {
            pageType: "story-page",
            data: {
              story: item.story,
              customSeo: getCustomSeoMetadata(item.story, "story-page"),
            },
          },
          `/${item.story.slug}`
        )
      }
      onItemFocus={(item) =>
        console.log(`Story In View: ${item.story.headline}`)
      }
    />
  );
}

You may now proceed to Loading Fonts or jump to a recipe from the Tutorial.